xref: /openbsd-src/gnu/llvm/lldb/source/Target/StopInfo.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- StopInfo.cpp ------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include <string>
10061da546Spatrick 
11061da546Spatrick #include "lldb/Breakpoint/Breakpoint.h"
12061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
13061da546Spatrick #include "lldb/Breakpoint/StoppointCallbackContext.h"
14061da546Spatrick #include "lldb/Breakpoint/Watchpoint.h"
15061da546Spatrick #include "lldb/Core/Debugger.h"
16061da546Spatrick #include "lldb/Core/ValueObject.h"
17061da546Spatrick #include "lldb/Expression/UserExpression.h"
18061da546Spatrick #include "lldb/Target/Process.h"
19061da546Spatrick #include "lldb/Target/StopInfo.h"
20061da546Spatrick #include "lldb/Target/Target.h"
21061da546Spatrick #include "lldb/Target/Thread.h"
22061da546Spatrick #include "lldb/Target/ThreadPlan.h"
23*f6aab3d8Srobert #include "lldb/Target/ThreadPlanStepInstruction.h"
24061da546Spatrick #include "lldb/Target/UnixSignals.h"
25*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
26061da546Spatrick #include "lldb/Utility/Log.h"
27061da546Spatrick #include "lldb/Utility/StreamString.h"
28061da546Spatrick 
29061da546Spatrick using namespace lldb;
30061da546Spatrick using namespace lldb_private;
31061da546Spatrick 
StopInfo(Thread & thread,uint64_t value)32061da546Spatrick StopInfo::StopInfo(Thread &thread, uint64_t value)
33061da546Spatrick     : m_thread_wp(thread.shared_from_this()),
34061da546Spatrick       m_stop_id(thread.GetProcess()->GetStopID()),
35061da546Spatrick       m_resume_id(thread.GetProcess()->GetResumeID()), m_value(value),
36061da546Spatrick       m_description(), m_override_should_notify(eLazyBoolCalculate),
37061da546Spatrick       m_override_should_stop(eLazyBoolCalculate), m_extended_info() {}
38061da546Spatrick 
IsValid() const39061da546Spatrick bool StopInfo::IsValid() const {
40061da546Spatrick   ThreadSP thread_sp(m_thread_wp.lock());
41061da546Spatrick   if (thread_sp)
42061da546Spatrick     return thread_sp->GetProcess()->GetStopID() == m_stop_id;
43061da546Spatrick   return false;
44061da546Spatrick }
45061da546Spatrick 
MakeStopInfoValid()46061da546Spatrick void StopInfo::MakeStopInfoValid() {
47061da546Spatrick   ThreadSP thread_sp(m_thread_wp.lock());
48061da546Spatrick   if (thread_sp) {
49061da546Spatrick     m_stop_id = thread_sp->GetProcess()->GetStopID();
50061da546Spatrick     m_resume_id = thread_sp->GetProcess()->GetResumeID();
51061da546Spatrick   }
52061da546Spatrick }
53061da546Spatrick 
HasTargetRunSinceMe()54061da546Spatrick bool StopInfo::HasTargetRunSinceMe() {
55061da546Spatrick   ThreadSP thread_sp(m_thread_wp.lock());
56061da546Spatrick 
57061da546Spatrick   if (thread_sp) {
58061da546Spatrick     lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState();
59061da546Spatrick     if (ret_type == eStateRunning) {
60061da546Spatrick       return true;
61061da546Spatrick     } else if (ret_type == eStateStopped) {
62061da546Spatrick       // This is a little tricky.  We want to count "run and stopped again
63061da546Spatrick       // before you could ask this question as a "TRUE" answer to
64061da546Spatrick       // HasTargetRunSinceMe.  But we don't want to include any running of the
65061da546Spatrick       // target done for expressions.  So we track both resumes, and resumes
66061da546Spatrick       // caused by expressions, and check if there are any resumes
67061da546Spatrick       // NOT caused
68061da546Spatrick       // by expressions.
69061da546Spatrick 
70061da546Spatrick       uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID();
71061da546Spatrick       uint32_t last_user_expression_id =
72061da546Spatrick           thread_sp->GetProcess()->GetLastUserExpressionResumeID();
73061da546Spatrick       if (curr_resume_id == m_resume_id) {
74061da546Spatrick         return false;
75061da546Spatrick       } else if (curr_resume_id > last_user_expression_id) {
76061da546Spatrick         return true;
77061da546Spatrick       }
78061da546Spatrick     }
79061da546Spatrick   }
80061da546Spatrick   return false;
81061da546Spatrick }
82061da546Spatrick 
83061da546Spatrick // StopInfoBreakpoint
84061da546Spatrick 
85061da546Spatrick namespace lldb_private {
86061da546Spatrick class StopInfoBreakpoint : public StopInfo {
87061da546Spatrick public:
StopInfoBreakpoint(Thread & thread,break_id_t break_id)88061da546Spatrick   StopInfoBreakpoint(Thread &thread, break_id_t break_id)
89061da546Spatrick       : StopInfo(thread, break_id), m_should_stop(false),
90061da546Spatrick         m_should_stop_is_valid(false), m_should_perform_action(true),
91061da546Spatrick         m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
92*f6aab3d8Srobert         m_was_all_internal(false), m_was_one_shot(false) {
93061da546Spatrick     StoreBPInfo();
94061da546Spatrick   }
95061da546Spatrick 
StopInfoBreakpoint(Thread & thread,break_id_t break_id,bool should_stop)96061da546Spatrick   StopInfoBreakpoint(Thread &thread, break_id_t break_id, bool should_stop)
97061da546Spatrick       : StopInfo(thread, break_id), m_should_stop(should_stop),
98061da546Spatrick         m_should_stop_is_valid(true), m_should_perform_action(true),
99061da546Spatrick         m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
100*f6aab3d8Srobert         m_was_all_internal(false), m_was_one_shot(false) {
101061da546Spatrick     StoreBPInfo();
102061da546Spatrick   }
103061da546Spatrick 
104061da546Spatrick   ~StopInfoBreakpoint() override = default;
105061da546Spatrick 
StoreBPInfo()106061da546Spatrick   void StoreBPInfo() {
107061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
108061da546Spatrick     if (thread_sp) {
109061da546Spatrick       BreakpointSiteSP bp_site_sp(
110061da546Spatrick           thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
111061da546Spatrick       if (bp_site_sp) {
112*f6aab3d8Srobert         uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
113*f6aab3d8Srobert         if (num_owners == 1) {
114061da546Spatrick           BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0);
115061da546Spatrick           if (bp_loc_sp) {
116*f6aab3d8Srobert             Breakpoint & bkpt = bp_loc_sp->GetBreakpoint();
117*f6aab3d8Srobert             m_break_id = bkpt.GetID();
118*f6aab3d8Srobert             m_was_one_shot = bkpt.IsOneShot();
119*f6aab3d8Srobert             m_was_all_internal = bkpt.IsInternal();
120*f6aab3d8Srobert           }
121*f6aab3d8Srobert         } else {
122*f6aab3d8Srobert           m_was_all_internal = true;
123*f6aab3d8Srobert           for (uint32_t i = 0; i < num_owners; i++) {
124*f6aab3d8Srobert             if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) {
125*f6aab3d8Srobert               m_was_all_internal = false;
126*f6aab3d8Srobert               break;
127*f6aab3d8Srobert             }
128061da546Spatrick           }
129061da546Spatrick         }
130061da546Spatrick         m_address = bp_site_sp->GetLoadAddress();
131061da546Spatrick       }
132061da546Spatrick     }
133061da546Spatrick   }
134061da546Spatrick 
IsValidForOperatingSystemThread(Thread & thread)135061da546Spatrick   bool IsValidForOperatingSystemThread(Thread &thread) override {
136061da546Spatrick     ProcessSP process_sp(thread.GetProcess());
137061da546Spatrick     if (process_sp) {
138061da546Spatrick       BreakpointSiteSP bp_site_sp(
139061da546Spatrick           process_sp->GetBreakpointSiteList().FindByID(m_value));
140061da546Spatrick       if (bp_site_sp)
141be691f3bSpatrick         return bp_site_sp->ValidForThisThread(thread);
142061da546Spatrick     }
143061da546Spatrick     return false;
144061da546Spatrick   }
145061da546Spatrick 
GetStopReason() const146061da546Spatrick   StopReason GetStopReason() const override { return eStopReasonBreakpoint; }
147061da546Spatrick 
ShouldStopSynchronous(Event * event_ptr)148061da546Spatrick   bool ShouldStopSynchronous(Event *event_ptr) override {
149061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
150061da546Spatrick     if (thread_sp) {
151061da546Spatrick       if (!m_should_stop_is_valid) {
152061da546Spatrick         // Only check once if we should stop at a breakpoint
153061da546Spatrick         BreakpointSiteSP bp_site_sp(
154061da546Spatrick             thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
155061da546Spatrick         if (bp_site_sp) {
156061da546Spatrick           ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
157061da546Spatrick           StoppointCallbackContext context(event_ptr, exe_ctx, true);
158061da546Spatrick           bp_site_sp->BumpHitCounts();
159061da546Spatrick           m_should_stop = bp_site_sp->ShouldStop(&context);
160061da546Spatrick         } else {
161*f6aab3d8Srobert           Log *log = GetLog(LLDBLog::Process);
162061da546Spatrick 
163061da546Spatrick           LLDB_LOGF(log,
164061da546Spatrick                     "Process::%s could not find breakpoint site id: %" PRId64
165061da546Spatrick                     "...",
166061da546Spatrick                     __FUNCTION__, m_value);
167061da546Spatrick 
168061da546Spatrick           m_should_stop = true;
169061da546Spatrick         }
170061da546Spatrick         m_should_stop_is_valid = true;
171061da546Spatrick       }
172061da546Spatrick       return m_should_stop;
173061da546Spatrick     }
174061da546Spatrick     return false;
175061da546Spatrick   }
176061da546Spatrick 
DoShouldNotify(Event * event_ptr)177061da546Spatrick   bool DoShouldNotify(Event *event_ptr) override {
178*f6aab3d8Srobert     return !m_was_all_internal;
179061da546Spatrick   }
180061da546Spatrick 
GetDescription()181061da546Spatrick   const char *GetDescription() override {
182061da546Spatrick     if (m_description.empty()) {
183061da546Spatrick       ThreadSP thread_sp(m_thread_wp.lock());
184061da546Spatrick       if (thread_sp) {
185061da546Spatrick         BreakpointSiteSP bp_site_sp(
186061da546Spatrick             thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
187061da546Spatrick         if (bp_site_sp) {
188061da546Spatrick           StreamString strm;
189061da546Spatrick           // If we have just hit an internal breakpoint, and it has a kind
190061da546Spatrick           // description, print that instead of the full breakpoint printing:
191061da546Spatrick           if (bp_site_sp->IsInternal()) {
192061da546Spatrick             size_t num_owners = bp_site_sp->GetNumberOfOwners();
193061da546Spatrick             for (size_t idx = 0; idx < num_owners; idx++) {
194061da546Spatrick               const char *kind = bp_site_sp->GetOwnerAtIndex(idx)
195061da546Spatrick                                      ->GetBreakpoint()
196061da546Spatrick                                      .GetBreakpointKind();
197061da546Spatrick               if (kind != nullptr) {
198061da546Spatrick                 m_description.assign(kind);
199061da546Spatrick                 return kind;
200061da546Spatrick               }
201061da546Spatrick             }
202061da546Spatrick           }
203061da546Spatrick 
204061da546Spatrick           strm.Printf("breakpoint ");
205061da546Spatrick           bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
206dda28197Spatrick           m_description = std::string(strm.GetString());
207061da546Spatrick         } else {
208061da546Spatrick           StreamString strm;
209061da546Spatrick           if (m_break_id != LLDB_INVALID_BREAK_ID) {
210061da546Spatrick             BreakpointSP break_sp =
211061da546Spatrick                 thread_sp->GetProcess()->GetTarget().GetBreakpointByID(
212061da546Spatrick                     m_break_id);
213061da546Spatrick             if (break_sp) {
214061da546Spatrick               if (break_sp->IsInternal()) {
215061da546Spatrick                 const char *kind = break_sp->GetBreakpointKind();
216061da546Spatrick                 if (kind)
217061da546Spatrick                   strm.Printf("internal %s breakpoint(%d).", kind, m_break_id);
218061da546Spatrick                 else
219061da546Spatrick                   strm.Printf("internal breakpoint(%d).", m_break_id);
220061da546Spatrick               } else {
221061da546Spatrick                 strm.Printf("breakpoint %d.", m_break_id);
222061da546Spatrick               }
223061da546Spatrick             } else {
224061da546Spatrick               if (m_was_one_shot)
225061da546Spatrick                 strm.Printf("one-shot breakpoint %d", m_break_id);
226061da546Spatrick               else
227061da546Spatrick                 strm.Printf("breakpoint %d which has been deleted.",
228061da546Spatrick                             m_break_id);
229061da546Spatrick             }
230061da546Spatrick           } else if (m_address == LLDB_INVALID_ADDRESS)
231061da546Spatrick             strm.Printf("breakpoint site %" PRIi64
232061da546Spatrick                         " which has been deleted - unknown address",
233061da546Spatrick                         m_value);
234061da546Spatrick           else
235061da546Spatrick             strm.Printf("breakpoint site %" PRIi64
236061da546Spatrick                         " which has been deleted - was at 0x%" PRIx64,
237061da546Spatrick                         m_value, m_address);
238061da546Spatrick 
239dda28197Spatrick           m_description = std::string(strm.GetString());
240061da546Spatrick         }
241061da546Spatrick       }
242061da546Spatrick     }
243061da546Spatrick     return m_description.c_str();
244061da546Spatrick   }
245061da546Spatrick 
246061da546Spatrick protected:
ShouldStop(Event * event_ptr)247061da546Spatrick   bool ShouldStop(Event *event_ptr) override {
248061da546Spatrick     // This just reports the work done by PerformAction or the synchronous
249061da546Spatrick     // stop. It should only ever get called after they have had a chance to
250061da546Spatrick     // run.
251061da546Spatrick     assert(m_should_stop_is_valid);
252061da546Spatrick     return m_should_stop;
253061da546Spatrick   }
254061da546Spatrick 
PerformAction(Event * event_ptr)255061da546Spatrick   void PerformAction(Event *event_ptr) override {
256061da546Spatrick     if (!m_should_perform_action)
257061da546Spatrick       return;
258061da546Spatrick     m_should_perform_action = false;
259061da546Spatrick     bool internal_breakpoint = true;
260061da546Spatrick 
261061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
262061da546Spatrick 
263061da546Spatrick     if (thread_sp) {
264*f6aab3d8Srobert       Log *log = GetLog(LLDBLog::Breakpoints | LLDBLog::Step);
265061da546Spatrick 
266061da546Spatrick       if (!thread_sp->IsValid()) {
267061da546Spatrick         // This shouldn't ever happen, but just in case, don't do more harm.
268061da546Spatrick         if (log) {
269061da546Spatrick           LLDB_LOGF(log, "PerformAction got called with an invalid thread.");
270061da546Spatrick         }
271061da546Spatrick         m_should_stop = true;
272061da546Spatrick         m_should_stop_is_valid = true;
273061da546Spatrick         return;
274061da546Spatrick       }
275061da546Spatrick 
276061da546Spatrick       BreakpointSiteSP bp_site_sp(
277061da546Spatrick           thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
278061da546Spatrick       std::unordered_set<break_id_t> precondition_breakpoints;
279*f6aab3d8Srobert       // Breakpoints that fail their condition check are not considered to
280*f6aab3d8Srobert       // have been hit.  If the only locations at this site have failed their
281*f6aab3d8Srobert       // conditions, we should change the stop-info to none.  Otherwise, if we
282*f6aab3d8Srobert       // hit another breakpoint on a different thread which does stop, users
283*f6aab3d8Srobert       // will see a breakpont hit with a failed condition, which is wrong.
284*f6aab3d8Srobert       // Use this variable to tell us if that is true.
285*f6aab3d8Srobert       bool actually_hit_any_locations = false;
286061da546Spatrick       if (bp_site_sp) {
287061da546Spatrick         // Let's copy the owners list out of the site and store them in a local
288061da546Spatrick         // list.  That way if one of the breakpoint actions changes the site,
289061da546Spatrick         // then we won't be operating on a bad list.
290061da546Spatrick         BreakpointLocationCollection site_locations;
291061da546Spatrick         size_t num_owners = bp_site_sp->CopyOwnersList(site_locations);
292061da546Spatrick 
293061da546Spatrick         if (num_owners == 0) {
294061da546Spatrick           m_should_stop = true;
295*f6aab3d8Srobert           actually_hit_any_locations = true;  // We're going to stop, don't
296*f6aab3d8Srobert                                               // change the stop info.
297061da546Spatrick         } else {
298061da546Spatrick           // We go through each location, and test first its precondition -
299061da546Spatrick           // this overrides everything.  Note, we only do this once per
300061da546Spatrick           // breakpoint - not once per location... Then check the condition.
301061da546Spatrick           // If the condition says to stop, then we run the callback for that
302061da546Spatrick           // location.  If that callback says to stop as well, then we set
303061da546Spatrick           // m_should_stop to true; we are going to stop. But we still want to
304061da546Spatrick           // give all the breakpoints whose conditions say we are going to stop
305061da546Spatrick           // a chance to run their callbacks. Of course if any callback
306061da546Spatrick           // restarts the target by putting "continue" in the callback, then
307061da546Spatrick           // we're going to restart, without running the rest of the callbacks.
308061da546Spatrick           // And in this case we will end up not stopping even if another
309061da546Spatrick           // location said we should stop. But that's better than not running
310061da546Spatrick           // all the callbacks.
311061da546Spatrick 
312be691f3bSpatrick           // There's one other complication here.  We may have run an async
313be691f3bSpatrick           // breakpoint callback that said we should stop.  We only want to
314be691f3bSpatrick           // override that if another breakpoint action says we shouldn't
315be691f3bSpatrick           // stop.  If nobody else has an opinion, then we should stop if the
316be691f3bSpatrick           // async callback says we should.  An example of this is the async
317be691f3bSpatrick           // shared library load notification breakpoint and the setting
318be691f3bSpatrick           // stop-on-sharedlibrary-events.
319be691f3bSpatrick           // We'll keep the async value in async_should_stop, and track whether
320be691f3bSpatrick           // anyone said we should NOT stop in actually_said_continue.
321be691f3bSpatrick           bool async_should_stop = false;
322be691f3bSpatrick           if (m_should_stop_is_valid)
323be691f3bSpatrick             async_should_stop = m_should_stop;
324be691f3bSpatrick           bool actually_said_continue = false;
325be691f3bSpatrick 
326061da546Spatrick           m_should_stop = false;
327061da546Spatrick 
328061da546Spatrick           // We don't select threads as we go through them testing breakpoint
329061da546Spatrick           // conditions and running commands. So we need to set the thread for
330061da546Spatrick           // expression evaluation here:
331061da546Spatrick           ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);
332061da546Spatrick 
333061da546Spatrick           ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
334061da546Spatrick           Process *process = exe_ctx.GetProcessPtr();
335061da546Spatrick           if (process->GetModIDRef().IsLastResumeForUserExpression()) {
336061da546Spatrick             // If we are in the middle of evaluating an expression, don't run
337061da546Spatrick             // asynchronous breakpoint commands or expressions.  That could
338061da546Spatrick             // lead to infinite recursion if the command or condition re-calls
339061da546Spatrick             // the function with this breakpoint.
340061da546Spatrick             // TODO: We can keep a list of the breakpoints we've seen while
341061da546Spatrick             // running expressions in the nested
342061da546Spatrick             // PerformAction calls that can arise when the action runs a
343061da546Spatrick             // function that hits another breakpoint, and only stop running
344061da546Spatrick             // commands when we see the same breakpoint hit a second time.
345061da546Spatrick 
346061da546Spatrick             m_should_stop_is_valid = true;
347061da546Spatrick 
348061da546Spatrick             // It is possible that the user has a breakpoint at the same site
349061da546Spatrick             // as the completed plan had (e.g. user has a breakpoint
350061da546Spatrick             // on a module entry point, and `ThreadPlanCallFunction` ends
351061da546Spatrick             // also there). We can't find an internal breakpoint in the loop
352061da546Spatrick             // later because it was already removed on the plan completion.
353061da546Spatrick             // So check if the plan was completed, and stop if so.
354061da546Spatrick             if (thread_sp->CompletedPlanOverridesBreakpoint()) {
355061da546Spatrick               m_should_stop = true;
356061da546Spatrick               thread_sp->ResetStopInfo();
357061da546Spatrick               return;
358061da546Spatrick             }
359061da546Spatrick 
360061da546Spatrick             LLDB_LOGF(log, "StopInfoBreakpoint::PerformAction - Hit a "
361061da546Spatrick                            "breakpoint while running an expression,"
362061da546Spatrick                            " not running commands to avoid recursion.");
363061da546Spatrick             bool ignoring_breakpoints =
364061da546Spatrick                 process->GetIgnoreBreakpointsInExpressions();
365*f6aab3d8Srobert             // Internal breakpoints should be allowed to do their job, we
366*f6aab3d8Srobert             // can make sure they don't do anything that would cause recursive
367*f6aab3d8Srobert             // command execution:
368*f6aab3d8Srobert             if (!m_was_all_internal) {
369*f6aab3d8Srobert               m_should_stop = !ignoring_breakpoints;
370061da546Spatrick               LLDB_LOGF(log,
371061da546Spatrick                         "StopInfoBreakpoint::PerformAction - in expression, "
372061da546Spatrick                         "continuing: %s.",
373061da546Spatrick                         m_should_stop ? "true" : "false");
374*f6aab3d8Srobert               Debugger::ReportWarning(
375*f6aab3d8Srobert                   "hit breakpoint while running function, skipping commands "
376*f6aab3d8Srobert                   "and conditions to prevent recursion",
377*f6aab3d8Srobert                     process->GetTarget().GetDebugger().GetID());
378061da546Spatrick               return;
379061da546Spatrick             }
380*f6aab3d8Srobert           }
381061da546Spatrick 
382061da546Spatrick           StoppointCallbackContext context(event_ptr, exe_ctx, false);
383061da546Spatrick 
384061da546Spatrick           // For safety's sake let's also grab an extra reference to the
385061da546Spatrick           // breakpoint owners of the locations we're going to examine, since
386061da546Spatrick           // the locations are going to have to get back to their breakpoints,
387061da546Spatrick           // and the locations don't keep their owners alive.  I'm just
388061da546Spatrick           // sticking the BreakpointSP's in a vector since I'm only using it to
389061da546Spatrick           // locally increment their retain counts.
390061da546Spatrick 
391061da546Spatrick           std::vector<lldb::BreakpointSP> location_owners;
392061da546Spatrick 
393061da546Spatrick           for (size_t j = 0; j < num_owners; j++) {
394061da546Spatrick             BreakpointLocationSP loc(site_locations.GetByIndex(j));
395061da546Spatrick             location_owners.push_back(loc->GetBreakpoint().shared_from_this());
396061da546Spatrick           }
397061da546Spatrick 
398061da546Spatrick           for (size_t j = 0; j < num_owners; j++) {
399061da546Spatrick             lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
400061da546Spatrick             StreamString loc_desc;
401061da546Spatrick             if (log) {
402061da546Spatrick               bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief);
403061da546Spatrick             }
404061da546Spatrick             // If another action disabled this breakpoint or its location, then
405061da546Spatrick             // don't run the actions.
406061da546Spatrick             if (!bp_loc_sp->IsEnabled() ||
407061da546Spatrick                 !bp_loc_sp->GetBreakpoint().IsEnabled())
408061da546Spatrick               continue;
409061da546Spatrick 
410061da546Spatrick             // The breakpoint site may have many locations associated with it,
411061da546Spatrick             // not all of them valid for this thread.  Skip the ones that
412061da546Spatrick             // aren't:
413be691f3bSpatrick             if (!bp_loc_sp->ValidForThisThread(*thread_sp)) {
414061da546Spatrick               if (log) {
415061da546Spatrick                 LLDB_LOGF(log,
416061da546Spatrick                           "Breakpoint %s hit on thread 0x%llx but it was not "
417061da546Spatrick                           "for this thread, continuing.",
418061da546Spatrick                           loc_desc.GetData(),
419061da546Spatrick                           static_cast<unsigned long long>(thread_sp->GetID()));
420061da546Spatrick               }
421061da546Spatrick               continue;
422061da546Spatrick             }
423061da546Spatrick 
424061da546Spatrick             internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal();
425061da546Spatrick 
426061da546Spatrick             // First run the precondition, but since the precondition is per
427061da546Spatrick             // breakpoint, only run it once per breakpoint.
428061da546Spatrick             std::pair<std::unordered_set<break_id_t>::iterator, bool> result =
429061da546Spatrick                 precondition_breakpoints.insert(
430061da546Spatrick                     bp_loc_sp->GetBreakpoint().GetID());
431061da546Spatrick             if (!result.second)
432061da546Spatrick               continue;
433061da546Spatrick 
434061da546Spatrick             bool precondition_result =
435061da546Spatrick                 bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);
436be691f3bSpatrick             if (!precondition_result) {
437be691f3bSpatrick               actually_said_continue = true;
438061da546Spatrick               continue;
439be691f3bSpatrick             }
440061da546Spatrick             // Next run the condition for the breakpoint.  If that says we
441061da546Spatrick             // should stop, then we'll run the callback for the breakpoint.  If
442061da546Spatrick             // the callback says we shouldn't stop that will win.
443061da546Spatrick 
444*f6aab3d8Srobert             if (bp_loc_sp->GetConditionText() == nullptr)
445*f6aab3d8Srobert               actually_hit_any_locations = true;
446*f6aab3d8Srobert             else {
447061da546Spatrick               Status condition_error;
448061da546Spatrick               bool condition_says_stop =
449061da546Spatrick                   bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);
450061da546Spatrick 
451061da546Spatrick               if (!condition_error.Success()) {
452*f6aab3d8Srobert                 // If the condition fails to evaluate, we are going to stop
453*f6aab3d8Srobert                 // at it, so the location was hit.
454*f6aab3d8Srobert                 actually_hit_any_locations = true;
455061da546Spatrick                 const char *err_str =
456*f6aab3d8Srobert                     condition_error.AsCString("<unknown error>");
457061da546Spatrick                 LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);
458061da546Spatrick 
459*f6aab3d8Srobert                 StreamString strm;
460*f6aab3d8Srobert                 strm << "stopped due to an error evaluating condition of "
461*f6aab3d8Srobert                         "breakpoint ";
462*f6aab3d8Srobert                 bp_loc_sp->GetDescription(&strm, eDescriptionLevelBrief);
463*f6aab3d8Srobert                 strm << ": \"" << bp_loc_sp->GetConditionText() << "\"\n";
464*f6aab3d8Srobert                 strm << err_str;
465*f6aab3d8Srobert 
466*f6aab3d8Srobert                 Debugger::ReportError(
467*f6aab3d8Srobert                     strm.GetString().str(),
468*f6aab3d8Srobert                     exe_ctx.GetTargetRef().GetDebugger().GetID());
469061da546Spatrick               } else {
470061da546Spatrick                 LLDB_LOGF(log,
471061da546Spatrick                           "Condition evaluated for breakpoint %s on thread "
472dda28197Spatrick                           "0x%llx condition_says_stop: %i.",
473061da546Spatrick                           loc_desc.GetData(),
474061da546Spatrick                           static_cast<unsigned long long>(thread_sp->GetID()),
475061da546Spatrick                           condition_says_stop);
476*f6aab3d8Srobert                 if (condition_says_stop)
477*f6aab3d8Srobert                   actually_hit_any_locations = true;
478*f6aab3d8Srobert                 else {
479061da546Spatrick                   // We don't want to increment the hit count of breakpoints if
480061da546Spatrick                   // the condition fails. We've already bumped it by the time
481061da546Spatrick                   // we get here, so undo the bump:
482061da546Spatrick                   bp_loc_sp->UndoBumpHitCount();
483be691f3bSpatrick                   actually_said_continue = true;
484061da546Spatrick                   continue;
485061da546Spatrick                 }
486061da546Spatrick               }
487061da546Spatrick             }
488061da546Spatrick 
489be691f3bSpatrick             // We've done all the checks whose failure means "we consider lldb
490be691f3bSpatrick             // not to have hit the breakpoint".  Now we're going to check for
491be691f3bSpatrick             // conditions that might continue after hitting.  Start with the
492be691f3bSpatrick             // ignore count:
493be691f3bSpatrick             if (!bp_loc_sp->IgnoreCountShouldStop()) {
494be691f3bSpatrick               actually_said_continue = true;
495be691f3bSpatrick               continue;
496be691f3bSpatrick             }
497be691f3bSpatrick 
498061da546Spatrick             // Check the auto-continue bit on the location, do this before the
499061da546Spatrick             // callback since it may change this, but that would be for the
500061da546Spatrick             // NEXT hit.  Note, you might think you could check auto-continue
501061da546Spatrick             // before the condition, and not evaluate the condition if it says
502061da546Spatrick             // to continue.  But failing the condition means the breakpoint was
503061da546Spatrick             // effectively NOT HIT.  So these two states are different.
504061da546Spatrick             bool auto_continue_says_stop = true;
505061da546Spatrick             if (bp_loc_sp->IsAutoContinue())
506061da546Spatrick             {
507061da546Spatrick               LLDB_LOGF(log,
508061da546Spatrick                         "Continuing breakpoint %s as AutoContinue was set.",
509061da546Spatrick                         loc_desc.GetData());
510061da546Spatrick               // We want this stop reported, so you will know we auto-continued
511061da546Spatrick               // but only for external breakpoints:
512061da546Spatrick               if (!internal_breakpoint)
513061da546Spatrick                 thread_sp->SetShouldReportStop(eVoteYes);
514061da546Spatrick               auto_continue_says_stop = false;
515061da546Spatrick             }
516061da546Spatrick 
517061da546Spatrick             bool callback_says_stop = true;
518061da546Spatrick 
519061da546Spatrick             // FIXME: For now the callbacks have to run in async mode - the
520061da546Spatrick             // first time we restart we need
521061da546Spatrick             // to get out of there.  So set it here.
522061da546Spatrick             // When we figure out how to nest breakpoint hits then this will
523061da546Spatrick             // change.
524061da546Spatrick 
525be691f3bSpatrick             // Don't run async callbacks in PerformAction.  They have already
526be691f3bSpatrick             // been taken into account with async_should_stop.
527be691f3bSpatrick             if (!bp_loc_sp->IsCallbackSynchronous()) {
528061da546Spatrick               Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
529061da546Spatrick               bool old_async = debugger.GetAsyncExecution();
530061da546Spatrick               debugger.SetAsyncExecution(true);
531061da546Spatrick 
532061da546Spatrick               callback_says_stop = bp_loc_sp->InvokeCallback(&context);
533061da546Spatrick 
534061da546Spatrick               debugger.SetAsyncExecution(old_async);
535061da546Spatrick 
536061da546Spatrick               if (callback_says_stop && auto_continue_says_stop)
537061da546Spatrick                 m_should_stop = true;
538be691f3bSpatrick               else
539be691f3bSpatrick                 actually_said_continue = true;
540be691f3bSpatrick             }
541061da546Spatrick 
542061da546Spatrick             // If we are going to stop for this breakpoint, then remove the
543061da546Spatrick             // breakpoint.
544061da546Spatrick             if (callback_says_stop && bp_loc_sp &&
545061da546Spatrick                 bp_loc_sp->GetBreakpoint().IsOneShot()) {
546061da546Spatrick               thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(
547061da546Spatrick                   bp_loc_sp->GetBreakpoint().GetID());
548061da546Spatrick             }
549061da546Spatrick             // Also make sure that the callback hasn't continued the target. If
550061da546Spatrick             // it did, when we'll set m_should_start to false and get out of
551061da546Spatrick             // here.
552061da546Spatrick             if (HasTargetRunSinceMe()) {
553061da546Spatrick               m_should_stop = false;
554be691f3bSpatrick               actually_said_continue = true;
555061da546Spatrick               break;
556061da546Spatrick             }
557061da546Spatrick           }
558be691f3bSpatrick           // At this point if nobody actually told us to continue, we should
559be691f3bSpatrick           // give the async breakpoint callback a chance to weigh in:
560be691f3bSpatrick           if (!actually_said_continue && !m_should_stop) {
561be691f3bSpatrick             m_should_stop = async_should_stop;
562be691f3bSpatrick           }
563061da546Spatrick         }
564061da546Spatrick         // We've figured out what this stop wants to do, so mark it as valid so
565061da546Spatrick         // we don't compute it again.
566061da546Spatrick         m_should_stop_is_valid = true;
567061da546Spatrick       } else {
568061da546Spatrick         m_should_stop = true;
569061da546Spatrick         m_should_stop_is_valid = true;
570*f6aab3d8Srobert         actually_hit_any_locations = true;
571*f6aab3d8Srobert         Log *log_process(GetLog(LLDBLog::Process));
572061da546Spatrick 
573061da546Spatrick         LLDB_LOGF(log_process,
574061da546Spatrick                   "Process::%s could not find breakpoint site id: %" PRId64
575061da546Spatrick                   "...",
576061da546Spatrick                   __FUNCTION__, m_value);
577061da546Spatrick       }
578061da546Spatrick 
579061da546Spatrick       if ((!m_should_stop || internal_breakpoint) &&
580061da546Spatrick           thread_sp->CompletedPlanOverridesBreakpoint()) {
581061da546Spatrick 
582061da546Spatrick         // Override should_stop decision when we have completed step plan
583061da546Spatrick         // additionally to the breakpoint
584061da546Spatrick         m_should_stop = true;
585061da546Spatrick 
586061da546Spatrick         // We know we're stopping for a completed plan and we don't want to
587061da546Spatrick         // show the breakpoint stop, so compute the public stop info immediately
588061da546Spatrick         // here.
589061da546Spatrick         thread_sp->CalculatePublicStopInfo();
590*f6aab3d8Srobert       } else if (!actually_hit_any_locations) {
591*f6aab3d8Srobert         // In the end, we didn't actually have any locations that passed their
592*f6aab3d8Srobert         // "was I hit" checks.  So say we aren't stopped.
593*f6aab3d8Srobert         GetThread()->ResetStopInfo();
594*f6aab3d8Srobert         LLDB_LOGF(log, "Process::%s all locations failed condition checks.",
595*f6aab3d8Srobert           __FUNCTION__);
596061da546Spatrick       }
597061da546Spatrick 
598061da546Spatrick       LLDB_LOGF(log,
599061da546Spatrick                 "Process::%s returning from action with m_should_stop: %d.",
600061da546Spatrick                 __FUNCTION__, m_should_stop);
601061da546Spatrick     }
602061da546Spatrick   }
603061da546Spatrick 
604061da546Spatrick private:
605061da546Spatrick   bool m_should_stop;
606061da546Spatrick   bool m_should_stop_is_valid;
607061da546Spatrick   bool m_should_perform_action; // Since we are trying to preserve the "state"
608061da546Spatrick                                 // of the system even if we run functions
609061da546Spatrick   // etc. behind the users backs, we need to make sure we only REALLY perform
610061da546Spatrick   // the action once.
611061da546Spatrick   lldb::addr_t m_address; // We use this to capture the breakpoint site address
612061da546Spatrick                           // when we create the StopInfo,
613061da546Spatrick   // in case somebody deletes it between the time the StopInfo is made and the
614061da546Spatrick   // description is asked for.
615061da546Spatrick   lldb::break_id_t m_break_id;
616*f6aab3d8Srobert   bool m_was_all_internal;
617061da546Spatrick   bool m_was_one_shot;
618061da546Spatrick };
619061da546Spatrick 
620061da546Spatrick // StopInfoWatchpoint
621061da546Spatrick 
622061da546Spatrick class StopInfoWatchpoint : public StopInfo {
623061da546Spatrick public:
624061da546Spatrick   // Make sure watchpoint is properly disabled and subsequently enabled while
625061da546Spatrick   // performing watchpoint actions.
626061da546Spatrick   class WatchpointSentry {
627061da546Spatrick   public:
WatchpointSentry(ProcessSP p_sp,WatchpointSP w_sp)628061da546Spatrick     WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),
629061da546Spatrick                      watchpoint_sp(w_sp) {
630061da546Spatrick       if (process_sp && watchpoint_sp) {
631061da546Spatrick         const bool notify = false;
632061da546Spatrick         watchpoint_sp->TurnOnEphemeralMode();
633061da546Spatrick         process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
634061da546Spatrick         process_sp->AddPreResumeAction(SentryPreResumeAction, this);
635061da546Spatrick       }
636061da546Spatrick     }
637061da546Spatrick 
DoReenable()638061da546Spatrick     void DoReenable() {
639061da546Spatrick       if (process_sp && watchpoint_sp) {
640061da546Spatrick         bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();
641061da546Spatrick         watchpoint_sp->TurnOffEphemeralMode();
642061da546Spatrick         const bool notify = false;
643061da546Spatrick         if (was_disabled) {
644061da546Spatrick           process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
645061da546Spatrick         } else {
646061da546Spatrick           process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);
647061da546Spatrick         }
648061da546Spatrick       }
649061da546Spatrick     }
650061da546Spatrick 
~WatchpointSentry()651061da546Spatrick     ~WatchpointSentry() {
652061da546Spatrick         DoReenable();
653061da546Spatrick         if (process_sp)
654061da546Spatrick             process_sp->ClearPreResumeAction(SentryPreResumeAction, this);
655061da546Spatrick     }
656061da546Spatrick 
SentryPreResumeAction(void * sentry_void)657061da546Spatrick     static bool SentryPreResumeAction(void *sentry_void) {
658061da546Spatrick         WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;
659061da546Spatrick         sentry->DoReenable();
660061da546Spatrick         return true;
661061da546Spatrick     }
662061da546Spatrick 
663061da546Spatrick   private:
664061da546Spatrick     ProcessSP process_sp;
665061da546Spatrick     WatchpointSP watchpoint_sp;
666061da546Spatrick   };
667061da546Spatrick 
StopInfoWatchpoint(Thread & thread,break_id_t watch_id,lldb::addr_t watch_hit_addr)668061da546Spatrick   StopInfoWatchpoint(Thread &thread, break_id_t watch_id,
669061da546Spatrick                      lldb::addr_t watch_hit_addr)
670*f6aab3d8Srobert       : StopInfo(thread, watch_id), m_watch_hit_addr(watch_hit_addr) {}
671061da546Spatrick 
672061da546Spatrick   ~StopInfoWatchpoint() override = default;
673061da546Spatrick 
GetStopReason() const674061da546Spatrick   StopReason GetStopReason() const override { return eStopReasonWatchpoint; }
675061da546Spatrick 
GetDescription()676061da546Spatrick   const char *GetDescription() override {
677061da546Spatrick     if (m_description.empty()) {
678061da546Spatrick       StreamString strm;
679061da546Spatrick       strm.Printf("watchpoint %" PRIi64, m_value);
680dda28197Spatrick       m_description = std::string(strm.GetString());
681061da546Spatrick     }
682061da546Spatrick     return m_description.c_str();
683061da546Spatrick   }
684061da546Spatrick 
685061da546Spatrick protected:
686*f6aab3d8Srobert   using StopInfoWatchpointSP = std::shared_ptr<StopInfoWatchpoint>;
687*f6aab3d8Srobert   // This plan is used to orchestrate stepping over the watchpoint for
688*f6aab3d8Srobert   // architectures (e.g. ARM) that report the watch before running the watched
689*f6aab3d8Srobert   // access.  This is the sort of job you have to defer to the thread plans,
690*f6aab3d8Srobert   // if you try to do it directly in the stop info and there are other threads
691*f6aab3d8Srobert   // that needed to process this stop you will have yanked control away from
692*f6aab3d8Srobert   // them and they won't behave correctly.
693*f6aab3d8Srobert   class ThreadPlanStepOverWatchpoint : public ThreadPlanStepInstruction {
694*f6aab3d8Srobert   public:
ThreadPlanStepOverWatchpoint(Thread & thread,StopInfoWatchpointSP stop_info_sp,WatchpointSP watch_sp)695*f6aab3d8Srobert     ThreadPlanStepOverWatchpoint(Thread &thread,
696*f6aab3d8Srobert                                  StopInfoWatchpointSP stop_info_sp,
697*f6aab3d8Srobert                                  WatchpointSP watch_sp)
698*f6aab3d8Srobert         : ThreadPlanStepInstruction(thread, false, true, eVoteNoOpinion,
699*f6aab3d8Srobert                                     eVoteNoOpinion),
700*f6aab3d8Srobert           m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) {
701*f6aab3d8Srobert       assert(watch_sp);
702*f6aab3d8Srobert       m_watch_index = watch_sp->GetHardwareIndex();
703*f6aab3d8Srobert     }
704*f6aab3d8Srobert 
DoWillResume(lldb::StateType resume_state,bool current_plan)705*f6aab3d8Srobert     bool DoWillResume(lldb::StateType resume_state,
706*f6aab3d8Srobert                       bool current_plan) override {
707*f6aab3d8Srobert       if (resume_state == eStateSuspended)
708*f6aab3d8Srobert         return true;
709*f6aab3d8Srobert 
710*f6aab3d8Srobert       if (!m_did_disable_wp) {
711*f6aab3d8Srobert         GetThread().GetProcess()->DisableWatchpoint(m_watch_sp.get(), false);
712*f6aab3d8Srobert         m_did_disable_wp = true;
713*f6aab3d8Srobert       }
714*f6aab3d8Srobert       return true;
715*f6aab3d8Srobert     }
716*f6aab3d8Srobert 
DoPlanExplainsStop(Event * event_ptr)717*f6aab3d8Srobert     bool DoPlanExplainsStop(Event *event_ptr) override {
718*f6aab3d8Srobert       if (ThreadPlanStepInstruction::DoPlanExplainsStop(event_ptr))
719*f6aab3d8Srobert         return true;
720*f6aab3d8Srobert       StopInfoSP stop_info_sp = GetThread().GetPrivateStopInfo();
721*f6aab3d8Srobert       // lldb-server resets the stop info for threads that didn't get to run,
722*f6aab3d8Srobert       // so we might have not gotten to run, but still have a watchpoint stop
723*f6aab3d8Srobert       // reason, in which case this will indeed be for us.
724*f6aab3d8Srobert       if (stop_info_sp
725*f6aab3d8Srobert           && stop_info_sp->GetStopReason() == eStopReasonWatchpoint)
726*f6aab3d8Srobert         return true;
727*f6aab3d8Srobert       return false;
728*f6aab3d8Srobert     }
729*f6aab3d8Srobert 
DidPop()730*f6aab3d8Srobert     void DidPop() override {
731*f6aab3d8Srobert       // Don't artifically keep the watchpoint alive.
732*f6aab3d8Srobert       m_watch_sp.reset();
733*f6aab3d8Srobert     }
734*f6aab3d8Srobert 
ShouldStop(Event * event_ptr)735*f6aab3d8Srobert     bool ShouldStop(Event *event_ptr) override {
736*f6aab3d8Srobert       bool should_stop = ThreadPlanStepInstruction::ShouldStop(event_ptr);
737*f6aab3d8Srobert       bool plan_done = MischiefManaged();
738*f6aab3d8Srobert       if (plan_done) {
739*f6aab3d8Srobert         m_stop_info_sp->SetStepOverPlanComplete();
740*f6aab3d8Srobert         GetThread().SetStopInfo(m_stop_info_sp);
741*f6aab3d8Srobert         ResetWatchpoint();
742*f6aab3d8Srobert       }
743*f6aab3d8Srobert       return should_stop;
744*f6aab3d8Srobert     }
745*f6aab3d8Srobert 
ShouldRunBeforePublicStop()746*f6aab3d8Srobert     bool ShouldRunBeforePublicStop() override {
747*f6aab3d8Srobert         return true;
748*f6aab3d8Srobert     }
749*f6aab3d8Srobert 
750*f6aab3d8Srobert   protected:
ResetWatchpoint()751*f6aab3d8Srobert     void ResetWatchpoint() {
752*f6aab3d8Srobert       if (!m_did_disable_wp)
753*f6aab3d8Srobert         return;
754*f6aab3d8Srobert       m_did_disable_wp = true;
755*f6aab3d8Srobert       GetThread().GetProcess()->EnableWatchpoint(m_watch_sp.get(), true);
756*f6aab3d8Srobert       m_watch_sp->SetHardwareIndex(m_watch_index);
757*f6aab3d8Srobert     }
758*f6aab3d8Srobert 
759*f6aab3d8Srobert   private:
760*f6aab3d8Srobert     StopInfoWatchpointSP m_stop_info_sp;
761*f6aab3d8Srobert     WatchpointSP m_watch_sp;
762*f6aab3d8Srobert     uint32_t m_watch_index = LLDB_INVALID_INDEX32;
763*f6aab3d8Srobert     bool m_did_disable_wp = false;
764*f6aab3d8Srobert   };
765*f6aab3d8Srobert 
ShouldStopSynchronous(Event * event_ptr)766061da546Spatrick   bool ShouldStopSynchronous(Event *event_ptr) override {
767*f6aab3d8Srobert     // If we are running our step-over the watchpoint plan, stop if it's done
768*f6aab3d8Srobert     // and continue if it's not:
769061da546Spatrick     if (m_should_stop_is_valid)
770061da546Spatrick       return m_should_stop;
771061da546Spatrick 
772*f6aab3d8Srobert     // If we are running our step over plan, then stop here and let the regular
773*f6aab3d8Srobert     // ShouldStop figure out what we should do:  Otherwise, give our plan
774*f6aab3d8Srobert     // more time to get run:
775*f6aab3d8Srobert     if (m_using_step_over_plan)
776*f6aab3d8Srobert       return m_step_over_plan_complete;
777*f6aab3d8Srobert 
778*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Process);
779061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
780*f6aab3d8Srobert     assert(thread_sp);
781*f6aab3d8Srobert 
782*f6aab3d8Srobert     if (thread_sp->GetTemporaryResumeState() == eStateSuspended) {
783*f6aab3d8Srobert       // This is the second firing of a watchpoint so don't process it again.
784*f6aab3d8Srobert       LLDB_LOG(log, "We didn't run but stopped with a StopInfoWatchpoint, we "
785*f6aab3d8Srobert                "have already handled this one, don't do it again.");
786*f6aab3d8Srobert       m_should_stop = false;
787*f6aab3d8Srobert       m_should_stop_is_valid = true;
788*f6aab3d8Srobert       return m_should_stop;
789*f6aab3d8Srobert     }
790*f6aab3d8Srobert 
791061da546Spatrick     WatchpointSP wp_sp(
792*f6aab3d8Srobert         thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue()));
793*f6aab3d8Srobert     // If we can no longer find the watchpoint, we just have to stop:
794*f6aab3d8Srobert     if (!wp_sp) {
795061da546Spatrick 
796061da546Spatrick       LLDB_LOGF(log,
797061da546Spatrick                 "Process::%s could not find watchpoint location id: %" PRId64
798061da546Spatrick                 "...",
799061da546Spatrick                 __FUNCTION__, GetValue());
800061da546Spatrick 
801061da546Spatrick       m_should_stop = true;
802061da546Spatrick       m_should_stop_is_valid = true;
803*f6aab3d8Srobert       return true;
804*f6aab3d8Srobert     }
805*f6aab3d8Srobert 
806*f6aab3d8Srobert     ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
807*f6aab3d8Srobert     StoppointCallbackContext context(event_ptr, exe_ctx, true);
808*f6aab3d8Srobert     m_should_stop = wp_sp->ShouldStop(&context);
809*f6aab3d8Srobert     if (!m_should_stop) {
810*f6aab3d8Srobert       // This won't happen at present because we only allow one watchpoint per
811*f6aab3d8Srobert       // watched range.  So we won't stop at a watched address with a disabled
812*f6aab3d8Srobert       // watchpoint.  If we start allowing overlapping watchpoints, then we
813*f6aab3d8Srobert       // will have to make watchpoints be real "WatchpointSite" and delegate to
814*f6aab3d8Srobert       // all the watchpoints sharing the site.  In that case, the code below
815*f6aab3d8Srobert       // would be the right thing to do.
816*f6aab3d8Srobert       m_should_stop_is_valid = true;
817*f6aab3d8Srobert       return m_should_stop;
818*f6aab3d8Srobert     }
819*f6aab3d8Srobert     // If this is a system where we need to execute the watchpoint by hand
820*f6aab3d8Srobert     // after the hit, queue a thread plan to do that, and then say not to stop.
821*f6aab3d8Srobert     // Otherwise, let the async action figure out whether the watchpoint should
822*f6aab3d8Srobert     // stop
823*f6aab3d8Srobert 
824*f6aab3d8Srobert     ProcessSP process_sp = exe_ctx.GetProcessSP();
825*f6aab3d8Srobert     uint32_t num;
826*f6aab3d8Srobert     bool wp_triggers_after;
827*f6aab3d8Srobert 
828*f6aab3d8Srobert     if (!process_sp->GetWatchpointSupportInfo(num, wp_triggers_after)
829*f6aab3d8Srobert             .Success()) {
830*f6aab3d8Srobert       m_should_stop_is_valid = true;
831*f6aab3d8Srobert       m_should_stop = true;
832*f6aab3d8Srobert       return m_should_stop;
833*f6aab3d8Srobert     }
834*f6aab3d8Srobert 
835*f6aab3d8Srobert     if (!wp_triggers_after) {
836*f6aab3d8Srobert       // We have to step over the watchpoint before we know what to do:
837*f6aab3d8Srobert       StopInfoWatchpointSP me_as_siwp_sp
838*f6aab3d8Srobert           = std::static_pointer_cast<StopInfoWatchpoint>(shared_from_this());
839*f6aab3d8Srobert       ThreadPlanSP step_over_wp_sp(new ThreadPlanStepOverWatchpoint(
840*f6aab3d8Srobert           *(thread_sp.get()), me_as_siwp_sp, wp_sp));
841*f6aab3d8Srobert       Status error;
842*f6aab3d8Srobert       error = thread_sp->QueueThreadPlan(step_over_wp_sp, false);
843*f6aab3d8Srobert       // If we couldn't push the thread plan, just stop here:
844*f6aab3d8Srobert       if (!error.Success()) {
845*f6aab3d8Srobert         LLDB_LOGF(log, "Could not push our step over watchpoint plan: %s",
846*f6aab3d8Srobert             error.AsCString());
847*f6aab3d8Srobert 
848*f6aab3d8Srobert         m_should_stop = true;
849*f6aab3d8Srobert         m_should_stop_is_valid = true;
850*f6aab3d8Srobert         return true;
851*f6aab3d8Srobert       } else {
852*f6aab3d8Srobert       // Otherwise, don't set m_should_stop, we don't know that yet.  Just
853*f6aab3d8Srobert       // say we should continue, and tell the thread we really should do so:
854*f6aab3d8Srobert         thread_sp->SetShouldRunBeforePublicStop(true);
855*f6aab3d8Srobert         m_using_step_over_plan = true;
856*f6aab3d8Srobert         return false;
857*f6aab3d8Srobert       }
858*f6aab3d8Srobert     } else {
859*f6aab3d8Srobert       // We didn't have to do anything special
860*f6aab3d8Srobert       m_should_stop_is_valid = true;
861*f6aab3d8Srobert       return m_should_stop;
862*f6aab3d8Srobert     }
863*f6aab3d8Srobert 
864061da546Spatrick     return m_should_stop;
865061da546Spatrick   }
866061da546Spatrick 
ShouldStop(Event * event_ptr)867061da546Spatrick   bool ShouldStop(Event *event_ptr) override {
868061da546Spatrick     // This just reports the work done by PerformAction or the synchronous
869061da546Spatrick     // stop. It should only ever get called after they have had a chance to
870061da546Spatrick     // run.
871061da546Spatrick     assert(m_should_stop_is_valid);
872061da546Spatrick     return m_should_stop;
873061da546Spatrick   }
874061da546Spatrick 
PerformAction(Event * event_ptr)875061da546Spatrick   void PerformAction(Event *event_ptr) override {
876*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Watchpoints);
877061da546Spatrick     // We're going to calculate if we should stop or not in some way during the
878061da546Spatrick     // course of this code.  Also by default we're going to stop, so set that
879061da546Spatrick     // here.
880061da546Spatrick     m_should_stop = true;
881061da546Spatrick 
882061da546Spatrick 
883061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
884061da546Spatrick     if (thread_sp) {
885061da546Spatrick 
886061da546Spatrick       WatchpointSP wp_sp(
887061da546Spatrick           thread_sp->CalculateTarget()->GetWatchpointList().FindByID(
888061da546Spatrick               GetValue()));
889061da546Spatrick       if (wp_sp) {
890061da546Spatrick         // This sentry object makes sure the current watchpoint is disabled
891061da546Spatrick         // while performing watchpoint actions, and it is then enabled after we
892061da546Spatrick         // are finished.
893*f6aab3d8Srobert         ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
894*f6aab3d8Srobert         ProcessSP process_sp = exe_ctx.GetProcessSP();
895*f6aab3d8Srobert 
896061da546Spatrick         WatchpointSentry sentry(process_sp, wp_sp);
897061da546Spatrick 
898061da546Spatrick         /*
899061da546Spatrick          * MIPS: Last 3bits of the watchpoint address are masked by the kernel.
900061da546Spatrick          * For example:
901061da546Spatrick          * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is
902061da546Spatrick          * set at 'm', then
903061da546Spatrick          * watch exception is generated even when 'n' is read/written. To handle
904061da546Spatrick          * this case,
905061da546Spatrick          * server emulates the instruction at PC and finds the base address of
906061da546Spatrick          * the load/store
907061da546Spatrick          * instruction and appends it in the description of the stop-info
908061da546Spatrick          * packet. If watchpoint
909061da546Spatrick          * is not set on this address by user then this do not stop.
910061da546Spatrick         */
911061da546Spatrick         if (m_watch_hit_addr != LLDB_INVALID_ADDRESS) {
912061da546Spatrick           WatchpointSP wp_hit_sp =
913061da546Spatrick               thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress(
914061da546Spatrick                   m_watch_hit_addr);
915061da546Spatrick           if (!wp_hit_sp) {
916061da546Spatrick             m_should_stop = false;
917061da546Spatrick             wp_sp->IncrementFalseAlarmsAndReviseHitCount();
918061da546Spatrick           }
919061da546Spatrick         }
920061da546Spatrick 
921*f6aab3d8Srobert         if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) {
922061da546Spatrick           m_should_stop = false;
923*f6aab3d8Srobert           m_should_stop_is_valid = true;
924*f6aab3d8Srobert         }
925061da546Spatrick 
926061da546Spatrick         Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
927061da546Spatrick 
928061da546Spatrick         if (m_should_stop && wp_sp->GetConditionText() != nullptr) {
929061da546Spatrick           // We need to make sure the user sees any parse errors in their
930061da546Spatrick           // condition, so we'll hook the constructor errors up to the
931061da546Spatrick           // debugger's Async I/O.
932061da546Spatrick           ExpressionResults result_code;
933061da546Spatrick           EvaluateExpressionOptions expr_options;
934061da546Spatrick           expr_options.SetUnwindOnError(true);
935061da546Spatrick           expr_options.SetIgnoreBreakpoints(true);
936061da546Spatrick           ValueObjectSP result_value_sp;
937061da546Spatrick           Status error;
938061da546Spatrick           result_code = UserExpression::Evaluate(
939061da546Spatrick               exe_ctx, expr_options, wp_sp->GetConditionText(),
940061da546Spatrick               llvm::StringRef(), result_value_sp, error);
941061da546Spatrick 
942061da546Spatrick           if (result_code == eExpressionCompleted) {
943061da546Spatrick             if (result_value_sp) {
944061da546Spatrick               Scalar scalar_value;
945061da546Spatrick               if (result_value_sp->ResolveValue(scalar_value)) {
946061da546Spatrick                 if (scalar_value.ULongLong(1) == 0) {
947*f6aab3d8Srobert                   // The condition failed, which we consider "not having hit
948*f6aab3d8Srobert                   // the watchpoint" so undo the hit count here.
949*f6aab3d8Srobert                   wp_sp->UndoHitCount();
950061da546Spatrick                   m_should_stop = false;
951061da546Spatrick                 } else
952061da546Spatrick                   m_should_stop = true;
953061da546Spatrick                 LLDB_LOGF(log,
954061da546Spatrick                           "Condition successfully evaluated, result is %s.\n",
955061da546Spatrick                           m_should_stop ? "true" : "false");
956061da546Spatrick               } else {
957061da546Spatrick                 m_should_stop = true;
958061da546Spatrick                 LLDB_LOGF(
959061da546Spatrick                     log,
960061da546Spatrick                     "Failed to get an integer result from the expression.");
961061da546Spatrick               }
962061da546Spatrick             }
963061da546Spatrick           } else {
964*f6aab3d8Srobert             const char *err_str = error.AsCString("<unknown error>");
965061da546Spatrick             LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);
966061da546Spatrick 
967*f6aab3d8Srobert             StreamString strm;
968*f6aab3d8Srobert             strm << "stopped due to an error evaluating condition of "
969*f6aab3d8Srobert                     "watchpoint ";
970*f6aab3d8Srobert             wp_sp->GetDescription(&strm, eDescriptionLevelBrief);
971*f6aab3d8Srobert             strm << ": \"" << wp_sp->GetConditionText() << "\"\n";
972*f6aab3d8Srobert             strm << err_str;
973*f6aab3d8Srobert 
974*f6aab3d8Srobert             Debugger::ReportError(strm.GetString().str(),
975*f6aab3d8Srobert                                   exe_ctx.GetTargetRef().GetDebugger().GetID());
976061da546Spatrick           }
977061da546Spatrick         }
978061da546Spatrick 
979061da546Spatrick         // If the condition says to stop, we run the callback to further decide
980061da546Spatrick         // whether to stop.
981061da546Spatrick         if (m_should_stop) {
982061da546Spatrick             // FIXME: For now the callbacks have to run in async mode - the
983061da546Spatrick             // first time we restart we need
984061da546Spatrick             // to get out of there.  So set it here.
985061da546Spatrick             // When we figure out how to nest watchpoint hits then this will
986061da546Spatrick             // change.
987061da546Spatrick 
988061da546Spatrick           bool old_async = debugger.GetAsyncExecution();
989061da546Spatrick           debugger.SetAsyncExecution(true);
990061da546Spatrick 
991061da546Spatrick           StoppointCallbackContext context(event_ptr, exe_ctx, false);
992061da546Spatrick           bool stop_requested = wp_sp->InvokeCallback(&context);
993061da546Spatrick 
994061da546Spatrick           debugger.SetAsyncExecution(old_async);
995061da546Spatrick 
996061da546Spatrick           // Also make sure that the callback hasn't continued the target. If
997061da546Spatrick           // it did, when we'll set m_should_stop to false and get out of here.
998061da546Spatrick           if (HasTargetRunSinceMe())
999061da546Spatrick             m_should_stop = false;
1000061da546Spatrick 
1001061da546Spatrick           if (m_should_stop && !stop_requested) {
1002061da546Spatrick             // We have been vetoed by the callback mechanism.
1003061da546Spatrick             m_should_stop = false;
1004061da546Spatrick           }
1005061da546Spatrick         }
1006061da546Spatrick         // Finally, if we are going to stop, print out the new & old values:
1007061da546Spatrick         if (m_should_stop) {
1008061da546Spatrick           wp_sp->CaptureWatchedValue(exe_ctx);
1009061da546Spatrick 
1010061da546Spatrick           Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
1011061da546Spatrick           StreamSP output_sp = debugger.GetAsyncOutputStream();
1012061da546Spatrick           wp_sp->DumpSnapshots(output_sp.get());
1013061da546Spatrick           output_sp->EOL();
1014061da546Spatrick           output_sp->Flush();
1015061da546Spatrick         }
1016061da546Spatrick 
1017061da546Spatrick       } else {
1018*f6aab3d8Srobert         Log *log_process(GetLog(LLDBLog::Process));
1019061da546Spatrick 
1020061da546Spatrick         LLDB_LOGF(log_process,
1021061da546Spatrick                   "Process::%s could not find watchpoint id: %" PRId64 "...",
1022061da546Spatrick                   __FUNCTION__, m_value);
1023061da546Spatrick       }
1024061da546Spatrick       LLDB_LOGF(log,
1025061da546Spatrick                 "Process::%s returning from action with m_should_stop: %d.",
1026061da546Spatrick                 __FUNCTION__, m_should_stop);
1027061da546Spatrick 
1028061da546Spatrick       m_should_stop_is_valid = true;
1029061da546Spatrick     }
1030061da546Spatrick   }
1031061da546Spatrick 
1032061da546Spatrick private:
SetStepOverPlanComplete()1033*f6aab3d8Srobert   void SetStepOverPlanComplete() {
1034*f6aab3d8Srobert     assert(m_using_step_over_plan);
1035*f6aab3d8Srobert     m_step_over_plan_complete = true;
1036*f6aab3d8Srobert   }
1037*f6aab3d8Srobert 
1038*f6aab3d8Srobert   bool m_should_stop = false;
1039*f6aab3d8Srobert   bool m_should_stop_is_valid = false;
1040061da546Spatrick   lldb::addr_t m_watch_hit_addr;
1041*f6aab3d8Srobert   bool m_step_over_plan_complete = false;
1042*f6aab3d8Srobert   bool m_using_step_over_plan = false;
1043061da546Spatrick };
1044061da546Spatrick 
1045061da546Spatrick // StopInfoUnixSignal
1046061da546Spatrick 
1047061da546Spatrick class StopInfoUnixSignal : public StopInfo {
1048061da546Spatrick public:
StopInfoUnixSignal(Thread & thread,int signo,const char * description)1049061da546Spatrick   StopInfoUnixSignal(Thread &thread, int signo, const char *description)
1050061da546Spatrick       : StopInfo(thread, signo) {
1051061da546Spatrick     SetDescription(description);
1052061da546Spatrick   }
1053061da546Spatrick 
1054061da546Spatrick   ~StopInfoUnixSignal() override = default;
1055061da546Spatrick 
GetStopReason() const1056061da546Spatrick   StopReason GetStopReason() const override { return eStopReasonSignal; }
1057061da546Spatrick 
ShouldStopSynchronous(Event * event_ptr)1058061da546Spatrick   bool ShouldStopSynchronous(Event *event_ptr) override {
1059061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
1060061da546Spatrick     if (thread_sp)
1061061da546Spatrick       return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
1062061da546Spatrick     return false;
1063061da546Spatrick   }
1064061da546Spatrick 
ShouldStop(Event * event_ptr)1065061da546Spatrick   bool ShouldStop(Event *event_ptr) override {
1066061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
1067061da546Spatrick     if (thread_sp)
1068061da546Spatrick       return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
1069061da546Spatrick     return false;
1070061da546Spatrick   }
1071061da546Spatrick 
1072061da546Spatrick   // If should stop returns false, check if we should notify of this event
DoShouldNotify(Event * event_ptr)1073061da546Spatrick   bool DoShouldNotify(Event *event_ptr) override {
1074061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
1075061da546Spatrick     if (thread_sp) {
1076061da546Spatrick       bool should_notify =
1077061da546Spatrick           thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value);
1078061da546Spatrick       if (should_notify) {
1079061da546Spatrick         StreamString strm;
1080061da546Spatrick         strm.Printf(
1081061da546Spatrick             "thread %d received signal: %s", thread_sp->GetIndexID(),
1082061da546Spatrick             thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(
1083061da546Spatrick                 m_value));
1084061da546Spatrick         Process::ProcessEventData::AddRestartedReason(event_ptr,
1085061da546Spatrick                                                       strm.GetData());
1086061da546Spatrick       }
1087061da546Spatrick       return should_notify;
1088061da546Spatrick     }
1089061da546Spatrick     return true;
1090061da546Spatrick   }
1091061da546Spatrick 
WillResume(lldb::StateType resume_state)1092061da546Spatrick   void WillResume(lldb::StateType resume_state) override {
1093061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
1094061da546Spatrick     if (thread_sp) {
1095061da546Spatrick       if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(
1096061da546Spatrick               m_value))
1097061da546Spatrick         thread_sp->SetResumeSignal(m_value);
1098061da546Spatrick     }
1099061da546Spatrick   }
1100061da546Spatrick 
GetDescription()1101061da546Spatrick   const char *GetDescription() override {
1102061da546Spatrick     if (m_description.empty()) {
1103061da546Spatrick       ThreadSP thread_sp(m_thread_wp.lock());
1104061da546Spatrick       if (thread_sp) {
1105061da546Spatrick         StreamString strm;
1106061da546Spatrick         const char *signal_name =
1107061da546Spatrick             thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(
1108061da546Spatrick                 m_value);
1109061da546Spatrick         if (signal_name)
1110061da546Spatrick           strm.Printf("signal %s", signal_name);
1111061da546Spatrick         else
1112061da546Spatrick           strm.Printf("signal %" PRIi64, m_value);
1113dda28197Spatrick         m_description = std::string(strm.GetString());
1114061da546Spatrick       }
1115061da546Spatrick     }
1116061da546Spatrick     return m_description.c_str();
1117061da546Spatrick   }
1118061da546Spatrick };
1119061da546Spatrick 
1120061da546Spatrick // StopInfoTrace
1121061da546Spatrick 
1122061da546Spatrick class StopInfoTrace : public StopInfo {
1123061da546Spatrick public:
StopInfoTrace(Thread & thread)1124061da546Spatrick   StopInfoTrace(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}
1125061da546Spatrick 
1126061da546Spatrick   ~StopInfoTrace() override = default;
1127061da546Spatrick 
GetStopReason() const1128061da546Spatrick   StopReason GetStopReason() const override { return eStopReasonTrace; }
1129061da546Spatrick 
GetDescription()1130061da546Spatrick   const char *GetDescription() override {
1131061da546Spatrick     if (m_description.empty())
1132061da546Spatrick       return "trace";
1133061da546Spatrick     else
1134061da546Spatrick       return m_description.c_str();
1135061da546Spatrick   }
1136061da546Spatrick };
1137061da546Spatrick 
1138061da546Spatrick // StopInfoException
1139061da546Spatrick 
1140061da546Spatrick class StopInfoException : public StopInfo {
1141061da546Spatrick public:
StopInfoException(Thread & thread,const char * description)1142061da546Spatrick   StopInfoException(Thread &thread, const char *description)
1143061da546Spatrick       : StopInfo(thread, LLDB_INVALID_UID) {
1144061da546Spatrick     if (description)
1145061da546Spatrick       SetDescription(description);
1146061da546Spatrick   }
1147061da546Spatrick 
1148061da546Spatrick   ~StopInfoException() override = default;
1149061da546Spatrick 
GetStopReason() const1150061da546Spatrick   StopReason GetStopReason() const override { return eStopReasonException; }
1151061da546Spatrick 
GetDescription()1152061da546Spatrick   const char *GetDescription() override {
1153061da546Spatrick     if (m_description.empty())
1154061da546Spatrick       return "exception";
1155061da546Spatrick     else
1156061da546Spatrick       return m_description.c_str();
1157061da546Spatrick   }
1158061da546Spatrick };
1159061da546Spatrick 
1160be691f3bSpatrick // StopInfoProcessorTrace
1161be691f3bSpatrick 
1162be691f3bSpatrick class StopInfoProcessorTrace : public StopInfo {
1163be691f3bSpatrick public:
StopInfoProcessorTrace(Thread & thread,const char * description)1164be691f3bSpatrick   StopInfoProcessorTrace(Thread &thread, const char *description)
1165be691f3bSpatrick       : StopInfo(thread, LLDB_INVALID_UID) {
1166be691f3bSpatrick     if (description)
1167be691f3bSpatrick       SetDescription(description);
1168be691f3bSpatrick   }
1169be691f3bSpatrick 
1170be691f3bSpatrick   ~StopInfoProcessorTrace() override = default;
1171be691f3bSpatrick 
GetStopReason() const1172be691f3bSpatrick   StopReason GetStopReason() const override {
1173be691f3bSpatrick     return eStopReasonProcessorTrace;
1174be691f3bSpatrick   }
1175be691f3bSpatrick 
GetDescription()1176be691f3bSpatrick   const char *GetDescription() override {
1177be691f3bSpatrick     if (m_description.empty())
1178be691f3bSpatrick       return "processor trace event";
1179be691f3bSpatrick     else
1180be691f3bSpatrick       return m_description.c_str();
1181be691f3bSpatrick   }
1182be691f3bSpatrick };
1183be691f3bSpatrick 
1184061da546Spatrick // StopInfoThreadPlan
1185061da546Spatrick 
1186061da546Spatrick class StopInfoThreadPlan : public StopInfo {
1187061da546Spatrick public:
StopInfoThreadPlan(ThreadPlanSP & plan_sp,ValueObjectSP & return_valobj_sp,ExpressionVariableSP & expression_variable_sp)1188061da546Spatrick   StopInfoThreadPlan(ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp,
1189061da546Spatrick                      ExpressionVariableSP &expression_variable_sp)
1190061da546Spatrick       : StopInfo(plan_sp->GetThread(), LLDB_INVALID_UID), m_plan_sp(plan_sp),
1191061da546Spatrick         m_return_valobj_sp(return_valobj_sp),
1192061da546Spatrick         m_expression_variable_sp(expression_variable_sp) {}
1193061da546Spatrick 
1194061da546Spatrick   ~StopInfoThreadPlan() override = default;
1195061da546Spatrick 
GetStopReason() const1196061da546Spatrick   StopReason GetStopReason() const override { return eStopReasonPlanComplete; }
1197061da546Spatrick 
GetDescription()1198061da546Spatrick   const char *GetDescription() override {
1199061da546Spatrick     if (m_description.empty()) {
1200061da546Spatrick       StreamString strm;
1201061da546Spatrick       m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief);
1202dda28197Spatrick       m_description = std::string(strm.GetString());
1203061da546Spatrick     }
1204061da546Spatrick     return m_description.c_str();
1205061da546Spatrick   }
1206061da546Spatrick 
GetReturnValueObject()1207061da546Spatrick   ValueObjectSP GetReturnValueObject() { return m_return_valobj_sp; }
1208061da546Spatrick 
GetExpressionVariable()1209061da546Spatrick   ExpressionVariableSP GetExpressionVariable() {
1210061da546Spatrick     return m_expression_variable_sp;
1211061da546Spatrick   }
1212061da546Spatrick 
1213061da546Spatrick protected:
ShouldStop(Event * event_ptr)1214061da546Spatrick   bool ShouldStop(Event *event_ptr) override {
1215061da546Spatrick     if (m_plan_sp)
1216061da546Spatrick       return m_plan_sp->ShouldStop(event_ptr);
1217061da546Spatrick     else
1218061da546Spatrick       return StopInfo::ShouldStop(event_ptr);
1219061da546Spatrick   }
1220061da546Spatrick 
1221061da546Spatrick private:
1222061da546Spatrick   ThreadPlanSP m_plan_sp;
1223061da546Spatrick   ValueObjectSP m_return_valobj_sp;
1224061da546Spatrick   ExpressionVariableSP m_expression_variable_sp;
1225061da546Spatrick };
1226061da546Spatrick 
1227061da546Spatrick // StopInfoExec
1228061da546Spatrick 
1229061da546Spatrick class StopInfoExec : public StopInfo {
1230061da546Spatrick public:
StopInfoExec(Thread & thread)1231*f6aab3d8Srobert   StopInfoExec(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}
1232061da546Spatrick 
1233061da546Spatrick   ~StopInfoExec() override = default;
1234061da546Spatrick 
ShouldStop(Event * event_ptr)1235061da546Spatrick   bool ShouldStop(Event *event_ptr) override {
1236061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
1237061da546Spatrick     if (thread_sp)
1238061da546Spatrick       return thread_sp->GetProcess()->GetStopOnExec();
1239061da546Spatrick     return false;
1240061da546Spatrick   }
1241061da546Spatrick 
GetStopReason() const1242061da546Spatrick   StopReason GetStopReason() const override { return eStopReasonExec; }
1243061da546Spatrick 
GetDescription()1244061da546Spatrick   const char *GetDescription() override { return "exec"; }
1245061da546Spatrick 
1246061da546Spatrick protected:
PerformAction(Event * event_ptr)1247061da546Spatrick   void PerformAction(Event *event_ptr) override {
1248061da546Spatrick     // Only perform the action once
1249061da546Spatrick     if (m_performed_action)
1250061da546Spatrick       return;
1251061da546Spatrick     m_performed_action = true;
1252061da546Spatrick     ThreadSP thread_sp(m_thread_wp.lock());
1253061da546Spatrick     if (thread_sp)
1254061da546Spatrick       thread_sp->GetProcess()->DidExec();
1255061da546Spatrick   }
1256061da546Spatrick 
1257*f6aab3d8Srobert   bool m_performed_action = false;
1258*f6aab3d8Srobert };
1259*f6aab3d8Srobert 
1260*f6aab3d8Srobert // StopInfoFork
1261*f6aab3d8Srobert 
1262*f6aab3d8Srobert class StopInfoFork : public StopInfo {
1263*f6aab3d8Srobert public:
StopInfoFork(Thread & thread,lldb::pid_t child_pid,lldb::tid_t child_tid)1264*f6aab3d8Srobert   StopInfoFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)
1265*f6aab3d8Srobert       : StopInfo(thread, child_pid), m_child_pid(child_pid),
1266*f6aab3d8Srobert         m_child_tid(child_tid) {}
1267*f6aab3d8Srobert 
1268*f6aab3d8Srobert   ~StopInfoFork() override = default;
1269*f6aab3d8Srobert 
ShouldStop(Event * event_ptr)1270*f6aab3d8Srobert   bool ShouldStop(Event *event_ptr) override { return false; }
1271*f6aab3d8Srobert 
GetStopReason() const1272*f6aab3d8Srobert   StopReason GetStopReason() const override { return eStopReasonFork; }
1273*f6aab3d8Srobert 
GetDescription()1274*f6aab3d8Srobert   const char *GetDescription() override { return "fork"; }
1275*f6aab3d8Srobert 
1276*f6aab3d8Srobert protected:
PerformAction(Event * event_ptr)1277*f6aab3d8Srobert   void PerformAction(Event *event_ptr) override {
1278*f6aab3d8Srobert     // Only perform the action once
1279*f6aab3d8Srobert     if (m_performed_action)
1280*f6aab3d8Srobert       return;
1281*f6aab3d8Srobert     m_performed_action = true;
1282*f6aab3d8Srobert     ThreadSP thread_sp(m_thread_wp.lock());
1283*f6aab3d8Srobert     if (thread_sp)
1284*f6aab3d8Srobert       thread_sp->GetProcess()->DidFork(m_child_pid, m_child_tid);
1285*f6aab3d8Srobert   }
1286*f6aab3d8Srobert 
1287*f6aab3d8Srobert   bool m_performed_action = false;
1288*f6aab3d8Srobert 
1289*f6aab3d8Srobert private:
1290*f6aab3d8Srobert   lldb::pid_t m_child_pid;
1291*f6aab3d8Srobert   lldb::tid_t m_child_tid;
1292*f6aab3d8Srobert };
1293*f6aab3d8Srobert 
1294*f6aab3d8Srobert // StopInfoVFork
1295*f6aab3d8Srobert 
1296*f6aab3d8Srobert class StopInfoVFork : public StopInfo {
1297*f6aab3d8Srobert public:
StopInfoVFork(Thread & thread,lldb::pid_t child_pid,lldb::tid_t child_tid)1298*f6aab3d8Srobert   StopInfoVFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)
1299*f6aab3d8Srobert       : StopInfo(thread, child_pid), m_child_pid(child_pid),
1300*f6aab3d8Srobert         m_child_tid(child_tid) {}
1301*f6aab3d8Srobert 
1302*f6aab3d8Srobert   ~StopInfoVFork() override = default;
1303*f6aab3d8Srobert 
ShouldStop(Event * event_ptr)1304*f6aab3d8Srobert   bool ShouldStop(Event *event_ptr) override { return false; }
1305*f6aab3d8Srobert 
GetStopReason() const1306*f6aab3d8Srobert   StopReason GetStopReason() const override { return eStopReasonVFork; }
1307*f6aab3d8Srobert 
GetDescription()1308*f6aab3d8Srobert   const char *GetDescription() override { return "vfork"; }
1309*f6aab3d8Srobert 
1310*f6aab3d8Srobert protected:
PerformAction(Event * event_ptr)1311*f6aab3d8Srobert   void PerformAction(Event *event_ptr) override {
1312*f6aab3d8Srobert     // Only perform the action once
1313*f6aab3d8Srobert     if (m_performed_action)
1314*f6aab3d8Srobert       return;
1315*f6aab3d8Srobert     m_performed_action = true;
1316*f6aab3d8Srobert     ThreadSP thread_sp(m_thread_wp.lock());
1317*f6aab3d8Srobert     if (thread_sp)
1318*f6aab3d8Srobert       thread_sp->GetProcess()->DidVFork(m_child_pid, m_child_tid);
1319*f6aab3d8Srobert   }
1320*f6aab3d8Srobert 
1321*f6aab3d8Srobert   bool m_performed_action = false;
1322*f6aab3d8Srobert 
1323*f6aab3d8Srobert private:
1324*f6aab3d8Srobert   lldb::pid_t m_child_pid;
1325*f6aab3d8Srobert   lldb::tid_t m_child_tid;
1326*f6aab3d8Srobert };
1327*f6aab3d8Srobert 
1328*f6aab3d8Srobert // StopInfoVForkDone
1329*f6aab3d8Srobert 
1330*f6aab3d8Srobert class StopInfoVForkDone : public StopInfo {
1331*f6aab3d8Srobert public:
StopInfoVForkDone(Thread & thread)1332*f6aab3d8Srobert   StopInfoVForkDone(Thread &thread) : StopInfo(thread, 0) {}
1333*f6aab3d8Srobert 
1334*f6aab3d8Srobert   ~StopInfoVForkDone() override = default;
1335*f6aab3d8Srobert 
ShouldStop(Event * event_ptr)1336*f6aab3d8Srobert   bool ShouldStop(Event *event_ptr) override { return false; }
1337*f6aab3d8Srobert 
GetStopReason() const1338*f6aab3d8Srobert   StopReason GetStopReason() const override { return eStopReasonVForkDone; }
1339*f6aab3d8Srobert 
GetDescription()1340*f6aab3d8Srobert   const char *GetDescription() override { return "vforkdone"; }
1341*f6aab3d8Srobert 
1342*f6aab3d8Srobert protected:
PerformAction(Event * event_ptr)1343*f6aab3d8Srobert   void PerformAction(Event *event_ptr) override {
1344*f6aab3d8Srobert     // Only perform the action once
1345*f6aab3d8Srobert     if (m_performed_action)
1346*f6aab3d8Srobert       return;
1347*f6aab3d8Srobert     m_performed_action = true;
1348*f6aab3d8Srobert     ThreadSP thread_sp(m_thread_wp.lock());
1349*f6aab3d8Srobert     if (thread_sp)
1350*f6aab3d8Srobert       thread_sp->GetProcess()->DidVForkDone();
1351*f6aab3d8Srobert   }
1352*f6aab3d8Srobert 
1353*f6aab3d8Srobert   bool m_performed_action = false;
1354061da546Spatrick };
1355061da546Spatrick 
1356061da546Spatrick } // namespace lldb_private
1357061da546Spatrick 
CreateStopReasonWithBreakpointSiteID(Thread & thread,break_id_t break_id)1358061da546Spatrick StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
1359061da546Spatrick                                                           break_id_t break_id) {
1360061da546Spatrick   return StopInfoSP(new StopInfoBreakpoint(thread, break_id));
1361061da546Spatrick }
1362061da546Spatrick 
CreateStopReasonWithBreakpointSiteID(Thread & thread,break_id_t break_id,bool should_stop)1363061da546Spatrick StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
1364061da546Spatrick                                                           break_id_t break_id,
1365061da546Spatrick                                                           bool should_stop) {
1366061da546Spatrick   return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));
1367061da546Spatrick }
1368061da546Spatrick 
1369061da546Spatrick StopInfoSP
CreateStopReasonWithWatchpointID(Thread & thread,break_id_t watch_id,lldb::addr_t watch_hit_addr)1370061da546Spatrick StopInfo::CreateStopReasonWithWatchpointID(Thread &thread, break_id_t watch_id,
1371061da546Spatrick                                            lldb::addr_t watch_hit_addr) {
1372061da546Spatrick   return StopInfoSP(new StopInfoWatchpoint(thread, watch_id, watch_hit_addr));
1373061da546Spatrick }
1374061da546Spatrick 
CreateStopReasonWithSignal(Thread & thread,int signo,const char * description)1375061da546Spatrick StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
1376061da546Spatrick                                                 const char *description) {
1377*f6aab3d8Srobert   thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);
1378061da546Spatrick   return StopInfoSP(new StopInfoUnixSignal(thread, signo, description));
1379061da546Spatrick }
1380061da546Spatrick 
CreateStopReasonToTrace(Thread & thread)1381061da546Spatrick StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {
1382061da546Spatrick   return StopInfoSP(new StopInfoTrace(thread));
1383061da546Spatrick }
1384061da546Spatrick 
CreateStopReasonWithPlan(ThreadPlanSP & plan_sp,ValueObjectSP return_valobj_sp,ExpressionVariableSP expression_variable_sp)1385061da546Spatrick StopInfoSP StopInfo::CreateStopReasonWithPlan(
1386061da546Spatrick     ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp,
1387061da546Spatrick     ExpressionVariableSP expression_variable_sp) {
1388061da546Spatrick   return StopInfoSP(new StopInfoThreadPlan(plan_sp, return_valobj_sp,
1389061da546Spatrick                                            expression_variable_sp));
1390061da546Spatrick }
1391061da546Spatrick 
CreateStopReasonWithException(Thread & thread,const char * description)1392061da546Spatrick StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread,
1393061da546Spatrick                                                    const char *description) {
1394061da546Spatrick   return StopInfoSP(new StopInfoException(thread, description));
1395061da546Spatrick }
1396061da546Spatrick 
CreateStopReasonProcessorTrace(Thread & thread,const char * description)1397be691f3bSpatrick StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,
1398be691f3bSpatrick                                                     const char *description) {
1399be691f3bSpatrick   return StopInfoSP(new StopInfoProcessorTrace(thread, description));
1400be691f3bSpatrick }
1401be691f3bSpatrick 
CreateStopReasonWithExec(Thread & thread)1402061da546Spatrick StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {
1403061da546Spatrick   return StopInfoSP(new StopInfoExec(thread));
1404061da546Spatrick }
1405061da546Spatrick 
CreateStopReasonFork(Thread & thread,lldb::pid_t child_pid,lldb::tid_t child_tid)1406*f6aab3d8Srobert StopInfoSP StopInfo::CreateStopReasonFork(Thread &thread,
1407*f6aab3d8Srobert                                           lldb::pid_t child_pid,
1408*f6aab3d8Srobert                                           lldb::tid_t child_tid) {
1409*f6aab3d8Srobert   return StopInfoSP(new StopInfoFork(thread, child_pid, child_tid));
1410*f6aab3d8Srobert }
1411*f6aab3d8Srobert 
1412*f6aab3d8Srobert 
CreateStopReasonVFork(Thread & thread,lldb::pid_t child_pid,lldb::tid_t child_tid)1413*f6aab3d8Srobert StopInfoSP StopInfo::CreateStopReasonVFork(Thread &thread,
1414*f6aab3d8Srobert                                            lldb::pid_t child_pid,
1415*f6aab3d8Srobert                                            lldb::tid_t child_tid) {
1416*f6aab3d8Srobert   return StopInfoSP(new StopInfoVFork(thread, child_pid, child_tid));
1417*f6aab3d8Srobert }
1418*f6aab3d8Srobert 
CreateStopReasonVForkDone(Thread & thread)1419*f6aab3d8Srobert StopInfoSP StopInfo::CreateStopReasonVForkDone(Thread &thread) {
1420*f6aab3d8Srobert   return StopInfoSP(new StopInfoVForkDone(thread));
1421*f6aab3d8Srobert }
1422*f6aab3d8Srobert 
GetReturnValueObject(StopInfoSP & stop_info_sp)1423061da546Spatrick ValueObjectSP StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) {
1424061da546Spatrick   if (stop_info_sp &&
1425061da546Spatrick       stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
1426061da546Spatrick     StopInfoThreadPlan *plan_stop_info =
1427061da546Spatrick         static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
1428061da546Spatrick     return plan_stop_info->GetReturnValueObject();
1429061da546Spatrick   } else
1430061da546Spatrick     return ValueObjectSP();
1431061da546Spatrick }
1432061da546Spatrick 
GetExpressionVariable(StopInfoSP & stop_info_sp)1433061da546Spatrick ExpressionVariableSP StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) {
1434061da546Spatrick   if (stop_info_sp &&
1435061da546Spatrick       stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
1436061da546Spatrick     StopInfoThreadPlan *plan_stop_info =
1437061da546Spatrick         static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
1438061da546Spatrick     return plan_stop_info->GetExpressionVariable();
1439061da546Spatrick   } else
1440061da546Spatrick     return ExpressionVariableSP();
1441061da546Spatrick }
1442061da546Spatrick 
1443061da546Spatrick lldb::ValueObjectSP
GetCrashingDereference(StopInfoSP & stop_info_sp,lldb::addr_t * crashing_address)1444061da546Spatrick StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,
1445061da546Spatrick                                  lldb::addr_t *crashing_address) {
1446061da546Spatrick   if (!stop_info_sp) {
1447061da546Spatrick     return ValueObjectSP();
1448061da546Spatrick   }
1449061da546Spatrick 
1450061da546Spatrick   const char *description = stop_info_sp->GetDescription();
1451061da546Spatrick   if (!description) {
1452061da546Spatrick     return ValueObjectSP();
1453061da546Spatrick   }
1454061da546Spatrick 
1455061da546Spatrick   ThreadSP thread_sp = stop_info_sp->GetThread();
1456061da546Spatrick   if (!thread_sp) {
1457061da546Spatrick     return ValueObjectSP();
1458061da546Spatrick   }
1459061da546Spatrick 
1460061da546Spatrick   StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
1461061da546Spatrick 
1462061da546Spatrick   if (!frame_sp) {
1463061da546Spatrick     return ValueObjectSP();
1464061da546Spatrick   }
1465061da546Spatrick 
1466061da546Spatrick   const char address_string[] = "address=";
1467061da546Spatrick 
1468061da546Spatrick   const char *address_loc = strstr(description, address_string);
1469061da546Spatrick   if (!address_loc) {
1470061da546Spatrick     return ValueObjectSP();
1471061da546Spatrick   }
1472061da546Spatrick 
1473061da546Spatrick   address_loc += (sizeof(address_string) - 1);
1474061da546Spatrick 
1475061da546Spatrick   uint64_t address = strtoull(address_loc, nullptr, 0);
1476061da546Spatrick   if (crashing_address) {
1477061da546Spatrick     *crashing_address = address;
1478061da546Spatrick   }
1479061da546Spatrick 
1480061da546Spatrick   return frame_sp->GuessValueForAddress(address);
1481061da546Spatrick }
1482