1 //===-- StopInfo.h ----------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_TARGET_STOPINFO_H 10 #define LLDB_TARGET_STOPINFO_H 11 12 #include <string> 13 14 #include "lldb/Target/Process.h" 15 #include "lldb/Utility/StructuredData.h" 16 #include "lldb/lldb-public.h" 17 18 namespace lldb_private { 19 20 class StopInfo : public std::enable_shared_from_this<StopInfo> { 21 friend class Process::ProcessEventData; 22 friend class ThreadPlanBase; 23 24 public: 25 // Constructors and Destructors 26 StopInfo(Thread &thread, uint64_t value); 27 28 virtual ~StopInfo() = default; 29 30 bool IsValid() const; 31 SetThread(const lldb::ThreadSP & thread_sp)32 void SetThread(const lldb::ThreadSP &thread_sp) { m_thread_wp = thread_sp; } 33 GetThread()34 lldb::ThreadSP GetThread() const { return m_thread_wp.lock(); } 35 36 // The value of the StopInfo depends on the StopReason. 37 // 38 // StopReason Meaning 39 // ------------------------------------------------ 40 // eStopReasonBreakpoint BreakpointSiteID 41 // eStopReasonSignal Signal number 42 // eStopReasonWatchpoint WatchpointLocationID 43 // eStopReasonPlanComplete No significance 44 GetValue()45 uint64_t GetValue() const { return m_value; } 46 47 virtual lldb::StopReason GetStopReason() const = 0; 48 49 // ShouldStopSynchronous will get called before any thread plans are 50 // consulted, and if it says we should resume the target, then we will just 51 // immediately resume. This should not run any code in or resume the target. 52 ShouldStopSynchronous(Event * event_ptr)53 virtual bool ShouldStopSynchronous(Event *event_ptr) { return true; } 54 OverrideShouldNotify(bool override_value)55 void OverrideShouldNotify(bool override_value) { 56 m_override_should_notify = override_value ? eLazyBoolYes : eLazyBoolNo; 57 } 58 59 // If should stop returns false, check if we should notify of this event ShouldNotify(Event * event_ptr)60 virtual bool ShouldNotify(Event *event_ptr) { 61 if (m_override_should_notify == eLazyBoolCalculate) 62 return DoShouldNotify(event_ptr); 63 else 64 return m_override_should_notify == eLazyBoolYes; 65 } 66 WillResume(lldb::StateType resume_state)67 virtual void WillResume(lldb::StateType resume_state) { 68 // By default, don't do anything 69 } 70 GetDescription()71 virtual const char *GetDescription() { return m_description.c_str(); } 72 SetDescription(const char * desc_cstr)73 virtual void SetDescription(const char *desc_cstr) { 74 if (desc_cstr && desc_cstr[0]) 75 m_description.assign(desc_cstr); 76 else 77 m_description.clear(); 78 } 79 IsValidForOperatingSystemThread(Thread & thread)80 virtual bool IsValidForOperatingSystemThread(Thread &thread) { return true; } 81 82 /// A Continue operation can result in a false stop event 83 /// before any execution has happened. We need to detect this 84 /// and silently continue again one more time. WasContinueInterrupted(Thread & thread)85 virtual bool WasContinueInterrupted(Thread &thread) { return false; } 86 87 // Sometimes the thread plan logic will know that it wants a given stop to 88 // stop or not, regardless of what the ordinary logic for that StopInfo would 89 // dictate. The main example of this is the ThreadPlanCallFunction, which 90 // for instance knows - based on how that particular expression was executed 91 // - whether it wants all breakpoints to auto-continue or not. Use 92 // OverrideShouldStop on the StopInfo to implement this. 93 OverrideShouldStop(bool override_value)94 void OverrideShouldStop(bool override_value) { 95 m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo; 96 } 97 GetOverrideShouldStop()98 bool GetOverrideShouldStop() { 99 return m_override_should_stop != eLazyBoolCalculate; 100 } 101 GetOverriddenShouldStopValue()102 bool GetOverriddenShouldStopValue() { 103 return m_override_should_stop == eLazyBoolYes; 104 } 105 GetExtendedInfo()106 StructuredData::ObjectSP GetExtendedInfo() { return m_extended_info; } 107 108 static lldb::StopInfoSP 109 CreateStopReasonWithBreakpointSiteID(Thread &thread, 110 lldb::break_id_t break_id); 111 112 // This creates a StopInfo for the thread where the should_stop is already 113 // set, and won't be recalculated. 114 static lldb::StopInfoSP CreateStopReasonWithBreakpointSiteID( 115 Thread &thread, lldb::break_id_t break_id, bool should_stop); 116 117 static lldb::StopInfoSP 118 CreateStopReasonWithWatchpointID(Thread &thread, lldb::break_id_t watch_id, 119 bool silently_continue = false); 120 121 static lldb::StopInfoSP 122 CreateStopReasonWithSignal(Thread &thread, int signo, 123 const char *description = nullptr, 124 std::optional<int> code = std::nullopt); 125 126 static lldb::StopInfoSP 127 CreateStopReasonWithInterrupt(Thread &thread, int signo, 128 const char *description); 129 130 static lldb::StopInfoSP CreateStopReasonToTrace(Thread &thread); 131 132 static lldb::StopInfoSP 133 CreateStopReasonWithPlan(lldb::ThreadPlanSP &plan, 134 lldb::ValueObjectSP return_valobj_sp, 135 lldb::ExpressionVariableSP expression_variable_sp); 136 137 static lldb::StopInfoSP 138 CreateStopReasonWithException(Thread &thread, const char *description); 139 140 static lldb::StopInfoSP CreateStopReasonWithExec(Thread &thread); 141 142 static lldb::StopInfoSP 143 CreateStopReasonProcessorTrace(Thread &thread, const char *description); 144 145 static lldb::StopInfoSP CreateStopReasonFork(Thread &thread, 146 lldb::pid_t child_pid, 147 lldb::tid_t child_tid); 148 149 static lldb::StopInfoSP CreateStopReasonVFork(Thread &thread, 150 lldb::pid_t child_pid, 151 lldb::tid_t child_tid); 152 153 static lldb::StopInfoSP CreateStopReasonVForkDone(Thread &thread); 154 155 static lldb::ValueObjectSP 156 GetReturnValueObject(lldb::StopInfoSP &stop_info_sp); 157 158 static lldb::ExpressionVariableSP 159 GetExpressionVariable(lldb::StopInfoSP &stop_info_sp); 160 161 static lldb::ValueObjectSP 162 GetCrashingDereference(lldb::StopInfoSP &stop_info_sp, 163 lldb::addr_t *crashing_address = nullptr); 164 165 protected: 166 // Perform any action that is associated with this stop. This is done as the 167 // Event is removed from the event queue. ProcessEventData::DoOnRemoval does 168 // the job. 169 PerformAction(Event * event_ptr)170 virtual void PerformAction(Event *event_ptr) {} 171 DoShouldNotify(Event * event_ptr)172 virtual bool DoShouldNotify(Event *event_ptr) { return false; } 173 174 // Stop the thread by default. Subclasses can override this to allow the 175 // thread to continue if desired. The ShouldStop method should not do 176 // anything that might run code. If you need to run code when deciding 177 // whether to stop at this StopInfo, that must be done in the PerformAction. 178 // The PerformAction will always get called before the ShouldStop. This is 179 // done by the ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs 180 // to consult this later on. ShouldStop(Event * event_ptr)181 virtual bool ShouldStop(Event *event_ptr) { return true; } 182 183 // Classes that inherit from StackID can see and modify these 184 lldb::ThreadWP m_thread_wp; // The thread corresponding to the stop reason. 185 uint32_t m_stop_id; // The process stop ID for which this stop info is valid 186 uint32_t m_resume_id; // This is the resume ID when we made this stop ID. 187 uint64_t m_value; // A generic value that can be used for things pertaining to 188 // this stop info 189 std::string m_description; // A textual description describing this stop. 190 LazyBool m_override_should_notify; 191 LazyBool m_override_should_stop; 192 193 StructuredData::ObjectSP 194 m_extended_info; // The extended info for this stop info 195 196 // This determines whether the target has run since this stop info. N.B. 197 // running to evaluate a user expression does not count. 198 bool HasTargetRunSinceMe(); 199 200 // MakeStopInfoValid is necessary to allow saved stop infos to resurrect 201 // themselves as valid. It should only be used by 202 // Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step 203 // needed for before-the-fact watchpoints does not prevent us from stopping 204 void MakeStopInfoValid(); 205 206 private: 207 friend class Thread; 208 209 StopInfo(const StopInfo &) = delete; 210 const StopInfo &operator=(const StopInfo &) = delete; 211 }; 212 213 } // namespace lldb_private 214 215 #endif // LLDB_TARGET_STOPINFO_H 216