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/Core/Debugger.h"
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Expression/UserExpression.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/StopInfo.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Target/ThreadPlan.h"
23 #include "lldb/Target/UnixSignals.h"
24 #include "lldb/Utility/Log.h"
25 #include "lldb/Utility/StreamString.h"
26
27 using namespace lldb;
28 using namespace lldb_private;
29
StopInfo(Thread & thread,uint64_t value)30 StopInfo::StopInfo(Thread &thread, uint64_t value)
31 : m_thread_wp(thread.shared_from_this()),
32 m_stop_id(thread.GetProcess()->GetStopID()),
33 m_resume_id(thread.GetProcess()->GetResumeID()), m_value(value),
34 m_description(), m_override_should_notify(eLazyBoolCalculate),
35 m_override_should_stop(eLazyBoolCalculate), m_extended_info() {}
36
IsValid() const37 bool StopInfo::IsValid() const {
38 ThreadSP thread_sp(m_thread_wp.lock());
39 if (thread_sp)
40 return thread_sp->GetProcess()->GetStopID() == m_stop_id;
41 return false;
42 }
43
MakeStopInfoValid()44 void StopInfo::MakeStopInfoValid() {
45 ThreadSP thread_sp(m_thread_wp.lock());
46 if (thread_sp) {
47 m_stop_id = thread_sp->GetProcess()->GetStopID();
48 m_resume_id = thread_sp->GetProcess()->GetResumeID();
49 }
50 }
51
HasTargetRunSinceMe()52 bool StopInfo::HasTargetRunSinceMe() {
53 ThreadSP thread_sp(m_thread_wp.lock());
54
55 if (thread_sp) {
56 lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState();
57 if (ret_type == eStateRunning) {
58 return true;
59 } else if (ret_type == eStateStopped) {
60 // This is a little tricky. We want to count "run and stopped again
61 // before you could ask this question as a "TRUE" answer to
62 // HasTargetRunSinceMe. But we don't want to include any running of the
63 // target done for expressions. So we track both resumes, and resumes
64 // caused by expressions, and check if there are any resumes
65 // NOT caused
66 // by expressions.
67
68 uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID();
69 uint32_t last_user_expression_id =
70 thread_sp->GetProcess()->GetLastUserExpressionResumeID();
71 if (curr_resume_id == m_resume_id) {
72 return false;
73 } else if (curr_resume_id > last_user_expression_id) {
74 return true;
75 }
76 }
77 }
78 return false;
79 }
80
81 // StopInfoBreakpoint
82
83 namespace lldb_private {
84 class StopInfoBreakpoint : public StopInfo {
85 public:
StopInfoBreakpoint(Thread & thread,break_id_t break_id)86 StopInfoBreakpoint(Thread &thread, break_id_t break_id)
87 : StopInfo(thread, break_id), m_should_stop(false),
88 m_should_stop_is_valid(false), m_should_perform_action(true),
89 m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
90 m_was_one_shot(false) {
91 StoreBPInfo();
92 }
93
StopInfoBreakpoint(Thread & thread,break_id_t break_id,bool should_stop)94 StopInfoBreakpoint(Thread &thread, break_id_t break_id, bool should_stop)
95 : StopInfo(thread, break_id), m_should_stop(should_stop),
96 m_should_stop_is_valid(true), m_should_perform_action(true),
97 m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
98 m_was_one_shot(false) {
99 StoreBPInfo();
100 }
101
102 ~StopInfoBreakpoint() override = default;
103
StoreBPInfo()104 void StoreBPInfo() {
105 ThreadSP thread_sp(m_thread_wp.lock());
106 if (thread_sp) {
107 BreakpointSiteSP bp_site_sp(
108 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
109 if (bp_site_sp) {
110 if (bp_site_sp->GetNumberOfOwners() == 1) {
111 BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0);
112 if (bp_loc_sp) {
113 m_break_id = bp_loc_sp->GetBreakpoint().GetID();
114 m_was_one_shot = bp_loc_sp->GetBreakpoint().IsOneShot();
115 }
116 }
117 m_address = bp_site_sp->GetLoadAddress();
118 }
119 }
120 }
121
IsValidForOperatingSystemThread(Thread & thread)122 bool IsValidForOperatingSystemThread(Thread &thread) override {
123 ProcessSP process_sp(thread.GetProcess());
124 if (process_sp) {
125 BreakpointSiteSP bp_site_sp(
126 process_sp->GetBreakpointSiteList().FindByID(m_value));
127 if (bp_site_sp)
128 return bp_site_sp->ValidForThisThread(thread);
129 }
130 return false;
131 }
132
GetStopReason() const133 StopReason GetStopReason() const override { return eStopReasonBreakpoint; }
134
ShouldStopSynchronous(Event * event_ptr)135 bool ShouldStopSynchronous(Event *event_ptr) override {
136 ThreadSP thread_sp(m_thread_wp.lock());
137 if (thread_sp) {
138 if (!m_should_stop_is_valid) {
139 // Only check once if we should stop at a breakpoint
140 BreakpointSiteSP bp_site_sp(
141 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
142 if (bp_site_sp) {
143 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
144 StoppointCallbackContext context(event_ptr, exe_ctx, true);
145 bp_site_sp->BumpHitCounts();
146 m_should_stop = bp_site_sp->ShouldStop(&context);
147 } else {
148 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
149
150 LLDB_LOGF(log,
151 "Process::%s could not find breakpoint site id: %" PRId64
152 "...",
153 __FUNCTION__, m_value);
154
155 m_should_stop = true;
156 }
157 m_should_stop_is_valid = true;
158 }
159 return m_should_stop;
160 }
161 return false;
162 }
163
DoShouldNotify(Event * event_ptr)164 bool DoShouldNotify(Event *event_ptr) override {
165 ThreadSP thread_sp(m_thread_wp.lock());
166 if (thread_sp) {
167 BreakpointSiteSP bp_site_sp(
168 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
169 if (bp_site_sp) {
170 bool all_internal = true;
171
172 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) {
173 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) {
174 all_internal = false;
175 break;
176 }
177 }
178 return !all_internal;
179 }
180 }
181 return true;
182 }
183
GetDescription()184 const char *GetDescription() override {
185 if (m_description.empty()) {
186 ThreadSP thread_sp(m_thread_wp.lock());
187 if (thread_sp) {
188 BreakpointSiteSP bp_site_sp(
189 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
190 if (bp_site_sp) {
191 StreamString strm;
192 // If we have just hit an internal breakpoint, and it has a kind
193 // description, print that instead of the full breakpoint printing:
194 if (bp_site_sp->IsInternal()) {
195 size_t num_owners = bp_site_sp->GetNumberOfOwners();
196 for (size_t idx = 0; idx < num_owners; idx++) {
197 const char *kind = bp_site_sp->GetOwnerAtIndex(idx)
198 ->GetBreakpoint()
199 .GetBreakpointKind();
200 if (kind != nullptr) {
201 m_description.assign(kind);
202 return kind;
203 }
204 }
205 }
206
207 strm.Printf("breakpoint ");
208 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
209 m_description = std::string(strm.GetString());
210 } else {
211 StreamString strm;
212 if (m_break_id != LLDB_INVALID_BREAK_ID) {
213 BreakpointSP break_sp =
214 thread_sp->GetProcess()->GetTarget().GetBreakpointByID(
215 m_break_id);
216 if (break_sp) {
217 if (break_sp->IsInternal()) {
218 const char *kind = break_sp->GetBreakpointKind();
219 if (kind)
220 strm.Printf("internal %s breakpoint(%d).", kind, m_break_id);
221 else
222 strm.Printf("internal breakpoint(%d).", m_break_id);
223 } else {
224 strm.Printf("breakpoint %d.", m_break_id);
225 }
226 } else {
227 if (m_was_one_shot)
228 strm.Printf("one-shot breakpoint %d", m_break_id);
229 else
230 strm.Printf("breakpoint %d which has been deleted.",
231 m_break_id);
232 }
233 } else if (m_address == LLDB_INVALID_ADDRESS)
234 strm.Printf("breakpoint site %" PRIi64
235 " which has been deleted - unknown address",
236 m_value);
237 else
238 strm.Printf("breakpoint site %" PRIi64
239 " which has been deleted - was at 0x%" PRIx64,
240 m_value, m_address);
241
242 m_description = std::string(strm.GetString());
243 }
244 }
245 }
246 return m_description.c_str();
247 }
248
249 protected:
ShouldStop(Event * event_ptr)250 bool ShouldStop(Event *event_ptr) override {
251 // This just reports the work done by PerformAction or the synchronous
252 // stop. It should only ever get called after they have had a chance to
253 // run.
254 assert(m_should_stop_is_valid);
255 return m_should_stop;
256 }
257
PerformAction(Event * event_ptr)258 void PerformAction(Event *event_ptr) override {
259 if (!m_should_perform_action)
260 return;
261 m_should_perform_action = false;
262 bool internal_breakpoint = true;
263
264 ThreadSP thread_sp(m_thread_wp.lock());
265
266 if (thread_sp) {
267 Log *log = lldb_private::GetLogIfAnyCategoriesSet(
268 LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_STEP);
269
270 if (!thread_sp->IsValid()) {
271 // This shouldn't ever happen, but just in case, don't do more harm.
272 if (log) {
273 LLDB_LOGF(log, "PerformAction got called with an invalid thread.");
274 }
275 m_should_stop = true;
276 m_should_stop_is_valid = true;
277 return;
278 }
279
280 BreakpointSiteSP bp_site_sp(
281 thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
282 std::unordered_set<break_id_t> precondition_breakpoints;
283
284 if (bp_site_sp) {
285 // Let's copy the owners list out of the site and store them in a local
286 // list. That way if one of the breakpoint actions changes the site,
287 // then we won't be operating on a bad list.
288 BreakpointLocationCollection site_locations;
289 size_t num_owners = bp_site_sp->CopyOwnersList(site_locations);
290
291 if (num_owners == 0) {
292 m_should_stop = true;
293 } else {
294 // We go through each location, and test first its precondition -
295 // this overrides everything. Note, we only do this once per
296 // breakpoint - not once per location... Then check the condition.
297 // If the condition says to stop, then we run the callback for that
298 // location. If that callback says to stop as well, then we set
299 // m_should_stop to true; we are going to stop. But we still want to
300 // give all the breakpoints whose conditions say we are going to stop
301 // a chance to run their callbacks. Of course if any callback
302 // restarts the target by putting "continue" in the callback, then
303 // we're going to restart, without running the rest of the callbacks.
304 // And in this case we will end up not stopping even if another
305 // location said we should stop. But that's better than not running
306 // all the callbacks.
307
308 // There's one other complication here. We may have run an async
309 // breakpoint callback that said we should stop. We only want to
310 // override that if another breakpoint action says we shouldn't
311 // stop. If nobody else has an opinion, then we should stop if the
312 // async callback says we should. An example of this is the async
313 // shared library load notification breakpoint and the setting
314 // stop-on-sharedlibrary-events.
315 // We'll keep the async value in async_should_stop, and track whether
316 // anyone said we should NOT stop in actually_said_continue.
317 bool async_should_stop = false;
318 if (m_should_stop_is_valid)
319 async_should_stop = m_should_stop;
320 bool actually_said_continue = false;
321
322 m_should_stop = false;
323
324 // We don't select threads as we go through them testing breakpoint
325 // conditions and running commands. So we need to set the thread for
326 // expression evaluation here:
327 ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);
328
329 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
330 Process *process = exe_ctx.GetProcessPtr();
331 if (process->GetModIDRef().IsLastResumeForUserExpression()) {
332 // If we are in the middle of evaluating an expression, don't run
333 // asynchronous breakpoint commands or expressions. That could
334 // lead to infinite recursion if the command or condition re-calls
335 // the function with this breakpoint.
336 // TODO: We can keep a list of the breakpoints we've seen while
337 // running expressions in the nested
338 // PerformAction calls that can arise when the action runs a
339 // function that hits another breakpoint, and only stop running
340 // commands when we see the same breakpoint hit a second time.
341
342 m_should_stop_is_valid = true;
343
344 // It is possible that the user has a breakpoint at the same site
345 // as the completed plan had (e.g. user has a breakpoint
346 // on a module entry point, and `ThreadPlanCallFunction` ends
347 // also there). We can't find an internal breakpoint in the loop
348 // later because it was already removed on the plan completion.
349 // So check if the plan was completed, and stop if so.
350 if (thread_sp->CompletedPlanOverridesBreakpoint()) {
351 m_should_stop = true;
352 thread_sp->ResetStopInfo();
353 return;
354 }
355
356 LLDB_LOGF(log, "StopInfoBreakpoint::PerformAction - Hit a "
357 "breakpoint while running an expression,"
358 " not running commands to avoid recursion.");
359 bool ignoring_breakpoints =
360 process->GetIgnoreBreakpointsInExpressions();
361 if (ignoring_breakpoints) {
362 m_should_stop = false;
363 // Internal breakpoints will always stop.
364 for (size_t j = 0; j < num_owners; j++) {
365 lldb::BreakpointLocationSP bp_loc_sp =
366 bp_site_sp->GetOwnerAtIndex(j);
367 if (bp_loc_sp->GetBreakpoint().IsInternal()) {
368 m_should_stop = true;
369 break;
370 }
371 }
372 } else {
373 m_should_stop = true;
374 }
375 LLDB_LOGF(log,
376 "StopInfoBreakpoint::PerformAction - in expression, "
377 "continuing: %s.",
378 m_should_stop ? "true" : "false");
379 process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf(
380 "Warning: hit breakpoint while running function, skipping "
381 "commands and conditions to prevent recursion.\n");
382 return;
383 }
384
385 StoppointCallbackContext context(event_ptr, exe_ctx, false);
386
387 // For safety's sake let's also grab an extra reference to the
388 // breakpoint owners of the locations we're going to examine, since
389 // the locations are going to have to get back to their breakpoints,
390 // and the locations don't keep their owners alive. I'm just
391 // sticking the BreakpointSP's in a vector since I'm only using it to
392 // locally increment their retain counts.
393
394 std::vector<lldb::BreakpointSP> location_owners;
395
396 for (size_t j = 0; j < num_owners; j++) {
397 BreakpointLocationSP loc(site_locations.GetByIndex(j));
398 location_owners.push_back(loc->GetBreakpoint().shared_from_this());
399 }
400
401 for (size_t j = 0; j < num_owners; j++) {
402 lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
403 StreamString loc_desc;
404 if (log) {
405 bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief);
406 }
407 // If another action disabled this breakpoint or its location, then
408 // don't run the actions.
409 if (!bp_loc_sp->IsEnabled() ||
410 !bp_loc_sp->GetBreakpoint().IsEnabled())
411 continue;
412
413 // The breakpoint site may have many locations associated with it,
414 // not all of them valid for this thread. Skip the ones that
415 // aren't:
416 if (!bp_loc_sp->ValidForThisThread(*thread_sp)) {
417 if (log) {
418 LLDB_LOGF(log,
419 "Breakpoint %s hit on thread 0x%llx but it was not "
420 "for this thread, continuing.",
421 loc_desc.GetData(),
422 static_cast<unsigned long long>(thread_sp->GetID()));
423 }
424 continue;
425 }
426
427 internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal();
428
429 // First run the precondition, but since the precondition is per
430 // breakpoint, only run it once per breakpoint.
431 std::pair<std::unordered_set<break_id_t>::iterator, bool> result =
432 precondition_breakpoints.insert(
433 bp_loc_sp->GetBreakpoint().GetID());
434 if (!result.second)
435 continue;
436
437 bool precondition_result =
438 bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);
439 if (!precondition_result) {
440 actually_said_continue = true;
441 continue;
442 }
443 // Next run the condition for the breakpoint. If that says we
444 // should stop, then we'll run the callback for the breakpoint. If
445 // the callback says we shouldn't stop that will win.
446
447 if (bp_loc_sp->GetConditionText() != nullptr) {
448 Status condition_error;
449 bool condition_says_stop =
450 bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);
451
452 if (!condition_error.Success()) {
453 Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
454 StreamSP error_sp = debugger.GetAsyncErrorStream();
455 error_sp->Printf("Stopped due to an error evaluating condition "
456 "of breakpoint ");
457 bp_loc_sp->GetDescription(error_sp.get(),
458 eDescriptionLevelBrief);
459 error_sp->Printf(": \"%s\"", bp_loc_sp->GetConditionText());
460 error_sp->EOL();
461 const char *err_str =
462 condition_error.AsCString("<Unknown Error>");
463 LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);
464
465 error_sp->PutCString(err_str);
466 error_sp->EOL();
467 error_sp->Flush();
468 } else {
469 LLDB_LOGF(log,
470 "Condition evaluated for breakpoint %s on thread "
471 "0x%llx condition_says_stop: %i.",
472 loc_desc.GetData(),
473 static_cast<unsigned long long>(thread_sp->GetID()),
474 condition_says_stop);
475 if (!condition_says_stop) {
476 // We don't want to increment the hit count of breakpoints if
477 // the condition fails. We've already bumped it by the time
478 // we get here, so undo the bump:
479 bp_loc_sp->UndoBumpHitCount();
480 actually_said_continue = true;
481 continue;
482 }
483 }
484 }
485
486 // We've done all the checks whose failure means "we consider lldb
487 // not to have hit the breakpoint". Now we're going to check for
488 // conditions that might continue after hitting. Start with the
489 // ignore count:
490 if (!bp_loc_sp->IgnoreCountShouldStop()) {
491 actually_said_continue = true;
492 continue;
493 }
494
495 // Check the auto-continue bit on the location, do this before the
496 // callback since it may change this, but that would be for the
497 // NEXT hit. Note, you might think you could check auto-continue
498 // before the condition, and not evaluate the condition if it says
499 // to continue. But failing the condition means the breakpoint was
500 // effectively NOT HIT. So these two states are different.
501 bool auto_continue_says_stop = true;
502 if (bp_loc_sp->IsAutoContinue())
503 {
504 LLDB_LOGF(log,
505 "Continuing breakpoint %s as AutoContinue was set.",
506 loc_desc.GetData());
507 // We want this stop reported, so you will know we auto-continued
508 // but only for external breakpoints:
509 if (!internal_breakpoint)
510 thread_sp->SetShouldReportStop(eVoteYes);
511 auto_continue_says_stop = false;
512 }
513
514 bool callback_says_stop = true;
515
516 // FIXME: For now the callbacks have to run in async mode - the
517 // first time we restart we need
518 // to get out of there. So set it here.
519 // When we figure out how to nest breakpoint hits then this will
520 // change.
521
522 // Don't run async callbacks in PerformAction. They have already
523 // been taken into account with async_should_stop.
524 if (!bp_loc_sp->IsCallbackSynchronous()) {
525 Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
526 bool old_async = debugger.GetAsyncExecution();
527 debugger.SetAsyncExecution(true);
528
529 callback_says_stop = bp_loc_sp->InvokeCallback(&context);
530
531 debugger.SetAsyncExecution(old_async);
532
533 if (callback_says_stop && auto_continue_says_stop)
534 m_should_stop = true;
535 else
536 actually_said_continue = true;
537 }
538
539 // If we are going to stop for this breakpoint, then remove the
540 // breakpoint.
541 if (callback_says_stop && bp_loc_sp &&
542 bp_loc_sp->GetBreakpoint().IsOneShot()) {
543 thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(
544 bp_loc_sp->GetBreakpoint().GetID());
545 }
546 // Also make sure that the callback hasn't continued the target. If
547 // it did, when we'll set m_should_start to false and get out of
548 // here.
549 if (HasTargetRunSinceMe()) {
550 m_should_stop = false;
551 actually_said_continue = true;
552 break;
553 }
554 }
555 // At this point if nobody actually told us to continue, we should
556 // give the async breakpoint callback a chance to weigh in:
557 if (!actually_said_continue && !m_should_stop) {
558 m_should_stop = async_should_stop;
559 }
560 }
561 // We've figured out what this stop wants to do, so mark it as valid so
562 // we don't compute it again.
563 m_should_stop_is_valid = true;
564 } else {
565 m_should_stop = true;
566 m_should_stop_is_valid = true;
567 Log *log_process(
568 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
569
570 LLDB_LOGF(log_process,
571 "Process::%s could not find breakpoint site id: %" PRId64
572 "...",
573 __FUNCTION__, m_value);
574 }
575
576 if ((!m_should_stop || internal_breakpoint) &&
577 thread_sp->CompletedPlanOverridesBreakpoint()) {
578
579 // Override should_stop decision when we have completed step plan
580 // additionally to the breakpoint
581 m_should_stop = true;
582
583 // We know we're stopping for a completed plan and we don't want to
584 // show the breakpoint stop, so compute the public stop info immediately
585 // here.
586 thread_sp->CalculatePublicStopInfo();
587 }
588
589 LLDB_LOGF(log,
590 "Process::%s returning from action with m_should_stop: %d.",
591 __FUNCTION__, m_should_stop);
592 }
593 }
594
595 private:
596 bool m_should_stop;
597 bool m_should_stop_is_valid;
598 bool m_should_perform_action; // Since we are trying to preserve the "state"
599 // of the system even if we run functions
600 // etc. behind the users backs, we need to make sure we only REALLY perform
601 // the action once.
602 lldb::addr_t m_address; // We use this to capture the breakpoint site address
603 // when we create the StopInfo,
604 // in case somebody deletes it between the time the StopInfo is made and the
605 // description is asked for.
606 lldb::break_id_t m_break_id;
607 bool m_was_one_shot;
608 };
609
610 // StopInfoWatchpoint
611
612 class StopInfoWatchpoint : public StopInfo {
613 public:
614 // Make sure watchpoint is properly disabled and subsequently enabled while
615 // performing watchpoint actions.
616 class WatchpointSentry {
617 public:
WatchpointSentry(ProcessSP p_sp,WatchpointSP w_sp)618 WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),
619 watchpoint_sp(w_sp) {
620 if (process_sp && watchpoint_sp) {
621 const bool notify = false;
622 watchpoint_sp->TurnOnEphemeralMode();
623 process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
624 process_sp->AddPreResumeAction(SentryPreResumeAction, this);
625 }
626 }
627
DoReenable()628 void DoReenable() {
629 if (process_sp && watchpoint_sp) {
630 bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();
631 watchpoint_sp->TurnOffEphemeralMode();
632 const bool notify = false;
633 if (was_disabled) {
634 process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
635 } else {
636 process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);
637 }
638 }
639 }
640
~WatchpointSentry()641 ~WatchpointSentry() {
642 DoReenable();
643 if (process_sp)
644 process_sp->ClearPreResumeAction(SentryPreResumeAction, this);
645 }
646
SentryPreResumeAction(void * sentry_void)647 static bool SentryPreResumeAction(void *sentry_void) {
648 WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;
649 sentry->DoReenable();
650 return true;
651 }
652
653 private:
654 ProcessSP process_sp;
655 WatchpointSP watchpoint_sp;
656 };
657
StopInfoWatchpoint(Thread & thread,break_id_t watch_id,lldb::addr_t watch_hit_addr)658 StopInfoWatchpoint(Thread &thread, break_id_t watch_id,
659 lldb::addr_t watch_hit_addr)
660 : StopInfo(thread, watch_id), m_should_stop(false),
661 m_should_stop_is_valid(false), m_watch_hit_addr(watch_hit_addr) {}
662
663 ~StopInfoWatchpoint() override = default;
664
GetStopReason() const665 StopReason GetStopReason() const override { return eStopReasonWatchpoint; }
666
GetDescription()667 const char *GetDescription() override {
668 if (m_description.empty()) {
669 StreamString strm;
670 strm.Printf("watchpoint %" PRIi64, m_value);
671 m_description = std::string(strm.GetString());
672 }
673 return m_description.c_str();
674 }
675
676 protected:
ShouldStopSynchronous(Event * event_ptr)677 bool ShouldStopSynchronous(Event *event_ptr) override {
678 // ShouldStop() method is idempotent and should not affect hit count. See
679 // Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
680 // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()->
681 // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()->
682 // StopInfoWatchpoint::ShouldStop() and
683 // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()->
684 // StopInfoWatchpoint::PerformAction().
685 if (m_should_stop_is_valid)
686 return m_should_stop;
687
688 ThreadSP thread_sp(m_thread_wp.lock());
689 if (thread_sp) {
690 WatchpointSP wp_sp(
691 thread_sp->CalculateTarget()->GetWatchpointList().FindByID(
692 GetValue()));
693 if (wp_sp) {
694 // Check if we should stop at a watchpoint.
695 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
696 StoppointCallbackContext context(event_ptr, exe_ctx, true);
697 m_should_stop = wp_sp->ShouldStop(&context);
698 } else {
699 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
700
701 LLDB_LOGF(log,
702 "Process::%s could not find watchpoint location id: %" PRId64
703 "...",
704 __FUNCTION__, GetValue());
705
706 m_should_stop = true;
707 }
708 }
709 m_should_stop_is_valid = true;
710 return m_should_stop;
711 }
712
ShouldStop(Event * event_ptr)713 bool ShouldStop(Event *event_ptr) override {
714 // This just reports the work done by PerformAction or the synchronous
715 // stop. It should only ever get called after they have had a chance to
716 // run.
717 assert(m_should_stop_is_valid);
718 return m_should_stop;
719 }
720
PerformAction(Event * event_ptr)721 void PerformAction(Event *event_ptr) override {
722 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS);
723 // We're going to calculate if we should stop or not in some way during the
724 // course of this code. Also by default we're going to stop, so set that
725 // here.
726 m_should_stop = true;
727
728
729 ThreadSP thread_sp(m_thread_wp.lock());
730 if (thread_sp) {
731
732 WatchpointSP wp_sp(
733 thread_sp->CalculateTarget()->GetWatchpointList().FindByID(
734 GetValue()));
735 if (wp_sp) {
736 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
737 ProcessSP process_sp = exe_ctx.GetProcessSP();
738
739 {
740 // check if this process is running on an architecture where
741 // watchpoints trigger before the associated instruction runs. if so,
742 // disable the WP, single-step and then re-enable the watchpoint
743 if (process_sp) {
744 uint32_t num;
745 bool wp_triggers_after;
746
747 if (process_sp->GetWatchpointSupportInfo(num, wp_triggers_after)
748 .Success()) {
749 if (!wp_triggers_after) {
750 // We need to preserve the watch_index before watchpoint is
751 // disable. Since Watchpoint::SetEnabled will clear the watch
752 // index. This will fix TestWatchpointIter failure
753 Watchpoint *wp = wp_sp.get();
754 uint32_t watch_index = wp->GetHardwareIndex();
755 process_sp->DisableWatchpoint(wp, false);
756 StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo();
757 assert(stored_stop_info_sp.get() == this);
758
759 Status new_plan_status;
760 ThreadPlanSP new_plan_sp(
761 thread_sp->QueueThreadPlanForStepSingleInstruction(
762 false, // step-over
763 false, // abort_other_plans
764 true, // stop_other_threads
765 new_plan_status));
766 if (new_plan_sp && new_plan_status.Success()) {
767 new_plan_sp->SetIsMasterPlan(true);
768 new_plan_sp->SetOkayToDiscard(false);
769 new_plan_sp->SetPrivate(true);
770 }
771 process_sp->GetThreadList().SetSelectedThreadByID(
772 thread_sp->GetID());
773 process_sp->ResumeSynchronous(nullptr);
774 process_sp->GetThreadList().SetSelectedThreadByID(
775 thread_sp->GetID());
776 thread_sp->SetStopInfo(stored_stop_info_sp);
777 process_sp->EnableWatchpoint(wp, false);
778 wp->SetHardwareIndex(watch_index);
779 }
780 }
781 }
782 }
783
784 // This sentry object makes sure the current watchpoint is disabled
785 // while performing watchpoint actions, and it is then enabled after we
786 // are finished.
787 WatchpointSentry sentry(process_sp, wp_sp);
788
789 /*
790 * MIPS: Last 3bits of the watchpoint address are masked by the kernel.
791 * For example:
792 * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is
793 * set at 'm', then
794 * watch exception is generated even when 'n' is read/written. To handle
795 * this case,
796 * server emulates the instruction at PC and finds the base address of
797 * the load/store
798 * instruction and appends it in the description of the stop-info
799 * packet. If watchpoint
800 * is not set on this address by user then this do not stop.
801 */
802 if (m_watch_hit_addr != LLDB_INVALID_ADDRESS) {
803 WatchpointSP wp_hit_sp =
804 thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress(
805 m_watch_hit_addr);
806 if (!wp_hit_sp) {
807 m_should_stop = false;
808 wp_sp->IncrementFalseAlarmsAndReviseHitCount();
809 }
810 }
811
812 // TODO: This condition should be checked in the synchronous part of the
813 // watchpoint code
814 // (Watchpoint::ShouldStop), so that we avoid pulling an event even if
815 // the watchpoint fails the ignore count condition. It is moved here
816 // temporarily, because for archs with
817 // watchpoint_exceptions_received=before, the code in the previous
818 // lines takes care of moving the inferior to next PC. We have to check
819 // the ignore count condition after this is done, otherwise we will hit
820 // same watchpoint multiple times until we pass ignore condition, but
821 // we won't actually be ignoring them.
822 if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount())
823 m_should_stop = false;
824
825 Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
826
827 if (m_should_stop && wp_sp->GetConditionText() != nullptr) {
828 // We need to make sure the user sees any parse errors in their
829 // condition, so we'll hook the constructor errors up to the
830 // debugger's Async I/O.
831 ExpressionResults result_code;
832 EvaluateExpressionOptions expr_options;
833 expr_options.SetUnwindOnError(true);
834 expr_options.SetIgnoreBreakpoints(true);
835 ValueObjectSP result_value_sp;
836 Status error;
837 result_code = UserExpression::Evaluate(
838 exe_ctx, expr_options, wp_sp->GetConditionText(),
839 llvm::StringRef(), result_value_sp, error);
840
841 if (result_code == eExpressionCompleted) {
842 if (result_value_sp) {
843 Scalar scalar_value;
844 if (result_value_sp->ResolveValue(scalar_value)) {
845 if (scalar_value.ULongLong(1) == 0) {
846 // We have been vetoed. This takes precedence over querying
847 // the watchpoint whether it should stop (aka ignore count
848 // and friends). See also StopInfoWatchpoint::ShouldStop()
849 // as well as Process::ProcessEventData::DoOnRemoval().
850 m_should_stop = false;
851 } else
852 m_should_stop = true;
853 LLDB_LOGF(log,
854 "Condition successfully evaluated, result is %s.\n",
855 m_should_stop ? "true" : "false");
856 } else {
857 m_should_stop = true;
858 LLDB_LOGF(
859 log,
860 "Failed to get an integer result from the expression.");
861 }
862 }
863 } else {
864 StreamSP error_sp = debugger.GetAsyncErrorStream();
865 error_sp->Printf(
866 "Stopped due to an error evaluating condition of watchpoint ");
867 wp_sp->GetDescription(error_sp.get(), eDescriptionLevelBrief);
868 error_sp->Printf(": \"%s\"", wp_sp->GetConditionText());
869 error_sp->EOL();
870 const char *err_str = error.AsCString("<Unknown Error>");
871 LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);
872
873 error_sp->PutCString(err_str);
874 error_sp->EOL();
875 error_sp->Flush();
876 // If the condition fails to be parsed or run, we should stop.
877 m_should_stop = true;
878 }
879 }
880
881 // If the condition says to stop, we run the callback to further decide
882 // whether to stop.
883 if (m_should_stop) {
884 // FIXME: For now the callbacks have to run in async mode - the
885 // first time we restart we need
886 // to get out of there. So set it here.
887 // When we figure out how to nest watchpoint hits then this will
888 // change.
889
890 bool old_async = debugger.GetAsyncExecution();
891 debugger.SetAsyncExecution(true);
892
893 StoppointCallbackContext context(event_ptr, exe_ctx, false);
894 bool stop_requested = wp_sp->InvokeCallback(&context);
895
896 debugger.SetAsyncExecution(old_async);
897
898 // Also make sure that the callback hasn't continued the target. If
899 // it did, when we'll set m_should_stop to false and get out of here.
900 if (HasTargetRunSinceMe())
901 m_should_stop = false;
902
903 if (m_should_stop && !stop_requested) {
904 // We have been vetoed by the callback mechanism.
905 m_should_stop = false;
906 }
907 }
908 // Finally, if we are going to stop, print out the new & old values:
909 if (m_should_stop) {
910 wp_sp->CaptureWatchedValue(exe_ctx);
911
912 Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
913 StreamSP output_sp = debugger.GetAsyncOutputStream();
914 wp_sp->DumpSnapshots(output_sp.get());
915 output_sp->EOL();
916 output_sp->Flush();
917 }
918
919 } else {
920 Log *log_process(
921 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
922
923 LLDB_LOGF(log_process,
924 "Process::%s could not find watchpoint id: %" PRId64 "...",
925 __FUNCTION__, m_value);
926 }
927 LLDB_LOGF(log,
928 "Process::%s returning from action with m_should_stop: %d.",
929 __FUNCTION__, m_should_stop);
930
931 m_should_stop_is_valid = true;
932 }
933 }
934
935 private:
936 bool m_should_stop;
937 bool m_should_stop_is_valid;
938 lldb::addr_t m_watch_hit_addr;
939 };
940
941 // StopInfoUnixSignal
942
943 class StopInfoUnixSignal : public StopInfo {
944 public:
StopInfoUnixSignal(Thread & thread,int signo,const char * description)945 StopInfoUnixSignal(Thread &thread, int signo, const char *description)
946 : StopInfo(thread, signo) {
947 SetDescription(description);
948 }
949
950 ~StopInfoUnixSignal() override = default;
951
GetStopReason() const952 StopReason GetStopReason() const override { return eStopReasonSignal; }
953
ShouldStopSynchronous(Event * event_ptr)954 bool ShouldStopSynchronous(Event *event_ptr) override {
955 ThreadSP thread_sp(m_thread_wp.lock());
956 if (thread_sp)
957 return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
958 return false;
959 }
960
ShouldStop(Event * event_ptr)961 bool ShouldStop(Event *event_ptr) override {
962 ThreadSP thread_sp(m_thread_wp.lock());
963 if (thread_sp)
964 return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
965 return false;
966 }
967
968 // If should stop returns false, check if we should notify of this event
DoShouldNotify(Event * event_ptr)969 bool DoShouldNotify(Event *event_ptr) override {
970 ThreadSP thread_sp(m_thread_wp.lock());
971 if (thread_sp) {
972 bool should_notify =
973 thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value);
974 if (should_notify) {
975 StreamString strm;
976 strm.Printf(
977 "thread %d received signal: %s", thread_sp->GetIndexID(),
978 thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(
979 m_value));
980 Process::ProcessEventData::AddRestartedReason(event_ptr,
981 strm.GetData());
982 }
983 return should_notify;
984 }
985 return true;
986 }
987
WillResume(lldb::StateType resume_state)988 void WillResume(lldb::StateType resume_state) override {
989 ThreadSP thread_sp(m_thread_wp.lock());
990 if (thread_sp) {
991 if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(
992 m_value))
993 thread_sp->SetResumeSignal(m_value);
994 }
995 }
996
GetDescription()997 const char *GetDescription() override {
998 if (m_description.empty()) {
999 ThreadSP thread_sp(m_thread_wp.lock());
1000 if (thread_sp) {
1001 StreamString strm;
1002 const char *signal_name =
1003 thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(
1004 m_value);
1005 if (signal_name)
1006 strm.Printf("signal %s", signal_name);
1007 else
1008 strm.Printf("signal %" PRIi64, m_value);
1009 m_description = std::string(strm.GetString());
1010 }
1011 }
1012 return m_description.c_str();
1013 }
1014 };
1015
1016 // StopInfoTrace
1017
1018 class StopInfoTrace : public StopInfo {
1019 public:
StopInfoTrace(Thread & thread)1020 StopInfoTrace(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}
1021
1022 ~StopInfoTrace() override = default;
1023
GetStopReason() const1024 StopReason GetStopReason() const override { return eStopReasonTrace; }
1025
GetDescription()1026 const char *GetDescription() override {
1027 if (m_description.empty())
1028 return "trace";
1029 else
1030 return m_description.c_str();
1031 }
1032 };
1033
1034 // StopInfoException
1035
1036 class StopInfoException : public StopInfo {
1037 public:
StopInfoException(Thread & thread,const char * description)1038 StopInfoException(Thread &thread, const char *description)
1039 : StopInfo(thread, LLDB_INVALID_UID) {
1040 if (description)
1041 SetDescription(description);
1042 }
1043
1044 ~StopInfoException() override = default;
1045
GetStopReason() const1046 StopReason GetStopReason() const override { return eStopReasonException; }
1047
GetDescription()1048 const char *GetDescription() override {
1049 if (m_description.empty())
1050 return "exception";
1051 else
1052 return m_description.c_str();
1053 }
1054 };
1055
1056 // StopInfoProcessorTrace
1057
1058 class StopInfoProcessorTrace : public StopInfo {
1059 public:
StopInfoProcessorTrace(Thread & thread,const char * description)1060 StopInfoProcessorTrace(Thread &thread, const char *description)
1061 : StopInfo(thread, LLDB_INVALID_UID) {
1062 if (description)
1063 SetDescription(description);
1064 }
1065
1066 ~StopInfoProcessorTrace() override = default;
1067
GetStopReason() const1068 StopReason GetStopReason() const override {
1069 return eStopReasonProcessorTrace;
1070 }
1071
GetDescription()1072 const char *GetDescription() override {
1073 if (m_description.empty())
1074 return "processor trace event";
1075 else
1076 return m_description.c_str();
1077 }
1078 };
1079
1080 // StopInfoThreadPlan
1081
1082 class StopInfoThreadPlan : public StopInfo {
1083 public:
StopInfoThreadPlan(ThreadPlanSP & plan_sp,ValueObjectSP & return_valobj_sp,ExpressionVariableSP & expression_variable_sp)1084 StopInfoThreadPlan(ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp,
1085 ExpressionVariableSP &expression_variable_sp)
1086 : StopInfo(plan_sp->GetThread(), LLDB_INVALID_UID), m_plan_sp(plan_sp),
1087 m_return_valobj_sp(return_valobj_sp),
1088 m_expression_variable_sp(expression_variable_sp) {}
1089
1090 ~StopInfoThreadPlan() override = default;
1091
GetStopReason() const1092 StopReason GetStopReason() const override { return eStopReasonPlanComplete; }
1093
GetDescription()1094 const char *GetDescription() override {
1095 if (m_description.empty()) {
1096 StreamString strm;
1097 m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief);
1098 m_description = std::string(strm.GetString());
1099 }
1100 return m_description.c_str();
1101 }
1102
GetReturnValueObject()1103 ValueObjectSP GetReturnValueObject() { return m_return_valobj_sp; }
1104
GetExpressionVariable()1105 ExpressionVariableSP GetExpressionVariable() {
1106 return m_expression_variable_sp;
1107 }
1108
1109 protected:
ShouldStop(Event * event_ptr)1110 bool ShouldStop(Event *event_ptr) override {
1111 if (m_plan_sp)
1112 return m_plan_sp->ShouldStop(event_ptr);
1113 else
1114 return StopInfo::ShouldStop(event_ptr);
1115 }
1116
1117 private:
1118 ThreadPlanSP m_plan_sp;
1119 ValueObjectSP m_return_valobj_sp;
1120 ExpressionVariableSP m_expression_variable_sp;
1121 };
1122
1123 // StopInfoExec
1124
1125 class StopInfoExec : public StopInfo {
1126 public:
StopInfoExec(Thread & thread)1127 StopInfoExec(Thread &thread)
1128 : StopInfo(thread, LLDB_INVALID_UID), m_performed_action(false) {}
1129
1130 ~StopInfoExec() override = default;
1131
ShouldStop(Event * event_ptr)1132 bool ShouldStop(Event *event_ptr) override {
1133 ThreadSP thread_sp(m_thread_wp.lock());
1134 if (thread_sp)
1135 return thread_sp->GetProcess()->GetStopOnExec();
1136 return false;
1137 }
1138
GetStopReason() const1139 StopReason GetStopReason() const override { return eStopReasonExec; }
1140
GetDescription()1141 const char *GetDescription() override { return "exec"; }
1142
1143 protected:
PerformAction(Event * event_ptr)1144 void PerformAction(Event *event_ptr) override {
1145 // Only perform the action once
1146 if (m_performed_action)
1147 return;
1148 m_performed_action = true;
1149 ThreadSP thread_sp(m_thread_wp.lock());
1150 if (thread_sp)
1151 thread_sp->GetProcess()->DidExec();
1152 }
1153
1154 bool m_performed_action;
1155 };
1156
1157 } // namespace lldb_private
1158
CreateStopReasonWithBreakpointSiteID(Thread & thread,break_id_t break_id)1159 StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
1160 break_id_t break_id) {
1161 return StopInfoSP(new StopInfoBreakpoint(thread, break_id));
1162 }
1163
CreateStopReasonWithBreakpointSiteID(Thread & thread,break_id_t break_id,bool should_stop)1164 StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
1165 break_id_t break_id,
1166 bool should_stop) {
1167 return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));
1168 }
1169
1170 StopInfoSP
CreateStopReasonWithWatchpointID(Thread & thread,break_id_t watch_id,lldb::addr_t watch_hit_addr)1171 StopInfo::CreateStopReasonWithWatchpointID(Thread &thread, break_id_t watch_id,
1172 lldb::addr_t watch_hit_addr) {
1173 return StopInfoSP(new StopInfoWatchpoint(thread, watch_id, watch_hit_addr));
1174 }
1175
CreateStopReasonWithSignal(Thread & thread,int signo,const char * description)1176 StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
1177 const char *description) {
1178 return StopInfoSP(new StopInfoUnixSignal(thread, signo, description));
1179 }
1180
CreateStopReasonToTrace(Thread & thread)1181 StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {
1182 return StopInfoSP(new StopInfoTrace(thread));
1183 }
1184
CreateStopReasonWithPlan(ThreadPlanSP & plan_sp,ValueObjectSP return_valobj_sp,ExpressionVariableSP expression_variable_sp)1185 StopInfoSP StopInfo::CreateStopReasonWithPlan(
1186 ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp,
1187 ExpressionVariableSP expression_variable_sp) {
1188 return StopInfoSP(new StopInfoThreadPlan(plan_sp, return_valobj_sp,
1189 expression_variable_sp));
1190 }
1191
CreateStopReasonWithException(Thread & thread,const char * description)1192 StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread,
1193 const char *description) {
1194 return StopInfoSP(new StopInfoException(thread, description));
1195 }
1196
CreateStopReasonProcessorTrace(Thread & thread,const char * description)1197 StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,
1198 const char *description) {
1199 return StopInfoSP(new StopInfoProcessorTrace(thread, description));
1200 }
1201
CreateStopReasonWithExec(Thread & thread)1202 StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {
1203 return StopInfoSP(new StopInfoExec(thread));
1204 }
1205
GetReturnValueObject(StopInfoSP & stop_info_sp)1206 ValueObjectSP StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) {
1207 if (stop_info_sp &&
1208 stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
1209 StopInfoThreadPlan *plan_stop_info =
1210 static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
1211 return plan_stop_info->GetReturnValueObject();
1212 } else
1213 return ValueObjectSP();
1214 }
1215
GetExpressionVariable(StopInfoSP & stop_info_sp)1216 ExpressionVariableSP StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) {
1217 if (stop_info_sp &&
1218 stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
1219 StopInfoThreadPlan *plan_stop_info =
1220 static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
1221 return plan_stop_info->GetExpressionVariable();
1222 } else
1223 return ExpressionVariableSP();
1224 }
1225
1226 lldb::ValueObjectSP
GetCrashingDereference(StopInfoSP & stop_info_sp,lldb::addr_t * crashing_address)1227 StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,
1228 lldb::addr_t *crashing_address) {
1229 if (!stop_info_sp) {
1230 return ValueObjectSP();
1231 }
1232
1233 const char *description = stop_info_sp->GetDescription();
1234 if (!description) {
1235 return ValueObjectSP();
1236 }
1237
1238 ThreadSP thread_sp = stop_info_sp->GetThread();
1239 if (!thread_sp) {
1240 return ValueObjectSP();
1241 }
1242
1243 StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
1244
1245 if (!frame_sp) {
1246 return ValueObjectSP();
1247 }
1248
1249 const char address_string[] = "address=";
1250
1251 const char *address_loc = strstr(description, address_string);
1252 if (!address_loc) {
1253 return ValueObjectSP();
1254 }
1255
1256 address_loc += (sizeof(address_string) - 1);
1257
1258 uint64_t address = strtoull(address_loc, nullptr, 0);
1259 if (crashing_address) {
1260 *crashing_address = address;
1261 }
1262
1263 return frame_sp->GuessValueForAddress(address);
1264 }
1265