1//===-- StopInfo.cpp ------------------------------------------------------===//
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#include <string>
10
11#include "lldb/Breakpoint/Breakpoint.h"
12#include "lldb/Breakpoint/BreakpointLocation.h"
13#include "lldb/Breakpoint/StoppointCallbackContext.h"
14#include "lldb/Breakpoint/Watchpoint.h"
15#include "lldb/Breakpoint/WatchpointResource.h"
16#include "lldb/Core/Debugger.h"
17#include "lldb/Expression/UserExpression.h"
18#include "lldb/Symbol/Block.h"
19#include "lldb/Target/Process.h"
20#include "lldb/Target/StopInfo.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/Thread.h"
23#include "lldb/Target/ThreadPlan.h"
24#include "lldb/Target/ThreadPlanStepInstruction.h"
25#include "lldb/Target/UnixSignals.h"
26#include "lldb/Utility/LLDBLog.h"
27#include "lldb/Utility/Log.h"
28#include "lldb/Utility/StreamString.h"
29#include "lldb/ValueObject/ValueObject.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34StopInfo::StopInfo(Thread &thread, uint64_t value)
35 : m_thread_wp(thread.shared_from_this()),
36 m_stop_id(thread.GetProcess()->GetStopID()),
37 m_resume_id(thread.GetProcess()->GetResumeID()), m_value(value),
38 m_description(), m_override_should_notify(eLazyBoolCalculate),
39 m_override_should_stop(eLazyBoolCalculate), m_extended_info() {}
40
41bool StopInfo::IsValid() const {
42 ThreadSP thread_sp(m_thread_wp.lock());
43 if (thread_sp)
44 return thread_sp->GetProcess()->GetStopID() == m_stop_id;
45 return false;
46}
47
48void StopInfo::MakeStopInfoValid() {
49 ThreadSP thread_sp(m_thread_wp.lock());
50 if (thread_sp) {
51 m_stop_id = thread_sp->GetProcess()->GetStopID();
52 m_resume_id = thread_sp->GetProcess()->GetResumeID();
53 }
54}
55
56bool StopInfo::HasTargetRunSinceMe() {
57 ThreadSP thread_sp(m_thread_wp.lock());
58
59 if (thread_sp) {
60 lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState();
61 if (ret_type == eStateRunning) {
62 return true;
63 } else if (ret_type == eStateStopped) {
64 // This is a little tricky. We want to count "run and stopped again
65 // before you could ask this question as a "TRUE" answer to
66 // HasTargetRunSinceMe. But we don't want to include any running of the
67 // target done for expressions. So we track both resumes, and resumes
68 // caused by expressions, and check if there are any resumes
69 // NOT caused
70 // by expressions.
71
72 uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID();
73 uint32_t last_user_expression_id =
74 thread_sp->GetProcess()->GetLastUserExpressionResumeID();
75 if (curr_resume_id == m_resume_id) {
76 return false;
77 } else if (curr_resume_id > last_user_expression_id) {
78 return true;
79 }
80 }
81 }
82 return false;
83}
84
85// StopInfoBreakpoint
86
87namespace lldb_private {
88class StopInfoBreakpoint : public StopInfo {
89public:
90 StopInfoBreakpoint(Thread &thread, break_id_t break_id)
91 : StopInfo(thread, break_id), m_should_stop(false),
92 m_should_stop_is_valid(false), m_should_perform_action(true),
93 m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
94 m_was_all_internal(false), m_was_one_shot(false) {
95 StoreBPInfo();
96 }
97
98 StopInfoBreakpoint(Thread &thread, break_id_t break_id, bool should_stop)
99 : StopInfo(thread, break_id), m_should_stop(should_stop),
100 m_should_stop_is_valid(true), m_should_perform_action(true),
101 m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
102 m_was_all_internal(false), m_was_one_shot(false) {
103 StoreBPInfo();
104 }
105
106 ~StopInfoBreakpoint() override = default;
107
108 void StoreBPInfo() {
109 ThreadSP thread_sp(m_thread_wp.lock());
110 if (thread_sp) {
111 BreakpointSiteSP bp_site_sp(
112 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(site_id: m_value));
113 if (bp_site_sp) {
114 uint32_t num_constituents = bp_site_sp->GetNumberOfConstituents();
115 if (num_constituents == 1) {
116 BreakpointLocationSP bp_loc_sp = bp_site_sp->GetConstituentAtIndex(idx: 0);
117 if (bp_loc_sp) {
118 Breakpoint & bkpt = bp_loc_sp->GetBreakpoint();
119 m_break_id = bkpt.GetID();
120 m_was_one_shot = bkpt.IsOneShot();
121 m_was_all_internal = bkpt.IsInternal();
122 }
123 } else {
124 m_was_all_internal = true;
125 for (uint32_t i = 0; i < num_constituents; i++) {
126 if (!bp_site_sp->GetConstituentAtIndex(idx: i)
127 ->GetBreakpoint()
128 .IsInternal()) {
129 m_was_all_internal = false;
130 break;
131 }
132 }
133 }
134 m_address = bp_site_sp->GetLoadAddress();
135 }
136 }
137 }
138
139 bool IsValidForOperatingSystemThread(Thread &thread) override {
140 ProcessSP process_sp(thread.GetProcess());
141 if (process_sp) {
142 BreakpointSiteSP bp_site_sp(
143 process_sp->GetBreakpointSiteList().FindByID(site_id: m_value));
144 if (bp_site_sp)
145 return bp_site_sp->ValidForThisThread(thread);
146 }
147 return false;
148 }
149
150 StopReason GetStopReason() const override { return eStopReasonBreakpoint; }
151
152 bool ShouldStopSynchronous(Event *event_ptr) override {
153 ThreadSP thread_sp(m_thread_wp.lock());
154 if (thread_sp) {
155 if (!m_should_stop_is_valid) {
156 // Only check once if we should stop at a breakpoint
157 BreakpointSiteSP bp_site_sp(
158 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(site_id: m_value));
159 if (bp_site_sp) {
160 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(idx: 0));
161 StoppointCallbackContext context(event_ptr, exe_ctx, true);
162 bp_site_sp->BumpHitCounts();
163 m_should_stop = bp_site_sp->ShouldStop(context: &context);
164 } else {
165 Log *log = GetLog(mask: LLDBLog::Process);
166
167 LLDB_LOGF(log,
168 "Process::%s could not find breakpoint site id: %" PRId64
169 "...",
170 __FUNCTION__, m_value);
171
172 m_should_stop = true;
173 }
174 m_should_stop_is_valid = true;
175 }
176 return m_should_stop;
177 }
178 return false;
179 }
180
181 bool DoShouldNotify(Event *event_ptr) override {
182 return !m_was_all_internal;
183 }
184
185 const char *GetDescription() override {
186 if (m_description.empty()) {
187 ThreadSP thread_sp(m_thread_wp.lock());
188 if (thread_sp) {
189 BreakpointSiteSP bp_site_sp(
190 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(site_id: m_value));
191 if (bp_site_sp) {
192 StreamString strm;
193 // If we have just hit an internal breakpoint, and it has a kind
194 // description, print that instead of the full breakpoint printing:
195 if (bp_site_sp->IsInternal()) {
196 size_t num_constituents = bp_site_sp->GetNumberOfConstituents();
197 for (size_t idx = 0; idx < num_constituents; idx++) {
198 const char *kind = bp_site_sp->GetConstituentAtIndex(idx)
199 ->GetBreakpoint()
200 .GetBreakpointKind();
201 if (kind != nullptr) {
202 m_description.assign(s: kind);
203 return kind;
204 }
205 }
206 }
207
208 strm.Printf(format: "breakpoint ");
209 bp_site_sp->GetDescription(s: &strm, level: eDescriptionLevelBrief);
210 m_description = std::string(strm.GetString());
211 } else {
212 StreamString strm;
213 if (m_break_id != LLDB_INVALID_BREAK_ID) {
214 BreakpointSP break_sp =
215 thread_sp->GetProcess()->GetTarget().GetBreakpointByID(
216 break_id: m_break_id);
217 if (break_sp) {
218 if (break_sp->IsInternal()) {
219 const char *kind = break_sp->GetBreakpointKind();
220 if (kind)
221 strm.Printf(format: "internal %s breakpoint(%d).", kind, m_break_id);
222 else
223 strm.Printf(format: "internal breakpoint(%d).", m_break_id);
224 } else {
225 strm.Printf(format: "breakpoint %d.", m_break_id);
226 }
227 } else {
228 if (m_was_one_shot)
229 strm.Printf(format: "one-shot breakpoint %d", m_break_id);
230 else
231 strm.Printf(format: "breakpoint %d which has been deleted.",
232 m_break_id);
233 }
234 } else if (m_address == LLDB_INVALID_ADDRESS)
235 strm.Printf(format: "breakpoint site %" PRIi64
236 " which has been deleted - unknown address",
237 m_value);
238 else
239 strm.Printf(format: "breakpoint site %" PRIi64
240 " which has been deleted - was at 0x%" PRIx64,
241 m_value, m_address);
242
243 m_description = std::string(strm.GetString());
244 }
245 }
246 }
247 return m_description.c_str();
248 }
249
250 std::optional<uint32_t>
251 GetSuggestedStackFrameIndex(bool inlined_stack) override {
252 if (!inlined_stack)
253 return {};
254
255 ThreadSP thread_sp(m_thread_wp.lock());
256 if (!thread_sp)
257 return {};
258 BreakpointSiteSP bp_site_sp(
259 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(site_id: m_value));
260 if (!bp_site_sp)
261 return {};
262
263 return bp_site_sp->GetSuggestedStackFrameIndex();
264 }
265
266 bool ShouldShow() const override { return !m_was_all_internal; }
267
268 bool ShouldSelect() const override { return !m_was_all_internal; }
269
270protected:
271 bool ShouldStop(Event *event_ptr) override {
272 // This just reports the work done by PerformAction or the synchronous
273 // stop. It should only ever get called after they have had a chance to
274 // run.
275 assert(m_should_stop_is_valid);
276 return m_should_stop;
277 }
278
279 void PerformAction(Event *event_ptr) override {
280 if (!m_should_perform_action)
281 return;
282 m_should_perform_action = false;
283 bool all_stopping_locs_internal = true;
284
285 ThreadSP thread_sp(m_thread_wp.lock());
286
287 if (thread_sp) {
288 Log *log = GetLog(mask: LLDBLog::Breakpoints | LLDBLog::Step);
289
290 if (!thread_sp->IsValid()) {
291 // This shouldn't ever happen, but just in case, don't do more harm.
292 if (log) {
293 LLDB_LOGF(log, "PerformAction got called with an invalid thread.");
294 }
295 m_should_stop = true;
296 m_should_stop_is_valid = true;
297 return;
298 }
299
300 BreakpointSiteSP bp_site_sp(
301 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(site_id: m_value));
302 std::unordered_set<break_id_t> precondition_breakpoints;
303 // Breakpoints that fail their condition check are not considered to
304 // have been hit. If the only locations at this site have failed their
305 // conditions, we should change the stop-info to none. Otherwise, if we
306 // hit another breakpoint on a different thread which does stop, users
307 // will see a breakpont hit with a failed condition, which is wrong.
308 // Use this variable to tell us if that is true.
309 bool actually_hit_any_locations = false;
310 if (bp_site_sp) {
311 // Let's copy the constituents list out of the site and store them in a
312 // local list. That way if one of the breakpoint actions changes the
313 // site, then we won't be operating on a bad list.
314 BreakpointLocationCollection site_locations;
315 size_t num_constituents =
316 bp_site_sp->CopyConstituentsList(out_collection&: site_locations);
317
318 if (num_constituents == 0) {
319 m_should_stop = true;
320 actually_hit_any_locations = true; // We're going to stop, don't
321 // change the stop info.
322 } else {
323 // We go through each location, and test first its precondition -
324 // this overrides everything. Note, we only do this once per
325 // breakpoint - not once per location... Then check the condition.
326 // If the condition says to stop, then we run the callback for that
327 // location. If that callback says to stop as well, then we set
328 // m_should_stop to true; we are going to stop. But we still want to
329 // give all the breakpoints whose conditions say we are going to stop
330 // a chance to run their callbacks. Of course if any callback
331 // restarts the target by putting "continue" in the callback, then
332 // we're going to restart, without running the rest of the callbacks.
333 // And in this case we will end up not stopping even if another
334 // location said we should stop. But that's better than not running
335 // all the callbacks.
336
337 // There's one other complication here. We may have run an async
338 // breakpoint callback that said we should stop. We only want to
339 // override that if another breakpoint action says we shouldn't
340 // stop. If nobody else has an opinion, then we should stop if the
341 // async callback says we should. An example of this is the async
342 // shared library load notification breakpoint and the setting
343 // stop-on-sharedlibrary-events.
344 // We'll keep the async value in async_should_stop, and track whether
345 // anyone said we should NOT stop in actually_said_continue.
346 bool async_should_stop = false;
347 if (m_should_stop_is_valid)
348 async_should_stop = m_should_stop;
349 bool actually_said_continue = false;
350
351 m_should_stop = false;
352
353 // We don't select threads as we go through them testing breakpoint
354 // conditions and running commands. So we need to set the thread for
355 // expression evaluation here:
356 ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);
357
358 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(idx: 0));
359 Process *process = exe_ctx.GetProcessPtr();
360 if (process->GetModIDRef().IsRunningExpression()) {
361 // If we are in the middle of evaluating an expression, don't run
362 // asynchronous breakpoint commands or expressions. That could
363 // lead to infinite recursion if the command or condition re-calls
364 // the function with this breakpoint.
365 // TODO: We can keep a list of the breakpoints we've seen while
366 // running expressions in the nested
367 // PerformAction calls that can arise when the action runs a
368 // function that hits another breakpoint, and only stop running
369 // commands when we see the same breakpoint hit a second time.
370
371 m_should_stop_is_valid = true;
372
373 // It is possible that the user has a breakpoint at the same site
374 // as the completed plan had (e.g. user has a breakpoint
375 // on a module entry point, and `ThreadPlanCallFunction` ends
376 // also there). We can't find an internal breakpoint in the loop
377 // later because it was already removed on the plan completion.
378 // So check if the plan was completed, and stop if so.
379 if (thread_sp->CompletedPlanOverridesBreakpoint()) {
380 m_should_stop = true;
381 thread_sp->ResetStopInfo();
382 return;
383 }
384
385 LLDB_LOGF(log, "StopInfoBreakpoint::PerformAction - Hit a "
386 "breakpoint while running an expression,"
387 " not running commands to avoid recursion.");
388 bool ignoring_breakpoints =
389 process->GetIgnoreBreakpointsInExpressions();
390 // Internal breakpoints should be allowed to do their job, we
391 // can make sure they don't do anything that would cause recursive
392 // command execution:
393 if (!m_was_all_internal) {
394 m_should_stop = !ignoring_breakpoints;
395 LLDB_LOGF(log,
396 "StopInfoBreakpoint::PerformAction - in expression, "
397 "continuing: %s.",
398 m_should_stop ? "true" : "false");
399 Debugger::ReportWarning(
400 message: "hit breakpoint while running function, skipping commands "
401 "and conditions to prevent recursion",
402 debugger_id: process->GetTarget().GetDebugger().GetID());
403 return;
404 }
405 }
406
407 StoppointCallbackContext context(event_ptr, exe_ctx, false);
408
409 // For safety's sake let's also grab an extra reference to the
410 // breakpoint constituents of the locations we're going to examine,
411 // since the locations are going to have to get back to their
412 // breakpoints, and the locations don't keep their constituents alive.
413 // I'm just sticking the BreakpointSP's in a vector since I'm only
414 // using it to locally increment their retain counts.
415
416 std::vector<lldb::BreakpointSP> location_constituents;
417
418 for (size_t j = 0; j < num_constituents; j++) {
419 BreakpointLocationSP loc(site_locations.GetByIndex(i: j));
420 location_constituents.push_back(
421 x: loc->GetBreakpoint().shared_from_this());
422 }
423
424 for (size_t j = 0; j < num_constituents; j++) {
425 lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(i: j);
426 StreamString loc_desc;
427 if (log) {
428 bp_loc_sp->GetDescription(s: &loc_desc, level: eDescriptionLevelBrief);
429 }
430 // If another action disabled this breakpoint or its location, then
431 // don't run the actions.
432 if (!bp_loc_sp->IsEnabled() ||
433 !bp_loc_sp->GetBreakpoint().IsEnabled())
434 continue;
435
436 // The breakpoint site may have many locations associated with it,
437 // not all of them valid for this thread. Skip the ones that
438 // aren't:
439 if (!bp_loc_sp->ValidForThisThread(thread&: *thread_sp)) {
440 if (log) {
441 LLDB_LOGF(log,
442 "Breakpoint %s hit on thread 0x%llx but it was not "
443 "for this thread, continuing.",
444 loc_desc.GetData(),
445 static_cast<unsigned long long>(thread_sp->GetID()));
446 }
447 continue;
448 }
449
450 // First run the precondition, but since the precondition is per
451 // breakpoint, only run it once per breakpoint.
452 std::pair<std::unordered_set<break_id_t>::iterator, bool> result =
453 precondition_breakpoints.insert(
454 x: bp_loc_sp->GetBreakpoint().GetID());
455 if (!result.second)
456 continue;
457
458 bool precondition_result =
459 bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);
460 if (!precondition_result) {
461 actually_said_continue = true;
462 continue;
463 }
464 // Next run the condition for the breakpoint. If that says we
465 // should stop, then we'll run the callback for the breakpoint. If
466 // the callback says we shouldn't stop that will win.
467
468 if (bp_loc_sp->GetConditionText() == nullptr)
469 actually_hit_any_locations = true;
470 else {
471 Status condition_error;
472 bool condition_says_stop =
473 bp_loc_sp->ConditionSaysStop(exe_ctx, error&: condition_error);
474
475 if (!condition_error.Success()) {
476 // If the condition fails to evaluate, we are going to stop
477 // at it, so the location was hit.
478 actually_hit_any_locations = true;
479 const char *err_str =
480 condition_error.AsCString(default_error_str: "<unknown error>");
481 LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);
482
483 StreamString strm;
484 strm << "stopped due to an error evaluating condition of "
485 "breakpoint ";
486 bp_loc_sp->GetDescription(s: &strm, level: eDescriptionLevelBrief);
487 strm << ": \"" << bp_loc_sp->GetConditionText() << "\"\n";
488 strm << err_str;
489
490 Debugger::ReportError(
491 message: strm.GetString().str(),
492 debugger_id: exe_ctx.GetTargetRef().GetDebugger().GetID());
493 } else {
494 LLDB_LOGF(log,
495 "Condition evaluated for breakpoint %s on thread "
496 "0x%llx condition_says_stop: %i.",
497 loc_desc.GetData(),
498 static_cast<unsigned long long>(thread_sp->GetID()),
499 condition_says_stop);
500 if (condition_says_stop)
501 actually_hit_any_locations = true;
502 else {
503 // We don't want to increment the hit count of breakpoints if
504 // the condition fails. We've already bumped it by the time
505 // we get here, so undo the bump:
506 bp_loc_sp->UndoBumpHitCount();
507 actually_said_continue = true;
508 continue;
509 }
510 }
511 }
512
513 // We've done all the checks whose failure means "we consider lldb
514 // not to have hit the breakpoint". Now we're going to check for
515 // conditions that might continue after hitting. Start with the
516 // ignore count:
517 if (!bp_loc_sp->IgnoreCountShouldStop()) {
518 actually_said_continue = true;
519 continue;
520 }
521
522 // Check the auto-continue bit on the location, do this before the
523 // callback since it may change this, but that would be for the
524 // NEXT hit. Note, you might think you could check auto-continue
525 // before the condition, and not evaluate the condition if it says
526 // to continue. But failing the condition means the breakpoint was
527 // effectively NOT HIT. So these two states are different.
528 bool auto_continue_says_stop = true;
529 if (bp_loc_sp->IsAutoContinue())
530 {
531 LLDB_LOGF(log,
532 "Continuing breakpoint %s as AutoContinue was set.",
533 loc_desc.GetData());
534 // We want this stop reported, so you will know we auto-continued
535 // but only for external breakpoints:
536 if (!bp_loc_sp->GetBreakpoint().IsInternal())
537 thread_sp->SetShouldReportStop(eVoteYes);
538 auto_continue_says_stop = false;
539 }
540
541 bool callback_says_stop = true;
542
543 // FIXME: For now the callbacks have to run in async mode - the
544 // first time we restart we need
545 // to get out of there. So set it here.
546 // When we figure out how to nest breakpoint hits then this will
547 // change.
548
549 // Don't run async callbacks in PerformAction. They have already
550 // been taken into account with async_should_stop.
551 if (!bp_loc_sp->IsCallbackSynchronous()) {
552 Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
553 bool old_async = debugger.GetAsyncExecution();
554 debugger.SetAsyncExecution(true);
555
556 callback_says_stop = bp_loc_sp->InvokeCallback(context: &context);
557
558 debugger.SetAsyncExecution(old_async);
559
560 if (callback_says_stop && auto_continue_says_stop)
561 m_should_stop = true;
562 else
563 actually_said_continue = true;
564 }
565
566 if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())
567 all_stopping_locs_internal = false;
568
569 // If we are going to stop for this breakpoint, then remove the
570 // breakpoint.
571 if (callback_says_stop && bp_loc_sp &&
572 bp_loc_sp->GetBreakpoint().IsOneShot()) {
573 thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(
574 break_id: bp_loc_sp->GetBreakpoint().GetID());
575 }
576 // Also make sure that the callback hasn't continued the target. If
577 // it did, when we'll set m_should_start to false and get out of
578 // here.
579 if (HasTargetRunSinceMe()) {
580 m_should_stop = false;
581 actually_said_continue = true;
582 break;
583 }
584 }
585 // At this point if nobody actually told us to continue, we should
586 // give the async breakpoint callback a chance to weigh in:
587 if (!actually_said_continue && !m_should_stop) {
588 m_should_stop = async_should_stop;
589 }
590 }
591 // We've figured out what this stop wants to do, so mark it as valid so
592 // we don't compute it again.
593 m_should_stop_is_valid = true;
594 } else {
595 m_should_stop = true;
596 m_should_stop_is_valid = true;
597 actually_hit_any_locations = true;
598 Log *log_process(GetLog(mask: LLDBLog::Process));
599
600 LLDB_LOGF(log_process,
601 "Process::%s could not find breakpoint site id: %" PRId64
602 "...",
603 __FUNCTION__, m_value);
604 }
605
606 if ((!m_should_stop || all_stopping_locs_internal) &&
607 thread_sp->CompletedPlanOverridesBreakpoint()) {
608
609 // Override should_stop decision when we have completed step plan
610 // additionally to the breakpoint
611 m_should_stop = true;
612
613 // We know we're stopping for a completed plan and we don't want to
614 // show the breakpoint stop, so compute the public stop info immediately
615 // here.
616 thread_sp->CalculatePublicStopInfo();
617 } else if (!actually_hit_any_locations) {
618 // In the end, we didn't actually have any locations that passed their
619 // "was I hit" checks. So say we aren't stopped.
620 GetThread()->ResetStopInfo();
621 LLDB_LOGF(log, "Process::%s all locations failed condition checks.",
622 __FUNCTION__);
623 }
624
625 LLDB_LOGF(log,
626 "Process::%s returning from action with m_should_stop: %d.",
627 __FUNCTION__, m_should_stop);
628 }
629 }
630
631private:
632 bool m_should_stop;
633 bool m_should_stop_is_valid;
634 bool m_should_perform_action; // Since we are trying to preserve the "state"
635 // of the system even if we run functions
636 // etc. behind the users backs, we need to make sure we only REALLY perform
637 // the action once.
638 lldb::addr_t m_address; // We use this to capture the breakpoint site address
639 // when we create the StopInfo,
640 // in case somebody deletes it between the time the StopInfo is made and the
641 // description is asked for.
642 lldb::break_id_t m_break_id;
643 bool m_was_all_internal;
644 bool m_was_one_shot;
645};
646
647// StopInfoWatchpoint
648
649class StopInfoWatchpoint : public StopInfo {
650public:
651 // Make sure watchpoint is properly disabled and subsequently enabled while
652 // performing watchpoint actions.
653 class WatchpointSentry {
654 public:
655 WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),
656 watchpoint_sp(w_sp) {
657 if (process_sp && watchpoint_sp) {
658 const bool notify = false;
659 watchpoint_sp->TurnOnEphemeralMode();
660 process_sp->DisableWatchpoint(wp_sp: watchpoint_sp, notify);
661 process_sp->AddPreResumeAction(callback: SentryPreResumeAction, baton: this);
662 }
663 }
664
665 void DoReenable() {
666 if (process_sp && watchpoint_sp) {
667 bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();
668 watchpoint_sp->TurnOffEphemeralMode();
669 const bool notify = false;
670 if (was_disabled) {
671 process_sp->DisableWatchpoint(wp_sp: watchpoint_sp, notify);
672 } else {
673 process_sp->EnableWatchpoint(wp_sp: watchpoint_sp, notify);
674 }
675 }
676 }
677
678 ~WatchpointSentry() {
679 DoReenable();
680 if (process_sp)
681 process_sp->ClearPreResumeAction(callback: SentryPreResumeAction, baton: this);
682 }
683
684 static bool SentryPreResumeAction(void *sentry_void) {
685 WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;
686 sentry->DoReenable();
687 return true;
688 }
689
690 private:
691 ProcessSP process_sp;
692 WatchpointSP watchpoint_sp;
693 };
694
695 StopInfoWatchpoint(Thread &thread, break_id_t watch_id, bool silently_skip_wp)
696 : StopInfo(thread, watch_id), m_silently_skip_wp(silently_skip_wp) {}
697
698 ~StopInfoWatchpoint() override = default;
699
700 StopReason GetStopReason() const override { return eStopReasonWatchpoint; }
701
702 const char *GetDescription() override {
703 if (m_description.empty()) {
704 StreamString strm;
705 strm.Printf(format: "watchpoint %" PRIi64, m_value);
706 m_description = std::string(strm.GetString());
707 }
708 return m_description.c_str();
709 }
710
711protected:
712 using StopInfoWatchpointSP = std::shared_ptr<StopInfoWatchpoint>;
713 // This plan is used to orchestrate stepping over the watchpoint for
714 // architectures (e.g. ARM) that report the watch before running the watched
715 // access. This is the sort of job you have to defer to the thread plans,
716 // if you try to do it directly in the stop info and there are other threads
717 // that needed to process this stop you will have yanked control away from
718 // them and they won't behave correctly.
719 class ThreadPlanStepOverWatchpoint : public ThreadPlanStepInstruction {
720 public:
721 ThreadPlanStepOverWatchpoint(Thread &thread,
722 StopInfoWatchpointSP stop_info_sp,
723 WatchpointSP watch_sp)
724 : ThreadPlanStepInstruction(thread, false, true, eVoteNoOpinion,
725 eVoteNoOpinion),
726 m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) {
727 assert(watch_sp);
728 }
729
730 bool DoWillResume(lldb::StateType resume_state,
731 bool current_plan) override {
732 if (resume_state == eStateSuspended)
733 return true;
734
735 if (!m_did_disable_wp) {
736 GetThread().GetProcess()->DisableWatchpoint(wp_sp: m_watch_sp, notify: false);
737 m_did_disable_wp = true;
738 }
739 return true;
740 }
741
742 bool DoPlanExplainsStop(Event *event_ptr) override {
743 if (ThreadPlanStepInstruction::DoPlanExplainsStop(event_ptr))
744 return true;
745 StopInfoSP stop_info_sp = GetThread().GetPrivateStopInfo();
746 // lldb-server resets the stop info for threads that didn't get to run,
747 // so we might have not gotten to run, but still have a watchpoint stop
748 // reason, in which case this will indeed be for us.
749 if (stop_info_sp
750 && stop_info_sp->GetStopReason() == eStopReasonWatchpoint)
751 return true;
752 return false;
753 }
754
755 void DidPop() override {
756 // Don't artifically keep the watchpoint alive.
757 m_watch_sp.reset();
758 }
759
760 bool ShouldStop(Event *event_ptr) override {
761 bool should_stop = ThreadPlanStepInstruction::ShouldStop(event_ptr);
762 bool plan_done = MischiefManaged();
763 if (plan_done) {
764 m_stop_info_sp->SetStepOverPlanComplete();
765 GetThread().SetStopInfo(m_stop_info_sp);
766 ResetWatchpoint();
767 }
768 return should_stop;
769 }
770
771 bool ShouldRunBeforePublicStop() override {
772 return true;
773 }
774
775 protected:
776 void ResetWatchpoint() {
777 if (!m_did_disable_wp)
778 return;
779 m_did_disable_wp = true;
780 GetThread().GetProcess()->EnableWatchpoint(wp_sp: m_watch_sp, notify: true);
781 }
782
783 private:
784 StopInfoWatchpointSP m_stop_info_sp;
785 WatchpointSP m_watch_sp;
786 bool m_did_disable_wp = false;
787 };
788
789 bool ShouldStopSynchronous(Event *event_ptr) override {
790 // If we are running our step-over the watchpoint plan, stop if it's done
791 // and continue if it's not:
792 if (m_should_stop_is_valid)
793 return m_should_stop;
794
795 // If we are running our step over plan, then stop here and let the regular
796 // ShouldStop figure out what we should do: Otherwise, give our plan
797 // more time to get run:
798 if (m_using_step_over_plan)
799 return m_step_over_plan_complete;
800
801 Log *log = GetLog(mask: LLDBLog::Process);
802 ThreadSP thread_sp(m_thread_wp.lock());
803 assert(thread_sp);
804
805 if (thread_sp->GetTemporaryResumeState() == eStateSuspended) {
806 // This is the second firing of a watchpoint so don't process it again.
807 LLDB_LOG(log, "We didn't run but stopped with a StopInfoWatchpoint, we "
808 "have already handled this one, don't do it again.");
809 m_should_stop = false;
810 m_should_stop_is_valid = true;
811 return m_should_stop;
812 }
813
814 WatchpointSP wp_sp(
815 thread_sp->CalculateTarget()->GetWatchpointList().FindByID(watchID: GetValue()));
816 // If we can no longer find the watchpoint, we just have to stop:
817 if (!wp_sp) {
818
819 LLDB_LOGF(log,
820 "Process::%s could not find watchpoint location id: %" PRId64
821 "...",
822 __FUNCTION__, GetValue());
823
824 m_should_stop = true;
825 m_should_stop_is_valid = true;
826 return true;
827 }
828
829 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(idx: 0));
830 StoppointCallbackContext context(event_ptr, exe_ctx, true);
831 m_should_stop = wp_sp->ShouldStop(context: &context);
832 if (!m_should_stop) {
833 // This won't happen at present because we only allow one watchpoint per
834 // watched range. So we won't stop at a watched address with a disabled
835 // watchpoint. If we start allowing overlapping watchpoints, then we
836 // will have to make watchpoints be real "WatchpointSite" and delegate to
837 // all the watchpoints sharing the site. In that case, the code below
838 // would be the right thing to do.
839 m_should_stop_is_valid = true;
840 return m_should_stop;
841 }
842 // If this is a system where we need to execute the watchpoint by hand
843 // after the hit, queue a thread plan to do that, and then say not to stop.
844 // Otherwise, let the async action figure out whether the watchpoint should
845 // stop
846
847 ProcessSP process_sp = exe_ctx.GetProcessSP();
848 bool wp_triggers_after = process_sp->GetWatchpointReportedAfter();
849
850 if (!wp_triggers_after) {
851 // We have to step over the watchpoint before we know what to do:
852 StopInfoWatchpointSP me_as_siwp_sp
853 = std::static_pointer_cast<StopInfoWatchpoint>(r: shared_from_this());
854 ThreadPlanSP step_over_wp_sp(new ThreadPlanStepOverWatchpoint(
855 *(thread_sp.get()), me_as_siwp_sp, wp_sp));
856 // When this plan is done we want to stop, so set this as a Controlling
857 // plan.
858 step_over_wp_sp->SetIsControllingPlan(true);
859 step_over_wp_sp->SetOkayToDiscard(false);
860
861 Status error;
862 error = thread_sp->QueueThreadPlan(plan_sp&: step_over_wp_sp, abort_other_plans: false);
863 // If we couldn't push the thread plan, just stop here:
864 if (!error.Success()) {
865 LLDB_LOGF(log, "Could not push our step over watchpoint plan: %s",
866 error.AsCString());
867
868 m_should_stop = true;
869 m_should_stop_is_valid = true;
870 return true;
871 } else {
872 // Otherwise, don't set m_should_stop, we don't know that yet. Just
873 // say we should continue, and tell the thread we really should do so:
874 thread_sp->SetShouldRunBeforePublicStop(true);
875 m_using_step_over_plan = true;
876 return false;
877 }
878 } else {
879 // We didn't have to do anything special
880 m_should_stop_is_valid = true;
881 return m_should_stop;
882 }
883
884 return m_should_stop;
885 }
886
887 bool ShouldStop(Event *event_ptr) override {
888 // This just reports the work done by PerformAction or the synchronous
889 // stop. It should only ever get called after they have had a chance to
890 // run.
891 assert(m_should_stop_is_valid);
892 return m_should_stop;
893 }
894
895 void PerformAction(Event *event_ptr) override {
896 Log *log = GetLog(mask: LLDBLog::Watchpoints);
897 // We're going to calculate if we should stop or not in some way during the
898 // course of this code. Also by default we're going to stop, so set that
899 // here.
900 m_should_stop = true;
901
902
903 ThreadSP thread_sp(m_thread_wp.lock());
904 if (thread_sp) {
905
906 WatchpointSP wp_sp(
907 thread_sp->CalculateTarget()->GetWatchpointList().FindByID(
908 watchID: GetValue()));
909 if (wp_sp) {
910 // This sentry object makes sure the current watchpoint is disabled
911 // while performing watchpoint actions, and it is then enabled after we
912 // are finished.
913 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(idx: 0));
914 ProcessSP process_sp = exe_ctx.GetProcessSP();
915
916 WatchpointSentry sentry(process_sp, wp_sp);
917
918 if (m_silently_skip_wp) {
919 m_should_stop = false;
920 wp_sp->UndoHitCount();
921 }
922
923 if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) {
924 m_should_stop = false;
925 m_should_stop_is_valid = true;
926 }
927
928 Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
929
930 if (m_should_stop && wp_sp->GetConditionText() != nullptr) {
931 // We need to make sure the user sees any parse errors in their
932 // condition, so we'll hook the constructor errors up to the
933 // debugger's Async I/O.
934 ExpressionResults result_code;
935 EvaluateExpressionOptions expr_options;
936 expr_options.SetUnwindOnError(true);
937 expr_options.SetIgnoreBreakpoints(true);
938 ValueObjectSP result_value_sp;
939 result_code = UserExpression::Evaluate(
940 exe_ctx, options: expr_options, expr_cstr: wp_sp->GetConditionText(),
941 expr_prefix: llvm::StringRef(), result_valobj_sp&: result_value_sp);
942
943 if (result_code == eExpressionCompleted) {
944 if (result_value_sp) {
945 Scalar scalar_value;
946 if (result_value_sp->ResolveValue(scalar&: scalar_value)) {
947 if (scalar_value.ULongLong(fail_value: 1) == 0) {
948 // The condition failed, which we consider "not having hit
949 // the watchpoint" so undo the hit count here.
950 wp_sp->UndoHitCount();
951 m_should_stop = false;
952 } else
953 m_should_stop = true;
954 LLDB_LOGF(log,
955 "Condition successfully evaluated, result is %s.\n",
956 m_should_stop ? "true" : "false");
957 } else {
958 m_should_stop = true;
959 LLDB_LOGF(
960 log,
961 "Failed to get an integer result from the expression.");
962 }
963 }
964 } else {
965 const char *err_str = "<unknown error>";
966 if (result_value_sp)
967 err_str = result_value_sp->GetError().AsCString();
968
969 LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);
970
971 StreamString strm;
972 strm << "stopped due to an error evaluating condition of "
973 "watchpoint ";
974 wp_sp->GetDescription(s: &strm, level: eDescriptionLevelBrief);
975 strm << ": \"" << wp_sp->GetConditionText() << "\"\n";
976 strm << err_str;
977
978 Debugger::ReportError(message: strm.GetString().str(),
979 debugger_id: exe_ctx.GetTargetRef().GetDebugger().GetID());
980 }
981 }
982
983 // If the condition says to stop, we run the callback to further decide
984 // whether to stop.
985 if (m_should_stop) {
986 // FIXME: For now the callbacks have to run in async mode - the
987 // first time we restart we need
988 // to get out of there. So set it here.
989 // When we figure out how to nest watchpoint hits then this will
990 // change.
991
992 bool old_async = debugger.GetAsyncExecution();
993 debugger.SetAsyncExecution(true);
994
995 StoppointCallbackContext context(event_ptr, exe_ctx, false);
996 bool stop_requested = wp_sp->InvokeCallback(context: &context);
997
998 debugger.SetAsyncExecution(old_async);
999
1000 // Also make sure that the callback hasn't continued the target. If
1001 // it did, when we'll set m_should_stop to false and get out of here.
1002 if (HasTargetRunSinceMe())
1003 m_should_stop = false;
1004
1005 if (m_should_stop && !stop_requested) {
1006 // We have been vetoed by the callback mechanism.
1007 m_should_stop = false;
1008 }
1009 }
1010
1011 // Don't stop if the watched region value is unmodified, and
1012 // this is a Modify-type watchpoint.
1013 if (m_should_stop && !wp_sp->WatchedValueReportable(exe_ctx)) {
1014 wp_sp->UndoHitCount();
1015 m_should_stop = false;
1016 }
1017
1018 // Finally, if we are going to stop, print out the new & old values:
1019 if (m_should_stop) {
1020 wp_sp->CaptureWatchedValue(exe_ctx);
1021
1022 Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
1023 StreamUP output_up = debugger.GetAsyncOutputStream();
1024 if (wp_sp->DumpSnapshots(s: output_up.get()))
1025 output_up->EOL();
1026 }
1027
1028 } else {
1029 Log *log_process(GetLog(mask: LLDBLog::Process));
1030
1031 LLDB_LOGF(log_process,
1032 "Process::%s could not find watchpoint id: %" PRId64 "...",
1033 __FUNCTION__, m_value);
1034 }
1035 LLDB_LOGF(log,
1036 "Process::%s returning from action with m_should_stop: %d.",
1037 __FUNCTION__, m_should_stop);
1038
1039 m_should_stop_is_valid = true;
1040 }
1041 }
1042
1043private:
1044 void SetStepOverPlanComplete() {
1045 assert(m_using_step_over_plan);
1046 m_step_over_plan_complete = true;
1047 }
1048
1049 bool m_should_stop = false;
1050 bool m_should_stop_is_valid = false;
1051 // A false watchpoint hit has happened -
1052 // the thread stopped with a watchpoint
1053 // hit notification, but the watched region
1054 // was not actually accessed (as determined
1055 // by the gdb stub we're talking to).
1056 // Continue past this watchpoint without
1057 // notifying the user; on some targets this
1058 // may mean disable wp, instruction step,
1059 // re-enable wp, continue.
1060 // On others, just continue.
1061 bool m_silently_skip_wp = false;
1062 bool m_step_over_plan_complete = false;
1063 bool m_using_step_over_plan = false;
1064};
1065
1066// StopInfoUnixSignal
1067
1068class StopInfoUnixSignal : public StopInfo {
1069public:
1070 StopInfoUnixSignal(Thread &thread, int signo, const char *description,
1071 std::optional<int> code)
1072 : StopInfo(thread, signo), m_code(code) {
1073 SetDescription(description);
1074 }
1075
1076 ~StopInfoUnixSignal() override = default;
1077
1078 StopReason GetStopReason() const override { return eStopReasonSignal; }
1079
1080 bool ShouldStopSynchronous(Event *event_ptr) override {
1081 ThreadSP thread_sp(m_thread_wp.lock());
1082 if (thread_sp)
1083 return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(signo: m_value);
1084 return false;
1085 }
1086
1087 bool ShouldStop(Event *event_ptr) override { return IsShouldStopSignal(); }
1088
1089 // If should stop returns false, check if we should notify of this event
1090 bool DoShouldNotify(Event *event_ptr) override {
1091 ThreadSP thread_sp(m_thread_wp.lock());
1092 if (thread_sp) {
1093 bool should_notify =
1094 thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(signo: m_value);
1095 if (should_notify) {
1096 StreamString strm;
1097 strm.Format(
1098 format: "thread {0:d} received signal: {1}", args: thread_sp->GetIndexID(),
1099 args: thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsStringRef(
1100 signo: m_value));
1101 Process::ProcessEventData::AddRestartedReason(event_ptr,
1102 reason: strm.GetData());
1103 }
1104 return should_notify;
1105 }
1106 return true;
1107 }
1108
1109 void WillResume(lldb::StateType resume_state) override {
1110 ThreadSP thread_sp(m_thread_wp.lock());
1111 if (thread_sp) {
1112 if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(
1113 signo: m_value))
1114 thread_sp->SetResumeSignal(m_value);
1115 }
1116 }
1117
1118 const char *GetDescription() override {
1119 if (m_description.empty()) {
1120 ThreadSP thread_sp(m_thread_wp.lock());
1121 if (thread_sp) {
1122 UnixSignalsSP unix_signals = thread_sp->GetProcess()->GetUnixSignals();
1123 StreamString strm;
1124 strm << "signal ";
1125
1126 std::string signal_name =
1127 unix_signals->GetSignalDescription(signo: m_value, code: m_code);
1128 if (signal_name.size())
1129 strm << signal_name;
1130 else
1131 strm.Printf(format: "%" PRIi64, m_value);
1132
1133 m_description = std::string(strm.GetString());
1134 }
1135 }
1136 return m_description.c_str();
1137 }
1138
1139 bool ShouldSelect() const override { return IsShouldStopSignal(); }
1140
1141private:
1142 // In siginfo_t terms, if m_value is si_signo, m_code is si_code.
1143 std::optional<int> m_code;
1144
1145 bool IsShouldStopSignal() const {
1146 if (ThreadSP thread_sp = m_thread_wp.lock())
1147 return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(signo: m_value);
1148 return false;
1149 }
1150};
1151
1152// StopInfoInterrupt
1153
1154class StopInfoInterrupt : public StopInfo {
1155public:
1156 StopInfoInterrupt(Thread &thread, int signo, const char *description)
1157 : StopInfo(thread, signo) {
1158 SetDescription(description);
1159 }
1160
1161 ~StopInfoInterrupt() override = default;
1162
1163 StopReason GetStopReason() const override {
1164 return lldb::eStopReasonInterrupt;
1165 }
1166
1167 const char *GetDescription() override {
1168 if (m_description.empty()) {
1169 m_description = "async interrupt";
1170 }
1171 return m_description.c_str();
1172 }
1173};
1174
1175// StopInfoTrace
1176
1177class StopInfoTrace : public StopInfo {
1178public:
1179 StopInfoTrace(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}
1180
1181 ~StopInfoTrace() override = default;
1182
1183 StopReason GetStopReason() const override { return eStopReasonTrace; }
1184
1185 const char *GetDescription() override {
1186 if (m_description.empty())
1187 return "trace";
1188 else
1189 return m_description.c_str();
1190 }
1191
1192 std::optional<uint32_t>
1193 GetSuggestedStackFrameIndex(bool inlined_stack) override {
1194 // Trace only knows how to adjust inlined stacks:
1195 if (!inlined_stack)
1196 return {};
1197
1198 ThreadSP thread_sp = GetThread();
1199 StackFrameSP frame_0_sp = thread_sp->GetStackFrameAtIndex(idx: 0);
1200 if (!frame_0_sp)
1201 return {};
1202 if (!frame_0_sp->IsInlined())
1203 return {};
1204 Block *block_ptr = frame_0_sp->GetFrameBlock();
1205 if (!block_ptr)
1206 return {};
1207 Address pc_address = frame_0_sp->GetFrameCodeAddress();
1208 AddressRange containing_range;
1209 if (!block_ptr->GetRangeContainingAddress(addr: pc_address, range&: containing_range) ||
1210 pc_address != containing_range.GetBaseAddress())
1211 return {};
1212
1213 int num_inlined_functions = 0;
1214
1215 for (Block *container_ptr = block_ptr->GetInlinedParent();
1216 container_ptr != nullptr;
1217 container_ptr = container_ptr->GetInlinedParent()) {
1218 if (!container_ptr->GetRangeContainingAddress(addr: pc_address,
1219 range&: containing_range))
1220 break;
1221 if (pc_address != containing_range.GetBaseAddress())
1222 break;
1223
1224 num_inlined_functions++;
1225 }
1226 inlined_stack = true;
1227 return num_inlined_functions + 1;
1228 }
1229};
1230
1231// StopInfoException
1232
1233class StopInfoException : public StopInfo {
1234public:
1235 StopInfoException(Thread &thread, const char *description)
1236 : StopInfo(thread, LLDB_INVALID_UID) {
1237 if (description)
1238 SetDescription(description);
1239 }
1240
1241 ~StopInfoException() override = default;
1242
1243 StopReason GetStopReason() const override { return eStopReasonException; }
1244
1245 const char *GetDescription() override {
1246 if (m_description.empty())
1247 return "exception";
1248 else
1249 return m_description.c_str();
1250 }
1251};
1252
1253// StopInfoProcessorTrace
1254
1255class StopInfoProcessorTrace : public StopInfo {
1256public:
1257 StopInfoProcessorTrace(Thread &thread, const char *description)
1258 : StopInfo(thread, LLDB_INVALID_UID) {
1259 if (description)
1260 SetDescription(description);
1261 }
1262
1263 ~StopInfoProcessorTrace() override = default;
1264
1265 StopReason GetStopReason() const override {
1266 return eStopReasonProcessorTrace;
1267 }
1268
1269 const char *GetDescription() override {
1270 if (m_description.empty())
1271 return "processor trace event";
1272 else
1273 return m_description.c_str();
1274 }
1275};
1276
1277// StopInfoHistoryBoundary
1278
1279class StopInfoHistoryBoundary : public StopInfo {
1280public:
1281 StopInfoHistoryBoundary(Thread &thread, const char *description)
1282 : StopInfo(thread, LLDB_INVALID_UID) {
1283 if (description)
1284 SetDescription(description);
1285 }
1286
1287 ~StopInfoHistoryBoundary() override = default;
1288
1289 StopReason GetStopReason() const override {
1290 return eStopReasonHistoryBoundary;
1291 }
1292
1293 const char *GetDescription() override {
1294 if (m_description.empty())
1295 return "history boundary";
1296 return m_description.c_str();
1297 }
1298};
1299
1300// StopInfoThreadPlan
1301
1302class StopInfoThreadPlan : public StopInfo {
1303public:
1304 StopInfoThreadPlan(ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp,
1305 ExpressionVariableSP &expression_variable_sp)
1306 : StopInfo(plan_sp->GetThread(), LLDB_INVALID_UID), m_plan_sp(plan_sp),
1307 m_return_valobj_sp(return_valobj_sp),
1308 m_expression_variable_sp(expression_variable_sp) {}
1309
1310 ~StopInfoThreadPlan() override = default;
1311
1312 StopReason GetStopReason() const override { return eStopReasonPlanComplete; }
1313
1314 const char *GetDescription() override {
1315 if (m_description.empty()) {
1316 StreamString strm;
1317 m_plan_sp->GetDescription(s: &strm, level: eDescriptionLevelBrief);
1318 m_description = std::string(strm.GetString());
1319 }
1320 return m_description.c_str();
1321 }
1322
1323 ValueObjectSP GetReturnValueObject() { return m_return_valobj_sp; }
1324
1325 ExpressionVariableSP GetExpressionVariable() {
1326 return m_expression_variable_sp;
1327 }
1328
1329protected:
1330 bool ShouldStop(Event *event_ptr) override {
1331 if (m_plan_sp)
1332 return m_plan_sp->ShouldStop(event_ptr);
1333 else
1334 return StopInfo::ShouldStop(event_ptr);
1335 }
1336
1337private:
1338 ThreadPlanSP m_plan_sp;
1339 ValueObjectSP m_return_valobj_sp;
1340 ExpressionVariableSP m_expression_variable_sp;
1341};
1342
1343// StopInfoExec
1344
1345class StopInfoExec : public StopInfo {
1346public:
1347 StopInfoExec(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}
1348
1349 ~StopInfoExec() override = default;
1350
1351 bool ShouldStop(Event *event_ptr) override {
1352 ThreadSP thread_sp(m_thread_wp.lock());
1353 if (thread_sp)
1354 return thread_sp->GetProcess()->GetStopOnExec();
1355 return false;
1356 }
1357
1358 StopReason GetStopReason() const override { return eStopReasonExec; }
1359
1360 const char *GetDescription() override { return "exec"; }
1361
1362protected:
1363 void PerformAction(Event *event_ptr) override {
1364 // Only perform the action once
1365 if (m_performed_action)
1366 return;
1367 m_performed_action = true;
1368 ThreadSP thread_sp(m_thread_wp.lock());
1369 if (thread_sp)
1370 thread_sp->GetProcess()->DidExec();
1371 }
1372
1373 bool m_performed_action = false;
1374};
1375
1376// StopInfoFork
1377
1378class StopInfoFork : public StopInfo {
1379public:
1380 StopInfoFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)
1381 : StopInfo(thread, child_pid), m_child_pid(child_pid),
1382 m_child_tid(child_tid) {}
1383
1384 ~StopInfoFork() override = default;
1385
1386 bool ShouldStop(Event *event_ptr) override { return false; }
1387
1388 StopReason GetStopReason() const override { return eStopReasonFork; }
1389
1390 const char *GetDescription() override { return "fork"; }
1391
1392protected:
1393 void PerformAction(Event *event_ptr) override {
1394 // Only perform the action once
1395 if (m_performed_action)
1396 return;
1397 m_performed_action = true;
1398 ThreadSP thread_sp(m_thread_wp.lock());
1399 if (thread_sp)
1400 thread_sp->GetProcess()->DidFork(child_pid: m_child_pid, child_tid: m_child_tid);
1401 }
1402
1403 bool m_performed_action = false;
1404
1405private:
1406 lldb::pid_t m_child_pid;
1407 lldb::tid_t m_child_tid;
1408};
1409
1410// StopInfoVFork
1411
1412class StopInfoVFork : public StopInfo {
1413public:
1414 StopInfoVFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)
1415 : StopInfo(thread, child_pid), m_child_pid(child_pid),
1416 m_child_tid(child_tid) {}
1417
1418 ~StopInfoVFork() override = default;
1419
1420 bool ShouldStop(Event *event_ptr) override { return false; }
1421
1422 StopReason GetStopReason() const override { return eStopReasonVFork; }
1423
1424 const char *GetDescription() override { return "vfork"; }
1425
1426protected:
1427 void PerformAction(Event *event_ptr) override {
1428 // Only perform the action once
1429 if (m_performed_action)
1430 return;
1431 m_performed_action = true;
1432 ThreadSP thread_sp(m_thread_wp.lock());
1433 if (thread_sp)
1434 thread_sp->GetProcess()->DidVFork(child_pid: m_child_pid, child_tid: m_child_tid);
1435 }
1436
1437 bool m_performed_action = false;
1438
1439private:
1440 lldb::pid_t m_child_pid;
1441 lldb::tid_t m_child_tid;
1442};
1443
1444// StopInfoVForkDone
1445
1446class StopInfoVForkDone : public StopInfo {
1447public:
1448 StopInfoVForkDone(Thread &thread) : StopInfo(thread, 0) {}
1449
1450 ~StopInfoVForkDone() override = default;
1451
1452 bool ShouldStop(Event *event_ptr) override { return false; }
1453
1454 StopReason GetStopReason() const override { return eStopReasonVForkDone; }
1455
1456 const char *GetDescription() override { return "vforkdone"; }
1457
1458protected:
1459 void PerformAction(Event *event_ptr) override {
1460 // Only perform the action once
1461 if (m_performed_action)
1462 return;
1463 m_performed_action = true;
1464 ThreadSP thread_sp(m_thread_wp.lock());
1465 if (thread_sp)
1466 thread_sp->GetProcess()->DidVForkDone();
1467 }
1468
1469 bool m_performed_action = false;
1470};
1471
1472} // namespace lldb_private
1473
1474StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
1475 break_id_t break_id) {
1476 thread.SetThreadHitBreakpointSite();
1477
1478 return StopInfoSP(new StopInfoBreakpoint(thread, break_id));
1479}
1480
1481StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
1482 break_id_t break_id,
1483 bool should_stop) {
1484 return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));
1485}
1486
1487// LWP_TODO: We'll need a CreateStopReasonWithWatchpointResourceID akin
1488// to CreateStopReasonWithBreakpointSiteID
1489StopInfoSP StopInfo::CreateStopReasonWithWatchpointID(Thread &thread,
1490 break_id_t watch_id,
1491 bool silently_continue) {
1492 return StopInfoSP(
1493 new StopInfoWatchpoint(thread, watch_id, silently_continue));
1494}
1495
1496StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
1497 const char *description,
1498 std::optional<int> code) {
1499 thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);
1500 return StopInfoSP(new StopInfoUnixSignal(thread, signo, description, code));
1501}
1502
1503StopInfoSP StopInfo::CreateStopReasonWithInterrupt(Thread &thread, int signo,
1504 const char *description) {
1505 return StopInfoSP(new StopInfoInterrupt(thread, signo, description));
1506}
1507
1508StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {
1509 return StopInfoSP(new StopInfoTrace(thread));
1510}
1511
1512StopInfoSP StopInfo::CreateStopReasonWithPlan(
1513 ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp,
1514 ExpressionVariableSP expression_variable_sp) {
1515 return StopInfoSP(new StopInfoThreadPlan(plan_sp, return_valobj_sp,
1516 expression_variable_sp));
1517}
1518
1519StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread,
1520 const char *description) {
1521 return StopInfoSP(new StopInfoException(thread, description));
1522}
1523
1524StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,
1525 const char *description) {
1526 return StopInfoSP(new StopInfoProcessorTrace(thread, description));
1527}
1528
1529StopInfoSP StopInfo::CreateStopReasonHistoryBoundary(Thread &thread,
1530 const char *description) {
1531 return StopInfoSP(new StopInfoHistoryBoundary(thread, description));
1532}
1533
1534StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {
1535 return StopInfoSP(new StopInfoExec(thread));
1536}
1537
1538StopInfoSP StopInfo::CreateStopReasonFork(Thread &thread,
1539 lldb::pid_t child_pid,
1540 lldb::tid_t child_tid) {
1541 return StopInfoSP(new StopInfoFork(thread, child_pid, child_tid));
1542}
1543
1544
1545StopInfoSP StopInfo::CreateStopReasonVFork(Thread &thread,
1546 lldb::pid_t child_pid,
1547 lldb::tid_t child_tid) {
1548 return StopInfoSP(new StopInfoVFork(thread, child_pid, child_tid));
1549}
1550
1551StopInfoSP StopInfo::CreateStopReasonVForkDone(Thread &thread) {
1552 return StopInfoSP(new StopInfoVForkDone(thread));
1553}
1554
1555ValueObjectSP StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) {
1556 if (stop_info_sp &&
1557 stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
1558 StopInfoThreadPlan *plan_stop_info =
1559 static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
1560 return plan_stop_info->GetReturnValueObject();
1561 } else
1562 return ValueObjectSP();
1563}
1564
1565ExpressionVariableSP StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) {
1566 if (stop_info_sp &&
1567 stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
1568 StopInfoThreadPlan *plan_stop_info =
1569 static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
1570 return plan_stop_info->GetExpressionVariable();
1571 } else
1572 return ExpressionVariableSP();
1573}
1574
1575lldb::ValueObjectSP
1576StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,
1577 lldb::addr_t *crashing_address) {
1578 if (!stop_info_sp) {
1579 return ValueObjectSP();
1580 }
1581
1582 const char *description = stop_info_sp->GetDescription();
1583 if (!description) {
1584 return ValueObjectSP();
1585 }
1586
1587 ThreadSP thread_sp = stop_info_sp->GetThread();
1588 if (!thread_sp) {
1589 return ValueObjectSP();
1590 }
1591
1592 StackFrameSP frame_sp =
1593 thread_sp->GetSelectedFrame(select_most_relevant: DoNoSelectMostRelevantFrame);
1594
1595 if (!frame_sp) {
1596 return ValueObjectSP();
1597 }
1598
1599 const char address_string[] = "address=";
1600
1601 const char *address_loc = strstr(haystack: description, needle: address_string);
1602 if (!address_loc) {
1603 return ValueObjectSP();
1604 }
1605
1606 address_loc += (sizeof(address_string) - 1);
1607
1608 uint64_t address = strtoull(nptr: address_loc, endptr: nullptr, base: 0);
1609 if (crashing_address) {
1610 *crashing_address = address;
1611 }
1612
1613 return frame_sp->GuessValueForAddress(addr: address);
1614}
1615

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of lldb/source/Target/StopInfo.cpp