1727 lines · cpp
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-exception6//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 again65 // before you could ask this question as a "TRUE" answer to66 // HasTargetRunSinceMe. But we don't want to include any running of the67 // target done for expressions. So we track both resumes, and resumes68 // caused by expressions, and check if there are any resumes69 // NOT caused70 // 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// StopInfoBreakpoint86 87namespace lldb_private {88class StopInfoBreakpoint : public StopInfo {89public:90 // We use a "breakpoint preserving BreakpointLocationCollection because we91 // may need to hand out the "breakpoint hit" list as any point, potentially92 // after the breakpoint has been deleted. But we still need to refer to them.93 StopInfoBreakpoint(Thread &thread, break_id_t break_id)94 : StopInfo(thread, break_id), m_should_stop(false),95 m_should_stop_is_valid(false), m_should_perform_action(true),96 m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),97 m_was_all_internal(false), m_was_one_shot(false),98 m_async_stopped_locs(true) {99 StoreBPInfo();100 }101 102 StopInfoBreakpoint(Thread &thread, break_id_t break_id, bool should_stop)103 : StopInfo(thread, break_id), m_should_stop(should_stop),104 m_should_stop_is_valid(true), m_should_perform_action(true),105 m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),106 m_was_all_internal(false), m_was_one_shot(false),107 m_async_stopped_locs(true) {108 StoreBPInfo();109 }110 111 ~StopInfoBreakpoint() override = default;112 113 void StoreBPInfo() {114 ThreadSP thread_sp(m_thread_wp.lock());115 if (thread_sp) {116 BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();117 if (bp_site_sp) {118 uint32_t num_constituents = bp_site_sp->GetNumberOfConstituents();119 if (num_constituents == 1) {120 BreakpointLocationSP bp_loc_sp = bp_site_sp->GetConstituentAtIndex(0);121 if (bp_loc_sp) {122 Breakpoint & bkpt = bp_loc_sp->GetBreakpoint();123 m_break_id = bkpt.GetID();124 m_was_one_shot = bkpt.IsOneShot();125 m_was_all_internal = bkpt.IsInternal();126 }127 } else {128 m_was_all_internal = true;129 for (uint32_t i = 0; i < num_constituents; i++) {130 if (!bp_site_sp->GetConstituentAtIndex(i)131 ->GetBreakpoint()132 .IsInternal()) {133 m_was_all_internal = false;134 break;135 }136 }137 }138 m_address = bp_site_sp->GetLoadAddress();139 }140 }141 }142 143 bool IsValidForOperatingSystemThread(Thread &thread) override {144 ProcessSP process_sp(thread.GetProcess());145 if (process_sp) {146 BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();147 if (bp_site_sp)148 return bp_site_sp->ValidForThisThread(thread);149 }150 return false;151 }152 153 StopReason GetStopReason() const override { return eStopReasonBreakpoint; }154 155 bool ShouldStopSynchronous(Event *event_ptr) override {156 ThreadSP thread_sp(m_thread_wp.lock());157 if (thread_sp) {158 if (!m_should_stop_is_valid) {159 // Only check once if we should stop at a breakpoint160 BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();161 if (bp_site_sp) {162 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));163 StoppointCallbackContext context(event_ptr, exe_ctx, true);164 bp_site_sp->BumpHitCounts();165 m_should_stop =166 bp_site_sp->ShouldStop(&context, m_async_stopped_locs);167 } else {168 Log *log = GetLog(LLDBLog::Process);169 170 LLDB_LOGF(log,171 "Process::%s could not find breakpoint site id: %" PRId64172 "...",173 __FUNCTION__, m_value);174 175 m_should_stop = true;176 }177 m_should_stop_is_valid = true;178 }179 return m_should_stop;180 }181 return false;182 }183 184 bool DoShouldNotify(Event *event_ptr) override {185 return !m_was_all_internal;186 }187 188 const char *GetDescription() override {189 // FIXME: only print m_async_stopped_locs.190 if (m_description.empty()) {191 ThreadSP thread_sp(m_thread_wp.lock());192 if (thread_sp) {193 BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();194 if (bp_site_sp) {195 StreamString strm;196 // If we have just hit an internal breakpoint, and it has a kind197 // description, print that instead of the full breakpoint printing:198 if (bp_site_sp->IsInternal()) {199 size_t num_constituents = bp_site_sp->GetNumberOfConstituents();200 for (size_t idx = 0; idx < num_constituents; idx++) {201 const char *kind = bp_site_sp->GetConstituentAtIndex(idx)202 ->GetBreakpoint()203 .GetBreakpointKind();204 if (kind != nullptr) {205 m_description.assign(kind);206 return kind;207 }208 }209 }210 211 strm.Printf("breakpoint ");212 m_async_stopped_locs.GetDescription(&strm, eDescriptionLevelBrief);213 m_description = std::string(strm.GetString());214 } else {215 StreamString strm;216 if (m_break_id != LLDB_INVALID_BREAK_ID) {217 BreakpointSP break_sp =218 thread_sp->GetProcess()->GetTarget().GetBreakpointByID(219 m_break_id);220 if (break_sp) {221 if (break_sp->IsInternal()) {222 const char *kind = break_sp->GetBreakpointKind();223 if (kind)224 strm.Printf("internal %s breakpoint(%d).", kind, m_break_id);225 else226 strm.Printf("internal breakpoint(%d).", m_break_id);227 } else {228 strm.Printf("breakpoint %d.", m_break_id);229 }230 } else {231 if (m_was_one_shot)232 strm.Printf("one-shot breakpoint %d", m_break_id);233 else234 strm.Printf("breakpoint %d which has been deleted.",235 m_break_id);236 }237 } else if (m_address == LLDB_INVALID_ADDRESS)238 strm.Printf("breakpoint site %" PRIi64239 " which has been deleted - unknown address",240 m_value);241 else242 strm.Printf("breakpoint site %" PRIi64243 " which has been deleted - was at 0x%" PRIx64,244 m_value, m_address);245 246 m_description = std::string(strm.GetString());247 }248 }249 }250 return m_description.c_str();251 }252 253 uint32_t GetStopReasonDataCount() const override {254 size_t num_async_locs = m_async_stopped_locs.GetSize();255 // If we have async locations, they are the ones we should report:256 if (num_async_locs > 0)257 return num_async_locs * 2;258 259 // Otherwise report the number of locations at this breakpoint's site.260 lldb::BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();261 if (bp_site_sp)262 return bp_site_sp->GetNumberOfConstituents() * 2;263 return 0; // Breakpoint must have cleared itself...264 }265 266 uint64_t GetStopReasonDataAtIndex(uint32_t idx) override {267 uint32_t bp_index = idx / 2;268 BreakpointLocationSP loc_to_report_sp;269 270 size_t num_async_locs = m_async_stopped_locs.GetSize();271 if (num_async_locs > 0) {272 // GetByIndex returns an empty SP if we ask past its contents:273 loc_to_report_sp = m_async_stopped_locs.GetByIndex(bp_index);274 } else {275 lldb::BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();276 if (bp_site_sp)277 loc_to_report_sp = bp_site_sp->GetConstituentAtIndex(bp_index);278 }279 if (loc_to_report_sp) {280 if (idx & 1) {281 // Odd idx, return the breakpoint location ID282 return loc_to_report_sp->GetID();283 } else {284 // Even idx, return the breakpoint ID285 return loc_to_report_sp->GetBreakpoint().GetID();286 }287 }288 return LLDB_INVALID_BREAK_ID;289 }290 291 std::optional<uint32_t>292 GetSuggestedStackFrameIndex(bool inlined_stack) override {293 if (!inlined_stack)294 return {};295 296 ThreadSP thread_sp(m_thread_wp.lock());297 if (!thread_sp)298 return {};299 BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();300 if (!bp_site_sp)301 return {};302 303 return bp_site_sp->GetSuggestedStackFrameIndex();304 }305 306 bool ShouldShow() const override { return !m_was_all_internal; }307 308 bool ShouldSelect() const override { return !m_was_all_internal; }309 310protected:311 bool ShouldStop(Event *event_ptr) override {312 // This just reports the work done by PerformAction or the synchronous313 // stop. It should only ever get called after they have had a chance to314 // run.315 assert(m_should_stop_is_valid);316 return m_should_stop;317 }318 319 void PerformAction(Event *event_ptr) override {320 if (!m_should_perform_action)321 return;322 m_should_perform_action = false;323 bool all_stopping_locs_internal = true;324 325 ThreadSP thread_sp(m_thread_wp.lock());326 327 if (thread_sp) {328 Log *log = GetLog(LLDBLog::Breakpoints | LLDBLog::Step);329 330 if (!thread_sp->IsValid()) {331 // This shouldn't ever happen, but just in case, don't do more harm.332 if (log) {333 LLDB_LOGF(log, "PerformAction got called with an invalid thread.");334 }335 m_should_stop = true;336 m_should_stop_is_valid = true;337 return;338 }339 340 BreakpointSiteSP bp_site_sp = GetBreakpointSiteSP();341 std::unordered_set<break_id_t> precondition_breakpoints;342 // Breakpoints that fail their condition check are not considered to343 // have been hit. If the only locations at this site have failed their344 // conditions, we should change the stop-info to none. Otherwise, if we345 // hit another breakpoint on a different thread which does stop, users346 // will see a breakpont hit with a failed condition, which is wrong.347 // Use this variable to tell us if that is true.348 bool actually_hit_any_locations = false;349 if (bp_site_sp) {350 // Let's copy the constituents list out of the site and store them in a351 // local list. That way if one of the breakpoint actions changes the352 // site, then we won't be operating on a bad list.353 BreakpointLocationCollection site_locations;354 size_t num_constituents = m_async_stopped_locs.GetSize();355 356 if (num_constituents == 0) {357 m_should_stop = true;358 actually_hit_any_locations = true; // We're going to stop, don't 359 // change the stop info.360 } else {361 // We go through each location, and test first its precondition -362 // this overrides everything. Note, we only do this once per363 // breakpoint - not once per location... Then check the condition.364 // If the condition says to stop, then we run the callback for that365 // location. If that callback says to stop as well, then we set366 // m_should_stop to true; we are going to stop. But we still want to367 // give all the breakpoints whose conditions say we are going to stop368 // a chance to run their callbacks. Of course if any callback369 // restarts the target by putting "continue" in the callback, then370 // we're going to restart, without running the rest of the callbacks.371 // And in this case we will end up not stopping even if another372 // location said we should stop. But that's better than not running373 // all the callbacks.374 375 // There's one other complication here. We may have run an async376 // breakpoint callback that said we should stop. We only want to377 // override that if another breakpoint action says we shouldn't378 // stop. If nobody else has an opinion, then we should stop if the379 // async callback says we should. An example of this is the async380 // shared library load notification breakpoint and the setting381 // stop-on-sharedlibrary-events.382 // We'll keep the async value in async_should_stop, and track whether383 // anyone said we should NOT stop in actually_said_continue.384 bool async_should_stop = false;385 if (m_should_stop_is_valid)386 async_should_stop = m_should_stop;387 bool actually_said_continue = false;388 389 m_should_stop = false;390 391 // We don't select threads as we go through them testing breakpoint392 // conditions and running commands. So we need to set the thread for393 // expression evaluation here:394 ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);395 396 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));397 Process *process = exe_ctx.GetProcessPtr();398 if (process->GetModIDRef().IsRunningExpression()) {399 // If we are in the middle of evaluating an expression, don't run400 // asynchronous breakpoint commands or expressions. That could401 // lead to infinite recursion if the command or condition re-calls402 // the function with this breakpoint.403 // TODO: We can keep a list of the breakpoints we've seen while404 // running expressions in the nested405 // PerformAction calls that can arise when the action runs a406 // function that hits another breakpoint, and only stop running407 // commands when we see the same breakpoint hit a second time.408 409 m_should_stop_is_valid = true;410 411 // It is possible that the user has a breakpoint at the same site412 // as the completed plan had (e.g. user has a breakpoint413 // on a module entry point, and `ThreadPlanCallFunction` ends414 // also there). We can't find an internal breakpoint in the loop415 // later because it was already removed on the plan completion.416 // So check if the plan was completed, and stop if so.417 if (thread_sp->CompletedPlanOverridesBreakpoint()) {418 m_should_stop = true;419 thread_sp->ResetStopInfo();420 return;421 }422 423 LLDB_LOGF(log, "StopInfoBreakpoint::PerformAction - Hit a "424 "breakpoint while running an expression,"425 " not running commands to avoid recursion.");426 bool ignoring_breakpoints =427 process->GetIgnoreBreakpointsInExpressions();428 // Internal breakpoints should be allowed to do their job, we429 // can make sure they don't do anything that would cause recursive430 // command execution:431 if (!m_was_all_internal) {432 m_should_stop = !ignoring_breakpoints;433 LLDB_LOGF(log,434 "StopInfoBreakpoint::PerformAction - in expression, "435 "continuing: %s.",436 m_should_stop ? "true" : "false");437 Debugger::ReportWarning(438 "hit breakpoint while running function, skipping commands "439 "and conditions to prevent recursion",440 process->GetTarget().GetDebugger().GetID());441 return;442 }443 }444 445 StoppointCallbackContext context(event_ptr, exe_ctx, false);446 447 // For safety's sake let's also grab an extra reference to the448 // breakpoint constituents of the locations we're going to examine,449 // since the locations are going to have to get back to their450 // breakpoints, and the locations don't keep their constituents alive.451 // I'm just sticking the BreakpointSP's in a vector since I'm only452 // using it to locally increment their retain counts.453 454 // We are holding onto the breakpoint locations that were hit455 // by this stop info between the "synchonous" ShouldStop and now.456 // But an intervening action might have deleted one of the breakpoints457 // we hit before we get here. So at the same time let's build a list458 // of the still valid locations:459 std::vector<lldb::BreakpointSP> location_constituents;460 461 BreakpointLocationCollection valid_locs;462 for (size_t j = 0; j < num_constituents; j++) {463 BreakpointLocationSP loc_sp(m_async_stopped_locs.GetByIndex(j));464 if (loc_sp->IsValid()) {465 location_constituents.push_back(466 loc_sp->GetBreakpoint().shared_from_this());467 valid_locs.Add(loc_sp);468 }469 }470 471 size_t num_valid_locs = valid_locs.GetSize();472 for (size_t j = 0; j < num_valid_locs; j++) {473 lldb::BreakpointLocationSP bp_loc_sp = valid_locs.GetByIndex(j);474 StreamString loc_desc;475 if (log) {476 bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief);477 }478 // If another action disabled this breakpoint or its location, then479 // don't run the actions.480 if (!bp_loc_sp->IsEnabled() ||481 !bp_loc_sp->GetBreakpoint().IsEnabled())482 continue;483 484 // The breakpoint site may have many locations associated with it,485 // not all of them valid for this thread. Skip the ones that486 // aren't:487 if (!bp_loc_sp->ValidForThisThread(*thread_sp)) {488 if (log) {489 LLDB_LOGF(log,490 "Breakpoint %s hit on thread 0x%llx but it was not "491 "for this thread, continuing.",492 loc_desc.GetData(),493 static_cast<unsigned long long>(thread_sp->GetID()));494 }495 continue;496 }497 498 // First run the precondition, but since the precondition is per499 // breakpoint, only run it once per breakpoint.500 std::pair<std::unordered_set<break_id_t>::iterator, bool> result =501 precondition_breakpoints.insert(502 bp_loc_sp->GetBreakpoint().GetID());503 if (!result.second)504 continue;505 506 bool precondition_result =507 bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);508 if (!precondition_result) {509 actually_said_continue = true;510 continue;511 }512 // Next run the condition for the breakpoint. If that says we513 // should stop, then we'll run the callback for the breakpoint. If514 // the callback says we shouldn't stop that will win.515 516 if (!bp_loc_sp->GetCondition())517 actually_hit_any_locations = true;518 else {519 Status condition_error;520 bool condition_says_stop =521 bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);522 523 if (!condition_error.Success()) {524 // If the condition fails to evaluate, we are going to stop 525 // at it, so the location was hit.526 actually_hit_any_locations = true;527 const char *err_str =528 condition_error.AsCString("<unknown error>");529 LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);530 531 StreamString strm;532 strm << "stopped due to an error evaluating condition of "533 "breakpoint ";534 bp_loc_sp->GetDescription(&strm, eDescriptionLevelBrief);535 strm << ": \"" << bp_loc_sp->GetCondition().GetText() << "\"\n";536 strm << err_str;537 538 Debugger::ReportError(539 strm.GetString().str(),540 exe_ctx.GetTargetRef().GetDebugger().GetID());541 } else {542 LLDB_LOGF(log,543 "Condition evaluated for breakpoint %s on thread "544 "0x%llx condition_says_stop: %i.",545 loc_desc.GetData(),546 static_cast<unsigned long long>(thread_sp->GetID()),547 condition_says_stop);548 if (condition_says_stop) 549 actually_hit_any_locations = true;550 else {551 // We don't want to increment the hit count of breakpoints if552 // the condition fails. We've already bumped it by the time553 // we get here, so undo the bump:554 bp_loc_sp->UndoBumpHitCount();555 actually_said_continue = true;556 continue;557 }558 }559 }560 561 // We've done all the checks whose failure means "we consider lldb562 // not to have hit the breakpoint". Now we're going to check for563 // conditions that might continue after hitting. Start with the564 // ignore count:565 if (!bp_loc_sp->IgnoreCountShouldStop()) {566 actually_said_continue = true;567 continue;568 }569 570 // Check the auto-continue bit on the location, do this before the571 // callback since it may change this, but that would be for the572 // NEXT hit. Note, you might think you could check auto-continue573 // before the condition, and not evaluate the condition if it says574 // to continue. But failing the condition means the breakpoint was575 // effectively NOT HIT. So these two states are different.576 bool auto_continue_says_stop = true;577 if (bp_loc_sp->IsAutoContinue())578 {579 LLDB_LOGF(log,580 "Continuing breakpoint %s as AutoContinue was set.",581 loc_desc.GetData());582 // We want this stop reported, so you will know we auto-continued583 // but only for external breakpoints:584 if (!bp_loc_sp->GetBreakpoint().IsInternal())585 thread_sp->SetShouldReportStop(eVoteYes);586 auto_continue_says_stop = false;587 }588 589 bool callback_says_stop = true;590 591 // FIXME: For now the callbacks have to run in async mode - the592 // first time we restart we need593 // to get out of there. So set it here.594 // When we figure out how to nest breakpoint hits then this will595 // change.596 597 // Don't run async callbacks in PerformAction. They have already598 // been taken into account with async_should_stop.599 if (!bp_loc_sp->IsCallbackSynchronous()) {600 Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();601 bool old_async = debugger.GetAsyncExecution();602 debugger.SetAsyncExecution(true);603 604 callback_says_stop = bp_loc_sp->InvokeCallback(&context);605 606 debugger.SetAsyncExecution(old_async);607 608 if (callback_says_stop && auto_continue_says_stop)609 m_should_stop = true;610 else611 actually_said_continue = true;612 }613 614 if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())615 all_stopping_locs_internal = false;616 617 // If we are going to stop for this breakpoint, then remove the618 // breakpoint.619 if (callback_says_stop && bp_loc_sp &&620 bp_loc_sp->GetBreakpoint().IsOneShot()) {621 thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(622 bp_loc_sp->GetBreakpoint().GetID());623 }624 // Also make sure that the callback hasn't continued the target. If625 // it did, when we'll set m_should_start to false and get out of626 // here.627 if (HasTargetRunSinceMe()) {628 m_should_stop = false;629 actually_said_continue = true;630 break;631 }632 }633 // At this point if nobody actually told us to continue, we should634 // give the async breakpoint callback a chance to weigh in:635 if (!actually_said_continue && !m_should_stop) {636 m_should_stop = async_should_stop;637 }638 }639 // We've figured out what this stop wants to do, so mark it as valid so640 // we don't compute it again.641 m_should_stop_is_valid = true;642 } else {643 m_should_stop = true;644 m_should_stop_is_valid = true;645 actually_hit_any_locations = true;646 Log *log_process(GetLog(LLDBLog::Process));647 648 LLDB_LOGF(log_process,649 "Process::%s could not find breakpoint site id: %" PRId64650 "...",651 __FUNCTION__, m_value);652 }653 654 if ((!m_should_stop || all_stopping_locs_internal) &&655 thread_sp->CompletedPlanOverridesBreakpoint()) {656 657 // Override should_stop decision when we have completed step plan658 // additionally to the breakpoint659 m_should_stop = true;660 661 // We know we're stopping for a completed plan and we don't want to662 // show the breakpoint stop, so compute the public stop info immediately663 // here.664 thread_sp->CalculatePublicStopInfo();665 } else if (!actually_hit_any_locations) {666 // In the end, we didn't actually have any locations that passed their667 // "was I hit" checks. So say we aren't stopped.668 GetThread()->ResetStopInfo();669 LLDB_LOGF(log, "Process::%s all locations failed condition checks.",670 __FUNCTION__);671 }672 673 LLDB_LOGF(log,674 "Process::%s returning from action with m_should_stop: %d.",675 __FUNCTION__, m_should_stop);676 }677 }678 679private:680 BreakpointSiteSP GetBreakpointSiteSP() const {681 if (m_value == LLDB_INVALID_BREAK_ID)682 return {};683 684 ThreadSP thread_sp = GetThread();685 if (!thread_sp)686 return {};687 ProcessSP process_sp = thread_sp->GetProcess();688 if (!process_sp)689 return {};690 691 return process_sp->GetBreakpointSiteList().FindByID(m_value);692 }693 694 bool m_should_stop;695 bool m_should_stop_is_valid;696 bool m_should_perform_action; // Since we are trying to preserve the "state"697 // of the system even if we run functions698 // etc. behind the users backs, we need to make sure we only REALLY perform699 // the action once.700 lldb::addr_t m_address; // We use this to capture the breakpoint site address701 // when we create the StopInfo,702 // in case somebody deletes it between the time the StopInfo is made and the703 // description is asked for.704 lldb::break_id_t m_break_id;705 bool m_was_all_internal;706 bool m_was_one_shot;707 /// The StopInfoBreakpoint lives after the stop, and could get queried708 /// at any time so we need to make sure that it keeps the breakpoints for709 /// each of the locations it records alive while it is around. That's what710 /// The BreakpointPreservingLocationCollection does.711 BreakpointLocationCollection m_async_stopped_locs;712};713 714// StopInfoWatchpoint715 716class StopInfoWatchpoint : public StopInfo {717public:718 // Make sure watchpoint is properly disabled and subsequently enabled while719 // performing watchpoint actions.720 class WatchpointSentry {721 public:722 WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),723 watchpoint_sp(w_sp) {724 if (process_sp && watchpoint_sp) {725 const bool notify = false;726 watchpoint_sp->TurnOnEphemeralMode();727 process_sp->DisableWatchpoint(watchpoint_sp, notify);728 process_sp->AddPreResumeAction(SentryPreResumeAction, this);729 }730 }731 732 void DoReenable() {733 if (process_sp && watchpoint_sp) {734 bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();735 watchpoint_sp->TurnOffEphemeralMode();736 const bool notify = false;737 if (was_disabled) {738 process_sp->DisableWatchpoint(watchpoint_sp, notify);739 } else {740 process_sp->EnableWatchpoint(watchpoint_sp, notify);741 }742 }743 }744 745 ~WatchpointSentry() {746 DoReenable();747 if (process_sp)748 process_sp->ClearPreResumeAction(SentryPreResumeAction, this);749 }750 751 static bool SentryPreResumeAction(void *sentry_void) {752 WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;753 sentry->DoReenable();754 return true;755 }756 757 private:758 ProcessSP process_sp;759 WatchpointSP watchpoint_sp;760 };761 762 StopInfoWatchpoint(Thread &thread, break_id_t watch_id, bool silently_skip_wp)763 : StopInfo(thread, watch_id), m_silently_skip_wp(silently_skip_wp) {}764 765 ~StopInfoWatchpoint() override = default;766 767 StopReason GetStopReason() const override { return eStopReasonWatchpoint; }768 769 uint32_t GetStopReasonDataCount() const override { return 1; }770 uint64_t GetStopReasonDataAtIndex(uint32_t idx) override {771 if (idx == 0)772 return GetValue();773 return 0;774 }775 776 const char *GetDescription() override {777 if (m_description.empty()) {778 StreamString strm;779 strm.Printf("watchpoint %" PRIi64, m_value);780 m_description = std::string(strm.GetString());781 }782 return m_description.c_str();783 }784 785protected:786 using StopInfoWatchpointSP = std::shared_ptr<StopInfoWatchpoint>;787 // This plan is used to orchestrate stepping over the watchpoint for788 // architectures (e.g. ARM) that report the watch before running the watched789 // access. This is the sort of job you have to defer to the thread plans,790 // if you try to do it directly in the stop info and there are other threads791 // that needed to process this stop you will have yanked control away from792 // them and they won't behave correctly.793 class ThreadPlanStepOverWatchpoint : public ThreadPlanStepInstruction {794 public:795 ThreadPlanStepOverWatchpoint(Thread &thread, 796 StopInfoWatchpointSP stop_info_sp,797 WatchpointSP watch_sp)798 : ThreadPlanStepInstruction(thread, false, true, eVoteNoOpinion,799 eVoteNoOpinion),800 m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) {801 assert(watch_sp);802 }803 804 bool DoWillResume(lldb::StateType resume_state,805 bool current_plan) override {806 if (resume_state == eStateSuspended)807 return true;808 809 if (!m_did_disable_wp) {810 GetThread().GetProcess()->DisableWatchpoint(m_watch_sp, false);811 m_did_disable_wp = true;812 }813 return true;814 }815 816 bool DoPlanExplainsStop(Event *event_ptr) override {817 if (ThreadPlanStepInstruction::DoPlanExplainsStop(event_ptr))818 return true;819 StopInfoSP stop_info_sp = GetThread().GetPrivateStopInfo();820 // lldb-server resets the stop info for threads that didn't get to run,821 // so we might have not gotten to run, but still have a watchpoint stop822 // reason, in which case this will indeed be for us.823 if (stop_info_sp 824 && stop_info_sp->GetStopReason() == eStopReasonWatchpoint)825 return true;826 return false;827 }828 829 void DidPop() override {830 // Don't artifically keep the watchpoint alive.831 m_watch_sp.reset();832 }833 834 bool ShouldStop(Event *event_ptr) override {835 bool should_stop = ThreadPlanStepInstruction::ShouldStop(event_ptr);836 bool plan_done = MischiefManaged();837 if (plan_done) {838 m_stop_info_sp->SetStepOverPlanComplete();839 GetThread().SetStopInfo(m_stop_info_sp);840 ResetWatchpoint();841 }842 return should_stop;843 }844 845 bool ShouldRunBeforePublicStop() override {846 return true;847 }848 849 protected:850 void ResetWatchpoint() {851 if (!m_did_disable_wp)852 return;853 m_did_disable_wp = true;854 GetThread().GetProcess()->EnableWatchpoint(m_watch_sp, true);855 }856 857 private:858 StopInfoWatchpointSP m_stop_info_sp;859 WatchpointSP m_watch_sp;860 bool m_did_disable_wp = false;861 };862 863 bool ShouldStopSynchronous(Event *event_ptr) override {864 // If we are running our step-over the watchpoint plan, stop if it's done865 // and continue if it's not:866 if (m_should_stop_is_valid)867 return m_should_stop;868 869 // If we are running our step over plan, then stop here and let the regular870 // ShouldStop figure out what we should do: Otherwise, give our plan871 // more time to get run:872 if (m_using_step_over_plan)873 return m_step_over_plan_complete;874 875 Log *log = GetLog(LLDBLog::Process);876 ThreadSP thread_sp(m_thread_wp.lock());877 assert(thread_sp);878 879 if (thread_sp->GetTemporaryResumeState() == eStateSuspended) {880 // This is the second firing of a watchpoint so don't process it again.881 LLDB_LOG(log, "We didn't run but stopped with a StopInfoWatchpoint, we "882 "have already handled this one, don't do it again.");883 m_should_stop = false;884 m_should_stop_is_valid = true;885 return m_should_stop;886 }887 888 WatchpointSP wp_sp(889 thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue()));890 // If we can no longer find the watchpoint, we just have to stop:891 if (!wp_sp) {892 893 LLDB_LOGF(log,894 "Process::%s could not find watchpoint location id: %" PRId64895 "...",896 __FUNCTION__, GetValue());897 898 m_should_stop = true;899 m_should_stop_is_valid = true;900 return true;901 }902 903 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));904 StoppointCallbackContext context(event_ptr, exe_ctx, true);905 m_should_stop = wp_sp->ShouldStop(&context);906 if (!m_should_stop) {907 // This won't happen at present because we only allow one watchpoint per908 // watched range. So we won't stop at a watched address with a disabled909 // watchpoint. If we start allowing overlapping watchpoints, then we910 // will have to make watchpoints be real "WatchpointSite" and delegate to911 // all the watchpoints sharing the site. In that case, the code below912 // would be the right thing to do.913 m_should_stop_is_valid = true;914 return m_should_stop;915 }916 // If this is a system where we need to execute the watchpoint by hand917 // after the hit, queue a thread plan to do that, and then say not to stop.918 // Otherwise, let the async action figure out whether the watchpoint should919 // stop920 921 ProcessSP process_sp = exe_ctx.GetProcessSP();922 bool wp_triggers_after = process_sp->GetWatchpointReportedAfter();923 924 if (!wp_triggers_after) {925 // We have to step over the watchpoint before we know what to do: 926 StopInfoWatchpointSP me_as_siwp_sp 927 = std::static_pointer_cast<StopInfoWatchpoint>(shared_from_this());928 ThreadPlanSP step_over_wp_sp =929 std::make_shared<ThreadPlanStepOverWatchpoint>(*(thread_sp.get()),930 me_as_siwp_sp, wp_sp);931 // When this plan is done we want to stop, so set this as a Controlling932 // plan. 933 step_over_wp_sp->SetIsControllingPlan(true);934 step_over_wp_sp->SetOkayToDiscard(false);935 936 Status error;937 error = thread_sp->QueueThreadPlan(step_over_wp_sp, false);938 // If we couldn't push the thread plan, just stop here:939 if (!error.Success()) {940 LLDB_LOGF(log, "Could not push our step over watchpoint plan: %s", 941 error.AsCString());942 943 m_should_stop = true;944 m_should_stop_is_valid = true;945 return true;946 } else {947 // Otherwise, don't set m_should_stop, we don't know that yet. Just 948 // say we should continue, and tell the thread we really should do so:949 thread_sp->SetShouldRunBeforePublicStop(true);950 m_using_step_over_plan = true;951 return false;952 }953 } else {954 // We didn't have to do anything special955 m_should_stop_is_valid = true;956 return m_should_stop;957 }958 959 return m_should_stop;960 }961 962 bool ShouldStop(Event *event_ptr) override {963 // This just reports the work done by PerformAction or the synchronous964 // stop. It should only ever get called after they have had a chance to965 // run.966 assert(m_should_stop_is_valid);967 return m_should_stop;968 }969 970 void PerformAction(Event *event_ptr) override {971 Log *log = GetLog(LLDBLog::Watchpoints);972 // We're going to calculate if we should stop or not in some way during the973 // course of this code. Also by default we're going to stop, so set that974 // here.975 m_should_stop = true;976 977 978 ThreadSP thread_sp(m_thread_wp.lock());979 if (thread_sp) {980 981 WatchpointSP wp_sp(982 thread_sp->CalculateTarget()->GetWatchpointList().FindByID(983 GetValue()));984 if (wp_sp) {985 // This sentry object makes sure the current watchpoint is disabled986 // while performing watchpoint actions, and it is then enabled after we987 // are finished.988 ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));989 ProcessSP process_sp = exe_ctx.GetProcessSP();990 991 WatchpointSentry sentry(process_sp, wp_sp);992 993 if (m_silently_skip_wp) {994 m_should_stop = false;995 wp_sp->UndoHitCount();996 }997 998 if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) {999 m_should_stop = false;1000 m_should_stop_is_valid = true;1001 }1002 1003 Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();1004 1005 if (m_should_stop && wp_sp->GetConditionText() != nullptr) {1006 // We need to make sure the user sees any parse errors in their1007 // condition, so we'll hook the constructor errors up to the1008 // debugger's Async I/O.1009 ExpressionResults result_code;1010 EvaluateExpressionOptions expr_options;1011 expr_options.SetUnwindOnError(true);1012 expr_options.SetIgnoreBreakpoints(true);1013 ValueObjectSP result_value_sp;1014 result_code = UserExpression::Evaluate(1015 exe_ctx, expr_options, wp_sp->GetConditionText(),1016 llvm::StringRef(), result_value_sp);1017 1018 if (result_code == eExpressionCompleted) {1019 if (result_value_sp) {1020 Scalar scalar_value;1021 if (result_value_sp->ResolveValue(scalar_value)) {1022 if (scalar_value.ULongLong(1) == 0) {1023 // The condition failed, which we consider "not having hit1024 // the watchpoint" so undo the hit count here.1025 wp_sp->UndoHitCount();1026 m_should_stop = false;1027 } else1028 m_should_stop = true;1029 LLDB_LOGF(log,1030 "Condition successfully evaluated, result is %s.\n",1031 m_should_stop ? "true" : "false");1032 } else {1033 m_should_stop = true;1034 LLDB_LOGF(1035 log,1036 "Failed to get an integer result from the expression.");1037 }1038 }1039 } else {1040 const char *err_str = "<unknown error>";1041 if (result_value_sp)1042 err_str = result_value_sp->GetError().AsCString();1043 1044 LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);1045 1046 StreamString strm;1047 strm << "stopped due to an error evaluating condition of "1048 "watchpoint ";1049 wp_sp->GetDescription(&strm, eDescriptionLevelBrief);1050 strm << ": \"" << wp_sp->GetConditionText() << "\"\n";1051 strm << err_str;1052 1053 Debugger::ReportError(strm.GetString().str(),1054 exe_ctx.GetTargetRef().GetDebugger().GetID());1055 }1056 }1057 1058 // If the condition says to stop, we run the callback to further decide1059 // whether to stop.1060 if (m_should_stop) {1061 // FIXME: For now the callbacks have to run in async mode - the1062 // first time we restart we need1063 // to get out of there. So set it here.1064 // When we figure out how to nest watchpoint hits then this will1065 // change.1066 1067 bool old_async = debugger.GetAsyncExecution();1068 debugger.SetAsyncExecution(true);1069 1070 StoppointCallbackContext context(event_ptr, exe_ctx, false);1071 bool stop_requested = wp_sp->InvokeCallback(&context);1072 1073 debugger.SetAsyncExecution(old_async);1074 1075 // Also make sure that the callback hasn't continued the target. If1076 // it did, when we'll set m_should_stop to false and get out of here.1077 if (HasTargetRunSinceMe())1078 m_should_stop = false;1079 1080 if (m_should_stop && !stop_requested) {1081 // We have been vetoed by the callback mechanism.1082 m_should_stop = false;1083 }1084 }1085 1086 // Don't stop if the watched region value is unmodified, and1087 // this is a Modify-type watchpoint.1088 if (m_should_stop && !wp_sp->WatchedValueReportable(exe_ctx)) {1089 wp_sp->UndoHitCount();1090 m_should_stop = false;1091 }1092 1093 // Finally, if we are going to stop, print out the new & old values:1094 if (m_should_stop) {1095 wp_sp->CaptureWatchedValue(exe_ctx);1096 1097 Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();1098 StreamUP output_up = debugger.GetAsyncOutputStream();1099 if (wp_sp->DumpSnapshots(output_up.get()))1100 output_up->EOL();1101 }1102 1103 } else {1104 Log *log_process(GetLog(LLDBLog::Process));1105 1106 LLDB_LOGF(log_process,1107 "Process::%s could not find watchpoint id: %" PRId64 "...",1108 __FUNCTION__, m_value);1109 }1110 LLDB_LOGF(log,1111 "Process::%s returning from action with m_should_stop: %d.",1112 __FUNCTION__, m_should_stop);1113 1114 m_should_stop_is_valid = true;1115 }1116 }1117 1118private:1119 void SetStepOverPlanComplete() {1120 assert(m_using_step_over_plan);1121 m_step_over_plan_complete = true;1122 }1123 1124 bool m_should_stop = false;1125 bool m_should_stop_is_valid = false;1126 // A false watchpoint hit has happened -1127 // the thread stopped with a watchpoint1128 // hit notification, but the watched region1129 // was not actually accessed (as determined1130 // by the gdb stub we're talking to).1131 // Continue past this watchpoint without1132 // notifying the user; on some targets this1133 // may mean disable wp, instruction step,1134 // re-enable wp, continue.1135 // On others, just continue.1136 bool m_silently_skip_wp = false;1137 bool m_step_over_plan_complete = false;1138 bool m_using_step_over_plan = false;1139};1140 1141// StopInfoUnixSignal1142 1143class StopInfoUnixSignal : public StopInfo {1144public:1145 StopInfoUnixSignal(Thread &thread, int signo, const char *description,1146 std::optional<int> code)1147 : StopInfo(thread, signo), m_code(code) {1148 SetDescription(description);1149 }1150 1151 ~StopInfoUnixSignal() override = default;1152 1153 StopReason GetStopReason() const override { return eStopReasonSignal; }1154 1155 bool ShouldStopSynchronous(Event *event_ptr) override {1156 ThreadSP thread_sp(m_thread_wp.lock());1157 if (thread_sp)1158 return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);1159 return false;1160 }1161 1162 bool ShouldStop(Event *event_ptr) override { return IsShouldStopSignal(); }1163 1164 // If should stop returns false, check if we should notify of this event1165 bool DoShouldNotify(Event *event_ptr) override {1166 ThreadSP thread_sp(m_thread_wp.lock());1167 if (thread_sp) {1168 bool should_notify =1169 thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value);1170 if (should_notify) {1171 StreamString strm;1172 strm.Format(1173 "thread {0:d} received signal: {1}", thread_sp->GetIndexID(),1174 thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsStringRef(1175 m_value));1176 Process::ProcessEventData::AddRestartedReason(event_ptr,1177 strm.GetData());1178 }1179 return should_notify;1180 }1181 return true;1182 }1183 1184 void WillResume(lldb::StateType resume_state) override {1185 ThreadSP thread_sp(m_thread_wp.lock());1186 if (thread_sp) {1187 if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(1188 m_value))1189 thread_sp->SetResumeSignal(m_value);1190 }1191 }1192 1193 const char *GetDescription() override {1194 if (m_description.empty()) {1195 ThreadSP thread_sp(m_thread_wp.lock());1196 if (thread_sp) {1197 UnixSignalsSP unix_signals = thread_sp->GetProcess()->GetUnixSignals();1198 StreamString strm;1199 strm << "signal ";1200 1201 std::string signal_name =1202 unix_signals->GetSignalDescription(m_value, m_code);1203 if (signal_name.size())1204 strm << signal_name;1205 else1206 strm.Printf("%" PRIi64, m_value);1207 1208 m_description = std::string(strm.GetString());1209 }1210 }1211 return m_description.c_str();1212 }1213 1214 bool ShouldSelect() const override { return IsShouldStopSignal(); }1215 1216 uint32_t GetStopReasonDataCount() const override { return 1; }1217 uint64_t GetStopReasonDataAtIndex(uint32_t idx) override {1218 if (idx == 0)1219 return GetValue();1220 return 0;1221 }1222 1223private:1224 // In siginfo_t terms, if m_value is si_signo, m_code is si_code.1225 std::optional<int> m_code;1226 1227 bool IsShouldStopSignal() const {1228 if (ThreadSP thread_sp = m_thread_wp.lock())1229 return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);1230 return false;1231 }1232};1233 1234// StopInfoInterrupt1235 1236class StopInfoInterrupt : public StopInfo {1237public:1238 StopInfoInterrupt(Thread &thread, int signo, const char *description)1239 : StopInfo(thread, signo) {1240 SetDescription(description);1241 }1242 1243 ~StopInfoInterrupt() override = default;1244 1245 StopReason GetStopReason() const override {1246 return lldb::eStopReasonInterrupt;1247 }1248 1249 const char *GetDescription() override {1250 if (m_description.empty()) {1251 m_description = "async interrupt";1252 }1253 return m_description.c_str();1254 }1255 1256 uint32_t GetStopReasonDataCount() const override { return 1; }1257 uint64_t GetStopReasonDataAtIndex(uint32_t idx) override {1258 if (idx == 0)1259 return GetValue();1260 else1261 return 0;1262 }1263};1264 1265// StopInfoTrace1266 1267class StopInfoTrace : public StopInfo {1268public:1269 StopInfoTrace(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}1270 1271 ~StopInfoTrace() override = default;1272 1273 StopReason GetStopReason() const override { return eStopReasonTrace; }1274 1275 const char *GetDescription() override {1276 if (m_description.empty())1277 return "trace";1278 else1279 return m_description.c_str();1280 }1281 1282 std::optional<uint32_t>1283 GetSuggestedStackFrameIndex(bool inlined_stack) override {1284 // Trace only knows how to adjust inlined stacks:1285 if (!inlined_stack)1286 return {};1287 1288 ThreadSP thread_sp = GetThread();1289 StackFrameSP frame_0_sp = thread_sp->GetStackFrameAtIndex(0);1290 if (!frame_0_sp)1291 return {};1292 if (!frame_0_sp->IsInlined())1293 return {};1294 Block *block_ptr = frame_0_sp->GetFrameBlock();1295 if (!block_ptr)1296 return {};1297 Address pc_address = frame_0_sp->GetFrameCodeAddress();1298 AddressRange containing_range;1299 if (!block_ptr->GetRangeContainingAddress(pc_address, containing_range) ||1300 pc_address != containing_range.GetBaseAddress())1301 return {};1302 1303 int num_inlined_functions = 0;1304 1305 for (Block *container_ptr = block_ptr->GetInlinedParent();1306 container_ptr != nullptr;1307 container_ptr = container_ptr->GetInlinedParent()) {1308 if (!container_ptr->GetRangeContainingAddress(pc_address,1309 containing_range))1310 break;1311 if (pc_address != containing_range.GetBaseAddress())1312 break;1313 1314 num_inlined_functions++;1315 }1316 inlined_stack = true;1317 return num_inlined_functions + 1;1318 }1319};1320 1321// StopInfoException1322 1323class StopInfoException : public StopInfo {1324public:1325 StopInfoException(Thread &thread, const char *description)1326 : StopInfo(thread, LLDB_INVALID_UID) {1327 if (description)1328 SetDescription(description);1329 }1330 1331 ~StopInfoException() override = default;1332 1333 StopReason GetStopReason() const override { return eStopReasonException; }1334 1335 const char *GetDescription() override {1336 if (m_description.empty())1337 return "exception";1338 else1339 return m_description.c_str();1340 }1341 uint32_t GetStopReasonDataCount() const override { return 1; }1342 uint64_t GetStopReasonDataAtIndex(uint32_t idx) override {1343 if (idx == 0)1344 return GetValue();1345 else1346 return 0;1347 }1348};1349 1350// StopInfoProcessorTrace1351 1352class StopInfoProcessorTrace : public StopInfo {1353public:1354 StopInfoProcessorTrace(Thread &thread, const char *description)1355 : StopInfo(thread, LLDB_INVALID_UID) {1356 if (description)1357 SetDescription(description);1358 }1359 1360 ~StopInfoProcessorTrace() override = default;1361 1362 StopReason GetStopReason() const override {1363 return eStopReasonProcessorTrace;1364 }1365 1366 const char *GetDescription() override {1367 if (m_description.empty())1368 return "processor trace event";1369 else1370 return m_description.c_str();1371 }1372};1373 1374// StopInfoHistoryBoundary1375 1376class StopInfoHistoryBoundary : public StopInfo {1377public:1378 StopInfoHistoryBoundary(Thread &thread, const char *description)1379 : StopInfo(thread, LLDB_INVALID_UID) {1380 if (description)1381 SetDescription(description);1382 }1383 1384 ~StopInfoHistoryBoundary() override = default;1385 1386 StopReason GetStopReason() const override {1387 return eStopReasonHistoryBoundary;1388 }1389 1390 const char *GetDescription() override {1391 if (m_description.empty())1392 return "history boundary";1393 return m_description.c_str();1394 }1395};1396 1397// StopInfoThreadPlan1398 1399class StopInfoThreadPlan : public StopInfo {1400public:1401 StopInfoThreadPlan(ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp,1402 ExpressionVariableSP &expression_variable_sp)1403 : StopInfo(plan_sp->GetThread(), LLDB_INVALID_UID), m_plan_sp(plan_sp),1404 m_return_valobj_sp(return_valobj_sp),1405 m_expression_variable_sp(expression_variable_sp) {}1406 1407 ~StopInfoThreadPlan() override = default;1408 1409 StopReason GetStopReason() const override { return eStopReasonPlanComplete; }1410 1411 const char *GetDescription() override {1412 if (m_description.empty()) {1413 StreamString strm;1414 m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief);1415 m_description = std::string(strm.GetString());1416 }1417 return m_description.c_str();1418 }1419 1420 ValueObjectSP GetReturnValueObject() { return m_return_valobj_sp; }1421 1422 ExpressionVariableSP GetExpressionVariable() {1423 return m_expression_variable_sp;1424 }1425 1426protected:1427 bool ShouldStop(Event *event_ptr) override {1428 if (m_plan_sp)1429 return m_plan_sp->ShouldStop(event_ptr);1430 else1431 return StopInfo::ShouldStop(event_ptr);1432 }1433 1434private:1435 ThreadPlanSP m_plan_sp;1436 ValueObjectSP m_return_valobj_sp;1437 ExpressionVariableSP m_expression_variable_sp;1438};1439 1440// StopInfoExec1441 1442class StopInfoExec : public StopInfo {1443public:1444 StopInfoExec(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}1445 1446 ~StopInfoExec() override = default;1447 1448 bool ShouldStop(Event *event_ptr) override {1449 ThreadSP thread_sp(m_thread_wp.lock());1450 if (thread_sp)1451 return thread_sp->GetProcess()->GetStopOnExec();1452 return false;1453 }1454 1455 StopReason GetStopReason() const override { return eStopReasonExec; }1456 1457 const char *GetDescription() override { return "exec"; }1458 1459protected:1460 void PerformAction(Event *event_ptr) override {1461 // Only perform the action once1462 if (m_performed_action)1463 return;1464 m_performed_action = true;1465 ThreadSP thread_sp(m_thread_wp.lock());1466 if (thread_sp)1467 thread_sp->GetProcess()->DidExec();1468 }1469 1470 bool m_performed_action = false;1471};1472 1473// StopInfoFork1474 1475class StopInfoFork : public StopInfo {1476public:1477 StopInfoFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)1478 : StopInfo(thread, child_pid), m_child_pid(child_pid),1479 m_child_tid(child_tid) {}1480 1481 ~StopInfoFork() override = default;1482 1483 bool ShouldStop(Event *event_ptr) override { return false; }1484 1485 StopReason GetStopReason() const override { return eStopReasonFork; }1486 1487 const char *GetDescription() override { return "fork"; }1488 1489 uint32_t GetStopReasonDataCount() const override { return 1; }1490 uint64_t GetStopReasonDataAtIndex(uint32_t idx) override {1491 if (idx == 0)1492 return GetValue();1493 else1494 return 0;1495 }1496 1497protected:1498 void PerformAction(Event *event_ptr) override {1499 // Only perform the action once1500 if (m_performed_action)1501 return;1502 m_performed_action = true;1503 ThreadSP thread_sp(m_thread_wp.lock());1504 if (thread_sp)1505 thread_sp->GetProcess()->DidFork(m_child_pid, m_child_tid);1506 }1507 1508 bool m_performed_action = false;1509 1510private:1511 lldb::pid_t m_child_pid;1512 lldb::tid_t m_child_tid;1513};1514 1515// StopInfoVFork1516 1517class StopInfoVFork : public StopInfo {1518public:1519 StopInfoVFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)1520 : StopInfo(thread, child_pid), m_child_pid(child_pid),1521 m_child_tid(child_tid) {}1522 1523 ~StopInfoVFork() override = default;1524 1525 bool ShouldStop(Event *event_ptr) override { return false; }1526 1527 StopReason GetStopReason() const override { return eStopReasonVFork; }1528 1529 const char *GetDescription() override { return "vfork"; }1530 1531 uint32_t GetStopReasonDataCount() const override { return 1; }1532 uint64_t GetStopReasonDataAtIndex(uint32_t idx) override {1533 if (idx == 0)1534 return GetValue();1535 return 0;1536 }1537 1538protected:1539 void PerformAction(Event *event_ptr) override {1540 // Only perform the action once1541 if (m_performed_action)1542 return;1543 m_performed_action = true;1544 ThreadSP thread_sp(m_thread_wp.lock());1545 if (thread_sp)1546 thread_sp->GetProcess()->DidVFork(m_child_pid, m_child_tid);1547 }1548 1549 bool m_performed_action = false;1550 1551private:1552 lldb::pid_t m_child_pid;1553 lldb::tid_t m_child_tid;1554};1555 1556// StopInfoVForkDone1557 1558class StopInfoVForkDone : public StopInfo {1559public:1560 StopInfoVForkDone(Thread &thread) : StopInfo(thread, 0) {}1561 1562 ~StopInfoVForkDone() override = default;1563 1564 bool ShouldStop(Event *event_ptr) override { return false; }1565 1566 StopReason GetStopReason() const override { return eStopReasonVForkDone; }1567 1568 const char *GetDescription() override { return "vforkdone"; }1569 1570protected:1571 void PerformAction(Event *event_ptr) override {1572 // Only perform the action once1573 if (m_performed_action)1574 return;1575 m_performed_action = true;1576 ThreadSP thread_sp(m_thread_wp.lock());1577 if (thread_sp)1578 thread_sp->GetProcess()->DidVForkDone();1579 }1580 1581 bool m_performed_action = false;1582};1583 1584} // namespace lldb_private1585 1586StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,1587 break_id_t break_id) {1588 thread.SetThreadHitBreakpointSite();1589 1590 return std::make_shared<StopInfoBreakpoint>(thread, break_id);1591}1592 1593StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,1594 break_id_t break_id,1595 bool should_stop) {1596 return std::make_shared<StopInfoBreakpoint>(thread, break_id, should_stop);1597}1598 1599// LWP_TODO: We'll need a CreateStopReasonWithWatchpointResourceID akin1600// to CreateStopReasonWithBreakpointSiteID1601StopInfoSP StopInfo::CreateStopReasonWithWatchpointID(Thread &thread,1602 break_id_t watch_id,1603 bool silently_continue) {1604 return std::make_shared<StopInfoWatchpoint>(thread, watch_id,1605 silently_continue);1606}1607 1608StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,1609 const char *description,1610 std::optional<int> code) {1611 thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);1612 return std::make_shared<StopInfoUnixSignal>(thread, signo, description, code);1613}1614 1615StopInfoSP StopInfo::CreateStopReasonWithInterrupt(Thread &thread, int signo,1616 const char *description) {1617 return std::make_shared<StopInfoInterrupt>(thread, signo, description);1618}1619 1620StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {1621 return std::make_shared<StopInfoTrace>(thread);1622}1623 1624StopInfoSP StopInfo::CreateStopReasonWithPlan(1625 ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp,1626 ExpressionVariableSP expression_variable_sp) {1627 return std::make_shared<StopInfoThreadPlan>(plan_sp, return_valobj_sp,1628 expression_variable_sp);1629}1630 1631StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread,1632 const char *description) {1633 return std::make_shared<StopInfoException>(thread, description);1634}1635 1636StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,1637 const char *description) {1638 return std::make_shared<StopInfoProcessorTrace>(thread, description);1639}1640 1641StopInfoSP StopInfo::CreateStopReasonHistoryBoundary(Thread &thread,1642 const char *description) {1643 return std::make_shared<StopInfoHistoryBoundary>(thread, description);1644}1645 1646StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {1647 return std::make_shared<StopInfoExec>(thread);1648}1649 1650StopInfoSP StopInfo::CreateStopReasonFork(Thread &thread,1651 lldb::pid_t child_pid,1652 lldb::tid_t child_tid) {1653 return std::make_shared<StopInfoFork>(thread, child_pid, child_tid);1654}1655 1656 1657StopInfoSP StopInfo::CreateStopReasonVFork(Thread &thread,1658 lldb::pid_t child_pid,1659 lldb::tid_t child_tid) {1660 return std::make_shared<StopInfoVFork>(thread, child_pid, child_tid);1661}1662 1663StopInfoSP StopInfo::CreateStopReasonVForkDone(Thread &thread) {1664 return std::make_shared<StopInfoVForkDone>(thread);1665}1666 1667ValueObjectSP StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) {1668 if (stop_info_sp &&1669 stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {1670 StopInfoThreadPlan *plan_stop_info =1671 static_cast<StopInfoThreadPlan *>(stop_info_sp.get());1672 return plan_stop_info->GetReturnValueObject();1673 } else1674 return ValueObjectSP();1675}1676 1677ExpressionVariableSP StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) {1678 if (stop_info_sp &&1679 stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {1680 StopInfoThreadPlan *plan_stop_info =1681 static_cast<StopInfoThreadPlan *>(stop_info_sp.get());1682 return plan_stop_info->GetExpressionVariable();1683 } else1684 return ExpressionVariableSP();1685}1686 1687lldb::ValueObjectSP1688StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,1689 lldb::addr_t *crashing_address) {1690 if (!stop_info_sp) {1691 return ValueObjectSP();1692 }1693 1694 const char *description = stop_info_sp->GetDescription();1695 if (!description) {1696 return ValueObjectSP();1697 }1698 1699 ThreadSP thread_sp = stop_info_sp->GetThread();1700 if (!thread_sp) {1701 return ValueObjectSP();1702 }1703 1704 StackFrameSP frame_sp =1705 thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);1706 1707 if (!frame_sp) {1708 return ValueObjectSP();1709 }1710 1711 const char address_string[] = "address=";1712 1713 const char *address_loc = strstr(description, address_string);1714 if (!address_loc) {1715 return ValueObjectSP();1716 }1717 1718 address_loc += (sizeof(address_string) - 1);1719 1720 uint64_t address = strtoull(address_loc, nullptr, 0);1721 if (crashing_address) {1722 *crashing_address = address;1723 }1724 1725 return frame_sp->GuessValueForAddress(address);1726}1727