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
18namespace lldb_private {
19
20class StopInfo : public std::enable_shared_from_this<StopInfo> {
21 friend class Process::ProcessEventData;
22 friend class ThreadPlanBase;
23
24public:
25 // Constructors and Destructors
26 StopInfo(Thread &thread, uint64_t value);
27
28 virtual ~StopInfo() = default;
29
30 bool IsValid() const;
31
32 void SetThread(const lldb::ThreadSP &thread_sp) { m_thread_wp = thread_sp; }
33
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
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
53 virtual bool ShouldStopSynchronous(Event *event_ptr) { return true; }
54
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
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
67 virtual void WillResume(lldb::StateType resume_state) {
68 // By default, don't do anything
69 }
70
71 virtual const char *GetDescription() { return m_description.c_str(); }
72
73 virtual void SetDescription(const char *desc_cstr) {
74 if (desc_cstr && desc_cstr[0])
75 m_description.assign(s: desc_cstr);
76 else
77 m_description.clear();
78 }
79
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.
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
94 void OverrideShouldStop(bool override_value) {
95 m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo;
96 }
97
98 bool GetOverrideShouldStop() {
99 return m_override_should_stop != eLazyBoolCalculate;
100 }
101
102 bool GetOverriddenShouldStopValue() {
103 return m_override_should_stop == eLazyBoolYes;
104 }
105
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 CreateStopReasonToTrace(Thread &thread);
127
128 static lldb::StopInfoSP
129 CreateStopReasonWithPlan(lldb::ThreadPlanSP &plan,
130 lldb::ValueObjectSP return_valobj_sp,
131 lldb::ExpressionVariableSP expression_variable_sp);
132
133 static lldb::StopInfoSP
134 CreateStopReasonWithException(Thread &thread, const char *description);
135
136 static lldb::StopInfoSP CreateStopReasonWithExec(Thread &thread);
137
138 static lldb::StopInfoSP
139 CreateStopReasonProcessorTrace(Thread &thread, const char *description);
140
141 static lldb::StopInfoSP CreateStopReasonFork(Thread &thread,
142 lldb::pid_t child_pid,
143 lldb::tid_t child_tid);
144
145 static lldb::StopInfoSP CreateStopReasonVFork(Thread &thread,
146 lldb::pid_t child_pid,
147 lldb::tid_t child_tid);
148
149 static lldb::StopInfoSP CreateStopReasonVForkDone(Thread &thread);
150
151 static lldb::ValueObjectSP
152 GetReturnValueObject(lldb::StopInfoSP &stop_info_sp);
153
154 static lldb::ExpressionVariableSP
155 GetExpressionVariable(lldb::StopInfoSP &stop_info_sp);
156
157 static lldb::ValueObjectSP
158 GetCrashingDereference(lldb::StopInfoSP &stop_info_sp,
159 lldb::addr_t *crashing_address = nullptr);
160
161protected:
162 // Perform any action that is associated with this stop. This is done as the
163 // Event is removed from the event queue. ProcessEventData::DoOnRemoval does
164 // the job.
165
166 virtual void PerformAction(Event *event_ptr) {}
167
168 virtual bool DoShouldNotify(Event *event_ptr) { return false; }
169
170 // Stop the thread by default. Subclasses can override this to allow the
171 // thread to continue if desired. The ShouldStop method should not do
172 // anything that might run code. If you need to run code when deciding
173 // whether to stop at this StopInfo, that must be done in the PerformAction.
174 // The PerformAction will always get called before the ShouldStop. This is
175 // done by the ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs
176 // to consult this later on.
177 virtual bool ShouldStop(Event *event_ptr) { return true; }
178
179 // Classes that inherit from StackID can see and modify these
180 lldb::ThreadWP m_thread_wp; // The thread corresponding to the stop reason.
181 uint32_t m_stop_id; // The process stop ID for which this stop info is valid
182 uint32_t m_resume_id; // This is the resume ID when we made this stop ID.
183 uint64_t m_value; // A generic value that can be used for things pertaining to
184 // this stop info
185 std::string m_description; // A textual description describing this stop.
186 LazyBool m_override_should_notify;
187 LazyBool m_override_should_stop;
188
189 StructuredData::ObjectSP
190 m_extended_info; // The extended info for this stop info
191
192 // This determines whether the target has run since this stop info. N.B.
193 // running to evaluate a user expression does not count.
194 bool HasTargetRunSinceMe();
195
196 // MakeStopInfoValid is necessary to allow saved stop infos to resurrect
197 // themselves as valid. It should only be used by
198 // Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step
199 // needed for before-the-fact watchpoints does not prevent us from stopping
200 void MakeStopInfoValid();
201
202private:
203 friend class Thread;
204
205 StopInfo(const StopInfo &) = delete;
206 const StopInfo &operator=(const StopInfo &) = delete;
207};
208
209} // namespace lldb_private
210
211#endif // LLDB_TARGET_STOPINFO_H
212

source code of lldb/include/lldb/Target/StopInfo.h