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 friend class ThreadPlanReverseContinue; 24 25 public: 26 // Constructors and Destructors 27 StopInfo(Thread &thread, uint64_t value); 28 29 virtual ~StopInfo() = default; 30 31 bool IsValid() const; 32 SetThread(const lldb::ThreadSP & thread_sp)33 void SetThread(const lldb::ThreadSP &thread_sp) { m_thread_wp = thread_sp; } 34 GetThread()35 lldb::ThreadSP GetThread() const { return m_thread_wp.lock(); } 36 37 // The value of the StopInfo depends on the StopReason. 38 // 39 // StopReason Meaning 40 // ------------------------------------------------ 41 // eStopReasonBreakpoint BreakpointSiteID 42 // eStopReasonSignal Signal number 43 // eStopReasonWatchpoint WatchpointLocationID 44 // eStopReasonPlanComplete No significance 45 GetValue()46 uint64_t GetValue() const { return m_value; } 47 48 virtual lldb::StopReason GetStopReason() const = 0; 49 50 // ShouldStopSynchronous will get called before any thread plans are 51 // consulted, and if it says we should resume the target, then we will just 52 // immediately resume. This should not run any code in or resume the target. 53 ShouldStopSynchronous(Event * event_ptr)54 virtual bool ShouldStopSynchronous(Event *event_ptr) { return true; } 55 OverrideShouldNotify(bool override_value)56 void OverrideShouldNotify(bool override_value) { 57 m_override_should_notify = override_value ? eLazyBoolYes : eLazyBoolNo; 58 } 59 60 // If should stop returns false, check if we should notify of this event ShouldNotify(Event * event_ptr)61 virtual bool ShouldNotify(Event *event_ptr) { 62 if (m_override_should_notify == eLazyBoolCalculate) 63 return DoShouldNotify(event_ptr); 64 else 65 return m_override_should_notify == eLazyBoolYes; 66 } 67 WillResume(lldb::StateType resume_state)68 virtual void WillResume(lldb::StateType resume_state) { 69 // By default, don't do anything 70 } 71 GetDescription()72 virtual const char *GetDescription() { return m_description.c_str(); } 73 SetDescription(const char * desc_cstr)74 virtual void SetDescription(const char *desc_cstr) { 75 if (desc_cstr && desc_cstr[0]) 76 m_description.assign(desc_cstr); 77 else 78 m_description.clear(); 79 } 80 81 /// This gives the StopInfo a chance to suggest a stack frame to select. 82 /// Passing true for inlined_stack will request changes to the inlined 83 /// call stack. Passing false will request changes to the real stack 84 /// frame. The inlined stack gets adjusted before we call into the thread 85 /// plans so they can reason based on the correct values. The real stack 86 /// adjustment is handled after the frame recognizers get a chance to adjust 87 /// the frame. 88 virtual std::optional<uint32_t> GetSuggestedStackFrameIndex(bool inlined_stack)89 GetSuggestedStackFrameIndex(bool inlined_stack) { 90 return {}; 91 } 92 IsValidForOperatingSystemThread(Thread & thread)93 virtual bool IsValidForOperatingSystemThread(Thread &thread) { return true; } 94 95 /// A Continue operation can result in a false stop event 96 /// before any execution has happened. We need to detect this 97 /// and silently continue again one more time. WasContinueInterrupted(Thread & thread)98 virtual bool WasContinueInterrupted(Thread &thread) { return false; } 99 100 // Sometimes the thread plan logic will know that it wants a given stop to 101 // stop or not, regardless of what the ordinary logic for that StopInfo would 102 // dictate. The main example of this is the ThreadPlanCallFunction, which 103 // for instance knows - based on how that particular expression was executed 104 // - whether it wants all breakpoints to auto-continue or not. Use 105 // OverrideShouldStop on the StopInfo to implement this. 106 OverrideShouldStop(bool override_value)107 void OverrideShouldStop(bool override_value) { 108 m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo; 109 } 110 GetOverrideShouldStop()111 bool GetOverrideShouldStop() { 112 return m_override_should_stop != eLazyBoolCalculate; 113 } 114 GetOverriddenShouldStopValue()115 bool GetOverriddenShouldStopValue() { 116 return m_override_should_stop == eLazyBoolYes; 117 } 118 GetExtendedInfo()119 StructuredData::ObjectSP GetExtendedInfo() { return m_extended_info; } 120 121 /// Returns true if this is a stop reason that should be shown to a user when 122 /// viewing the thread with this stop info. ShouldShow()123 virtual bool ShouldShow() const { return IsValid(); } 124 125 /// Returns true if this is a stop reason that should cause a thread to be 126 /// selected when stopping. ShouldSelect()127 virtual bool ShouldSelect() const { 128 lldb::StopReason reason = GetStopReason(); 129 return reason != lldb::eStopReasonNone && 130 reason != lldb::eStopReasonHistoryBoundary && 131 reason != lldb::eStopReasonInvalid; 132 } 133 134 static lldb::StopInfoSP 135 CreateStopReasonWithBreakpointSiteID(Thread &thread, 136 lldb::break_id_t break_id); 137 138 // This creates a StopInfo for the thread where the should_stop is already 139 // set, and won't be recalculated. 140 static lldb::StopInfoSP CreateStopReasonWithBreakpointSiteID( 141 Thread &thread, lldb::break_id_t break_id, bool should_stop); 142 143 static lldb::StopInfoSP 144 CreateStopReasonWithWatchpointID(Thread &thread, lldb::break_id_t watch_id, 145 bool silently_continue = false); 146 147 static lldb::StopInfoSP 148 CreateStopReasonWithSignal(Thread &thread, int signo, 149 const char *description = nullptr, 150 std::optional<int> code = std::nullopt); 151 152 static lldb::StopInfoSP 153 CreateStopReasonWithInterrupt(Thread &thread, int signo, 154 const char *description); 155 156 static lldb::StopInfoSP CreateStopReasonToTrace(Thread &thread); 157 158 static lldb::StopInfoSP 159 CreateStopReasonWithPlan(lldb::ThreadPlanSP &plan, 160 lldb::ValueObjectSP return_valobj_sp, 161 lldb::ExpressionVariableSP expression_variable_sp); 162 163 static lldb::StopInfoSP 164 CreateStopReasonWithException(Thread &thread, const char *description); 165 166 static lldb::StopInfoSP CreateStopReasonWithExec(Thread &thread); 167 168 static lldb::StopInfoSP 169 CreateStopReasonProcessorTrace(Thread &thread, const char *description); 170 171 // This creates a StopInfo indicating that execution stopped because 172 // it was replaying some recorded execution history, and execution reached 173 // the end of that recorded history. 174 static lldb::StopInfoSP 175 CreateStopReasonHistoryBoundary(Thread &thread, const char *description); 176 177 static lldb::StopInfoSP CreateStopReasonFork(Thread &thread, 178 lldb::pid_t child_pid, 179 lldb::tid_t child_tid); 180 181 static lldb::StopInfoSP CreateStopReasonVFork(Thread &thread, 182 lldb::pid_t child_pid, 183 lldb::tid_t child_tid); 184 185 static lldb::StopInfoSP CreateStopReasonVForkDone(Thread &thread); 186 187 static lldb::ValueObjectSP 188 GetReturnValueObject(lldb::StopInfoSP &stop_info_sp); 189 190 static lldb::ExpressionVariableSP 191 GetExpressionVariable(lldb::StopInfoSP &stop_info_sp); 192 193 static lldb::ValueObjectSP 194 GetCrashingDereference(lldb::StopInfoSP &stop_info_sp, 195 lldb::addr_t *crashing_address = nullptr); 196 197 protected: 198 // Perform any action that is associated with this stop. This is done as the 199 // Event is removed from the event queue. ProcessEventData::DoOnRemoval does 200 // the job. 201 PerformAction(Event * event_ptr)202 virtual void PerformAction(Event *event_ptr) {} 203 DoShouldNotify(Event * event_ptr)204 virtual bool DoShouldNotify(Event *event_ptr) { return false; } 205 206 // Stop the thread by default. Subclasses can override this to allow the 207 // thread to continue if desired. The ShouldStop method should not do 208 // anything that might run code. If you need to run code when deciding 209 // whether to stop at this StopInfo, that must be done in the PerformAction. 210 // The PerformAction will always get called before the ShouldStop. This is 211 // done by the ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs 212 // to consult this later on. ShouldStop(Event * event_ptr)213 virtual bool ShouldStop(Event *event_ptr) { return true; } 214 215 // Classes that inherit from StackID can see and modify these 216 lldb::ThreadWP m_thread_wp; // The thread corresponding to the stop reason. 217 uint32_t m_stop_id; // The process stop ID for which this stop info is valid 218 uint32_t m_resume_id; // This is the resume ID when we made this stop ID. 219 uint64_t m_value; // A generic value that can be used for things pertaining to 220 // this stop info 221 std::string m_description; // A textual description describing this stop. 222 LazyBool m_override_should_notify; 223 LazyBool m_override_should_stop; 224 225 StructuredData::ObjectSP 226 m_extended_info; // The extended info for this stop info 227 228 // This determines whether the target has run since this stop info. N.B. 229 // running to evaluate a user expression does not count. 230 bool HasTargetRunSinceMe(); 231 232 // MakeStopInfoValid is necessary to allow saved stop infos to resurrect 233 // themselves as valid. It should only be used by 234 // Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step 235 // needed for before-the-fact watchpoints does not prevent us from stopping 236 void MakeStopInfoValid(); 237 238 private: 239 friend class Thread; 240 241 StopInfo(const StopInfo &) = delete; 242 const StopInfo &operator=(const StopInfo &) = delete; 243 }; 244 245 } // namespace lldb_private 246 247 #endif // LLDB_TARGET_STOPINFO_H 248