Path: blob/main/contrib/llvm-project/lldb/source/Target/StopInfo.cpp
39587 views
//===-- StopInfo.cpp ------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <string>910#include "lldb/Breakpoint/Breakpoint.h"11#include "lldb/Breakpoint/BreakpointLocation.h"12#include "lldb/Breakpoint/StoppointCallbackContext.h"13#include "lldb/Breakpoint/Watchpoint.h"14#include "lldb/Breakpoint/WatchpointResource.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/ThreadPlanStepInstruction.h"24#include "lldb/Target/UnixSignals.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/Utility/Log.h"27#include "lldb/Utility/StreamString.h"2829using namespace lldb;30using namespace lldb_private;3132StopInfo::StopInfo(Thread &thread, uint64_t value)33: m_thread_wp(thread.shared_from_this()),34m_stop_id(thread.GetProcess()->GetStopID()),35m_resume_id(thread.GetProcess()->GetResumeID()), m_value(value),36m_description(), m_override_should_notify(eLazyBoolCalculate),37m_override_should_stop(eLazyBoolCalculate), m_extended_info() {}3839bool StopInfo::IsValid() const {40ThreadSP thread_sp(m_thread_wp.lock());41if (thread_sp)42return thread_sp->GetProcess()->GetStopID() == m_stop_id;43return false;44}4546void StopInfo::MakeStopInfoValid() {47ThreadSP thread_sp(m_thread_wp.lock());48if (thread_sp) {49m_stop_id = thread_sp->GetProcess()->GetStopID();50m_resume_id = thread_sp->GetProcess()->GetResumeID();51}52}5354bool StopInfo::HasTargetRunSinceMe() {55ThreadSP thread_sp(m_thread_wp.lock());5657if (thread_sp) {58lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState();59if (ret_type == eStateRunning) {60return true;61} else if (ret_type == eStateStopped) {62// This is a little tricky. We want to count "run and stopped again63// before you could ask this question as a "TRUE" answer to64// HasTargetRunSinceMe. But we don't want to include any running of the65// target done for expressions. So we track both resumes, and resumes66// caused by expressions, and check if there are any resumes67// NOT caused68// by expressions.6970uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID();71uint32_t last_user_expression_id =72thread_sp->GetProcess()->GetLastUserExpressionResumeID();73if (curr_resume_id == m_resume_id) {74return false;75} else if (curr_resume_id > last_user_expression_id) {76return true;77}78}79}80return false;81}8283// StopInfoBreakpoint8485namespace lldb_private {86class StopInfoBreakpoint : public StopInfo {87public:88StopInfoBreakpoint(Thread &thread, break_id_t break_id)89: StopInfo(thread, break_id), m_should_stop(false),90m_should_stop_is_valid(false), m_should_perform_action(true),91m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),92m_was_all_internal(false), m_was_one_shot(false) {93StoreBPInfo();94}9596StopInfoBreakpoint(Thread &thread, break_id_t break_id, bool should_stop)97: StopInfo(thread, break_id), m_should_stop(should_stop),98m_should_stop_is_valid(true), m_should_perform_action(true),99m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),100m_was_all_internal(false), m_was_one_shot(false) {101StoreBPInfo();102}103104~StopInfoBreakpoint() override = default;105106void StoreBPInfo() {107ThreadSP thread_sp(m_thread_wp.lock());108if (thread_sp) {109BreakpointSiteSP bp_site_sp(110thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));111if (bp_site_sp) {112uint32_t num_constituents = bp_site_sp->GetNumberOfConstituents();113if (num_constituents == 1) {114BreakpointLocationSP bp_loc_sp = bp_site_sp->GetConstituentAtIndex(0);115if (bp_loc_sp) {116Breakpoint & bkpt = bp_loc_sp->GetBreakpoint();117m_break_id = bkpt.GetID();118m_was_one_shot = bkpt.IsOneShot();119m_was_all_internal = bkpt.IsInternal();120}121} else {122m_was_all_internal = true;123for (uint32_t i = 0; i < num_constituents; i++) {124if (!bp_site_sp->GetConstituentAtIndex(i)125->GetBreakpoint()126.IsInternal()) {127m_was_all_internal = false;128break;129}130}131}132m_address = bp_site_sp->GetLoadAddress();133}134}135}136137bool IsValidForOperatingSystemThread(Thread &thread) override {138ProcessSP process_sp(thread.GetProcess());139if (process_sp) {140BreakpointSiteSP bp_site_sp(141process_sp->GetBreakpointSiteList().FindByID(m_value));142if (bp_site_sp)143return bp_site_sp->ValidForThisThread(thread);144}145return false;146}147148StopReason GetStopReason() const override { return eStopReasonBreakpoint; }149150bool ShouldStopSynchronous(Event *event_ptr) override {151ThreadSP thread_sp(m_thread_wp.lock());152if (thread_sp) {153if (!m_should_stop_is_valid) {154// Only check once if we should stop at a breakpoint155BreakpointSiteSP bp_site_sp(156thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));157if (bp_site_sp) {158ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));159StoppointCallbackContext context(event_ptr, exe_ctx, true);160bp_site_sp->BumpHitCounts();161m_should_stop = bp_site_sp->ShouldStop(&context);162} else {163Log *log = GetLog(LLDBLog::Process);164165LLDB_LOGF(log,166"Process::%s could not find breakpoint site id: %" PRId64167"...",168__FUNCTION__, m_value);169170m_should_stop = true;171}172m_should_stop_is_valid = true;173}174return m_should_stop;175}176return false;177}178179bool DoShouldNotify(Event *event_ptr) override {180return !m_was_all_internal;181}182183const char *GetDescription() override {184if (m_description.empty()) {185ThreadSP thread_sp(m_thread_wp.lock());186if (thread_sp) {187BreakpointSiteSP bp_site_sp(188thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));189if (bp_site_sp) {190StreamString strm;191// If we have just hit an internal breakpoint, and it has a kind192// description, print that instead of the full breakpoint printing:193if (bp_site_sp->IsInternal()) {194size_t num_constituents = bp_site_sp->GetNumberOfConstituents();195for (size_t idx = 0; idx < num_constituents; idx++) {196const char *kind = bp_site_sp->GetConstituentAtIndex(idx)197->GetBreakpoint()198.GetBreakpointKind();199if (kind != nullptr) {200m_description.assign(kind);201return kind;202}203}204}205206strm.Printf("breakpoint ");207bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);208m_description = std::string(strm.GetString());209} else {210StreamString strm;211if (m_break_id != LLDB_INVALID_BREAK_ID) {212BreakpointSP break_sp =213thread_sp->GetProcess()->GetTarget().GetBreakpointByID(214m_break_id);215if (break_sp) {216if (break_sp->IsInternal()) {217const char *kind = break_sp->GetBreakpointKind();218if (kind)219strm.Printf("internal %s breakpoint(%d).", kind, m_break_id);220else221strm.Printf("internal breakpoint(%d).", m_break_id);222} else {223strm.Printf("breakpoint %d.", m_break_id);224}225} else {226if (m_was_one_shot)227strm.Printf("one-shot breakpoint %d", m_break_id);228else229strm.Printf("breakpoint %d which has been deleted.",230m_break_id);231}232} else if (m_address == LLDB_INVALID_ADDRESS)233strm.Printf("breakpoint site %" PRIi64234" which has been deleted - unknown address",235m_value);236else237strm.Printf("breakpoint site %" PRIi64238" which has been deleted - was at 0x%" PRIx64,239m_value, m_address);240241m_description = std::string(strm.GetString());242}243}244}245return m_description.c_str();246}247248protected:249bool ShouldStop(Event *event_ptr) override {250// This just reports the work done by PerformAction or the synchronous251// stop. It should only ever get called after they have had a chance to252// run.253assert(m_should_stop_is_valid);254return m_should_stop;255}256257void PerformAction(Event *event_ptr) override {258if (!m_should_perform_action)259return;260m_should_perform_action = false;261bool all_stopping_locs_internal = true;262263ThreadSP thread_sp(m_thread_wp.lock());264265if (thread_sp) {266Log *log = GetLog(LLDBLog::Breakpoints | LLDBLog::Step);267268if (!thread_sp->IsValid()) {269// This shouldn't ever happen, but just in case, don't do more harm.270if (log) {271LLDB_LOGF(log, "PerformAction got called with an invalid thread.");272}273m_should_stop = true;274m_should_stop_is_valid = true;275return;276}277278BreakpointSiteSP bp_site_sp(279thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));280std::unordered_set<break_id_t> precondition_breakpoints;281// Breakpoints that fail their condition check are not considered to282// have been hit. If the only locations at this site have failed their283// conditions, we should change the stop-info to none. Otherwise, if we284// hit another breakpoint on a different thread which does stop, users285// will see a breakpont hit with a failed condition, which is wrong.286// Use this variable to tell us if that is true.287bool actually_hit_any_locations = false;288if (bp_site_sp) {289// Let's copy the constituents list out of the site and store them in a290// local list. That way if one of the breakpoint actions changes the291// site, then we won't be operating on a bad list.292BreakpointLocationCollection site_locations;293size_t num_constituents =294bp_site_sp->CopyConstituentsList(site_locations);295296if (num_constituents == 0) {297m_should_stop = true;298actually_hit_any_locations = true; // We're going to stop, don't299// change the stop info.300} else {301// We go through each location, and test first its precondition -302// this overrides everything. Note, we only do this once per303// breakpoint - not once per location... Then check the condition.304// If the condition says to stop, then we run the callback for that305// location. If that callback says to stop as well, then we set306// m_should_stop to true; we are going to stop. But we still want to307// give all the breakpoints whose conditions say we are going to stop308// a chance to run their callbacks. Of course if any callback309// restarts the target by putting "continue" in the callback, then310// we're going to restart, without running the rest of the callbacks.311// And in this case we will end up not stopping even if another312// location said we should stop. But that's better than not running313// all the callbacks.314315// There's one other complication here. We may have run an async316// breakpoint callback that said we should stop. We only want to317// override that if another breakpoint action says we shouldn't318// stop. If nobody else has an opinion, then we should stop if the319// async callback says we should. An example of this is the async320// shared library load notification breakpoint and the setting321// stop-on-sharedlibrary-events.322// We'll keep the async value in async_should_stop, and track whether323// anyone said we should NOT stop in actually_said_continue.324bool async_should_stop = false;325if (m_should_stop_is_valid)326async_should_stop = m_should_stop;327bool actually_said_continue = false;328329m_should_stop = false;330331// We don't select threads as we go through them testing breakpoint332// conditions and running commands. So we need to set the thread for333// expression evaluation here:334ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);335336ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));337Process *process = exe_ctx.GetProcessPtr();338if (process->GetModIDRef().IsRunningExpression()) {339// If we are in the middle of evaluating an expression, don't run340// asynchronous breakpoint commands or expressions. That could341// lead to infinite recursion if the command or condition re-calls342// the function with this breakpoint.343// TODO: We can keep a list of the breakpoints we've seen while344// running expressions in the nested345// PerformAction calls that can arise when the action runs a346// function that hits another breakpoint, and only stop running347// commands when we see the same breakpoint hit a second time.348349m_should_stop_is_valid = true;350351// It is possible that the user has a breakpoint at the same site352// as the completed plan had (e.g. user has a breakpoint353// on a module entry point, and `ThreadPlanCallFunction` ends354// also there). We can't find an internal breakpoint in the loop355// later because it was already removed on the plan completion.356// So check if the plan was completed, and stop if so.357if (thread_sp->CompletedPlanOverridesBreakpoint()) {358m_should_stop = true;359thread_sp->ResetStopInfo();360return;361}362363LLDB_LOGF(log, "StopInfoBreakpoint::PerformAction - Hit a "364"breakpoint while running an expression,"365" not running commands to avoid recursion.");366bool ignoring_breakpoints =367process->GetIgnoreBreakpointsInExpressions();368// Internal breakpoints should be allowed to do their job, we369// can make sure they don't do anything that would cause recursive370// command execution:371if (!m_was_all_internal) {372m_should_stop = !ignoring_breakpoints;373LLDB_LOGF(log,374"StopInfoBreakpoint::PerformAction - in expression, "375"continuing: %s.",376m_should_stop ? "true" : "false");377Debugger::ReportWarning(378"hit breakpoint while running function, skipping commands "379"and conditions to prevent recursion",380process->GetTarget().GetDebugger().GetID());381return;382}383}384385StoppointCallbackContext context(event_ptr, exe_ctx, false);386387// For safety's sake let's also grab an extra reference to the388// breakpoint constituents of the locations we're going to examine,389// since the locations are going to have to get back to their390// breakpoints, and the locations don't keep their constituents alive.391// I'm just sticking the BreakpointSP's in a vector since I'm only392// using it to locally increment their retain counts.393394std::vector<lldb::BreakpointSP> location_constituents;395396for (size_t j = 0; j < num_constituents; j++) {397BreakpointLocationSP loc(site_locations.GetByIndex(j));398location_constituents.push_back(399loc->GetBreakpoint().shared_from_this());400}401402for (size_t j = 0; j < num_constituents; j++) {403lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);404StreamString loc_desc;405if (log) {406bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief);407}408// If another action disabled this breakpoint or its location, then409// don't run the actions.410if (!bp_loc_sp->IsEnabled() ||411!bp_loc_sp->GetBreakpoint().IsEnabled())412continue;413414// The breakpoint site may have many locations associated with it,415// not all of them valid for this thread. Skip the ones that416// aren't:417if (!bp_loc_sp->ValidForThisThread(*thread_sp)) {418if (log) {419LLDB_LOGF(log,420"Breakpoint %s hit on thread 0x%llx but it was not "421"for this thread, continuing.",422loc_desc.GetData(),423static_cast<unsigned long long>(thread_sp->GetID()));424}425continue;426}427428// First run the precondition, but since the precondition is per429// breakpoint, only run it once per breakpoint.430std::pair<std::unordered_set<break_id_t>::iterator, bool> result =431precondition_breakpoints.insert(432bp_loc_sp->GetBreakpoint().GetID());433if (!result.second)434continue;435436bool precondition_result =437bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);438if (!precondition_result) {439actually_said_continue = true;440continue;441}442// Next run the condition for the breakpoint. If that says we443// should stop, then we'll run the callback for the breakpoint. If444// the callback says we shouldn't stop that will win.445446if (bp_loc_sp->GetConditionText() == nullptr)447actually_hit_any_locations = true;448else {449Status condition_error;450bool condition_says_stop =451bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);452453if (!condition_error.Success()) {454// If the condition fails to evaluate, we are going to stop455// at it, so the location was hit.456actually_hit_any_locations = true;457const char *err_str =458condition_error.AsCString("<unknown error>");459LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);460461StreamString strm;462strm << "stopped due to an error evaluating condition of "463"breakpoint ";464bp_loc_sp->GetDescription(&strm, eDescriptionLevelBrief);465strm << ": \"" << bp_loc_sp->GetConditionText() << "\"\n";466strm << err_str;467468Debugger::ReportError(469strm.GetString().str(),470exe_ctx.GetTargetRef().GetDebugger().GetID());471} else {472LLDB_LOGF(log,473"Condition evaluated for breakpoint %s on thread "474"0x%llx condition_says_stop: %i.",475loc_desc.GetData(),476static_cast<unsigned long long>(thread_sp->GetID()),477condition_says_stop);478if (condition_says_stop)479actually_hit_any_locations = true;480else {481// We don't want to increment the hit count of breakpoints if482// the condition fails. We've already bumped it by the time483// we get here, so undo the bump:484bp_loc_sp->UndoBumpHitCount();485actually_said_continue = true;486continue;487}488}489}490491// We've done all the checks whose failure means "we consider lldb492// not to have hit the breakpoint". Now we're going to check for493// conditions that might continue after hitting. Start with the494// ignore count:495if (!bp_loc_sp->IgnoreCountShouldStop()) {496actually_said_continue = true;497continue;498}499500// Check the auto-continue bit on the location, do this before the501// callback since it may change this, but that would be for the502// NEXT hit. Note, you might think you could check auto-continue503// before the condition, and not evaluate the condition if it says504// to continue. But failing the condition means the breakpoint was505// effectively NOT HIT. So these two states are different.506bool auto_continue_says_stop = true;507if (bp_loc_sp->IsAutoContinue())508{509LLDB_LOGF(log,510"Continuing breakpoint %s as AutoContinue was set.",511loc_desc.GetData());512// We want this stop reported, so you will know we auto-continued513// but only for external breakpoints:514if (!bp_loc_sp->GetBreakpoint().IsInternal())515thread_sp->SetShouldReportStop(eVoteYes);516auto_continue_says_stop = false;517}518519bool callback_says_stop = true;520521// FIXME: For now the callbacks have to run in async mode - the522// first time we restart we need523// to get out of there. So set it here.524// When we figure out how to nest breakpoint hits then this will525// change.526527// Don't run async callbacks in PerformAction. They have already528// been taken into account with async_should_stop.529if (!bp_loc_sp->IsCallbackSynchronous()) {530Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();531bool old_async = debugger.GetAsyncExecution();532debugger.SetAsyncExecution(true);533534callback_says_stop = bp_loc_sp->InvokeCallback(&context);535536debugger.SetAsyncExecution(old_async);537538if (callback_says_stop && auto_continue_says_stop)539m_should_stop = true;540else541actually_said_continue = true;542}543544if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())545all_stopping_locs_internal = false;546547// If we are going to stop for this breakpoint, then remove the548// breakpoint.549if (callback_says_stop && bp_loc_sp &&550bp_loc_sp->GetBreakpoint().IsOneShot()) {551thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(552bp_loc_sp->GetBreakpoint().GetID());553}554// Also make sure that the callback hasn't continued the target. If555// it did, when we'll set m_should_start to false and get out of556// here.557if (HasTargetRunSinceMe()) {558m_should_stop = false;559actually_said_continue = true;560break;561}562}563// At this point if nobody actually told us to continue, we should564// give the async breakpoint callback a chance to weigh in:565if (!actually_said_continue && !m_should_stop) {566m_should_stop = async_should_stop;567}568}569// We've figured out what this stop wants to do, so mark it as valid so570// we don't compute it again.571m_should_stop_is_valid = true;572} else {573m_should_stop = true;574m_should_stop_is_valid = true;575actually_hit_any_locations = true;576Log *log_process(GetLog(LLDBLog::Process));577578LLDB_LOGF(log_process,579"Process::%s could not find breakpoint site id: %" PRId64580"...",581__FUNCTION__, m_value);582}583584if ((!m_should_stop || all_stopping_locs_internal) &&585thread_sp->CompletedPlanOverridesBreakpoint()) {586587// Override should_stop decision when we have completed step plan588// additionally to the breakpoint589m_should_stop = true;590591// We know we're stopping for a completed plan and we don't want to592// show the breakpoint stop, so compute the public stop info immediately593// here.594thread_sp->CalculatePublicStopInfo();595} else if (!actually_hit_any_locations) {596// In the end, we didn't actually have any locations that passed their597// "was I hit" checks. So say we aren't stopped.598GetThread()->ResetStopInfo();599LLDB_LOGF(log, "Process::%s all locations failed condition checks.",600__FUNCTION__);601}602603LLDB_LOGF(log,604"Process::%s returning from action with m_should_stop: %d.",605__FUNCTION__, m_should_stop);606}607}608609private:610bool m_should_stop;611bool m_should_stop_is_valid;612bool m_should_perform_action; // Since we are trying to preserve the "state"613// of the system even if we run functions614// etc. behind the users backs, we need to make sure we only REALLY perform615// the action once.616lldb::addr_t m_address; // We use this to capture the breakpoint site address617// when we create the StopInfo,618// in case somebody deletes it between the time the StopInfo is made and the619// description is asked for.620lldb::break_id_t m_break_id;621bool m_was_all_internal;622bool m_was_one_shot;623};624625// StopInfoWatchpoint626627class StopInfoWatchpoint : public StopInfo {628public:629// Make sure watchpoint is properly disabled and subsequently enabled while630// performing watchpoint actions.631class WatchpointSentry {632public:633WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),634watchpoint_sp(w_sp) {635if (process_sp && watchpoint_sp) {636const bool notify = false;637watchpoint_sp->TurnOnEphemeralMode();638process_sp->DisableWatchpoint(watchpoint_sp, notify);639process_sp->AddPreResumeAction(SentryPreResumeAction, this);640}641}642643void DoReenable() {644if (process_sp && watchpoint_sp) {645bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();646watchpoint_sp->TurnOffEphemeralMode();647const bool notify = false;648if (was_disabled) {649process_sp->DisableWatchpoint(watchpoint_sp, notify);650} else {651process_sp->EnableWatchpoint(watchpoint_sp, notify);652}653}654}655656~WatchpointSentry() {657DoReenable();658if (process_sp)659process_sp->ClearPreResumeAction(SentryPreResumeAction, this);660}661662static bool SentryPreResumeAction(void *sentry_void) {663WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;664sentry->DoReenable();665return true;666}667668private:669ProcessSP process_sp;670WatchpointSP watchpoint_sp;671};672673StopInfoWatchpoint(Thread &thread, break_id_t watch_id, bool silently_skip_wp)674: StopInfo(thread, watch_id), m_silently_skip_wp(silently_skip_wp) {}675676~StopInfoWatchpoint() override = default;677678StopReason GetStopReason() const override { return eStopReasonWatchpoint; }679680const char *GetDescription() override {681if (m_description.empty()) {682StreamString strm;683strm.Printf("watchpoint %" PRIi64, m_value);684m_description = std::string(strm.GetString());685}686return m_description.c_str();687}688689protected:690using StopInfoWatchpointSP = std::shared_ptr<StopInfoWatchpoint>;691// This plan is used to orchestrate stepping over the watchpoint for692// architectures (e.g. ARM) that report the watch before running the watched693// access. This is the sort of job you have to defer to the thread plans,694// if you try to do it directly in the stop info and there are other threads695// that needed to process this stop you will have yanked control away from696// them and they won't behave correctly.697class ThreadPlanStepOverWatchpoint : public ThreadPlanStepInstruction {698public:699ThreadPlanStepOverWatchpoint(Thread &thread,700StopInfoWatchpointSP stop_info_sp,701WatchpointSP watch_sp)702: ThreadPlanStepInstruction(thread, false, true, eVoteNoOpinion,703eVoteNoOpinion),704m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) {705assert(watch_sp);706}707708bool DoWillResume(lldb::StateType resume_state,709bool current_plan) override {710if (resume_state == eStateSuspended)711return true;712713if (!m_did_disable_wp) {714GetThread().GetProcess()->DisableWatchpoint(m_watch_sp, false);715m_did_disable_wp = true;716}717return true;718}719720bool DoPlanExplainsStop(Event *event_ptr) override {721if (ThreadPlanStepInstruction::DoPlanExplainsStop(event_ptr))722return true;723StopInfoSP stop_info_sp = GetThread().GetPrivateStopInfo();724// lldb-server resets the stop info for threads that didn't get to run,725// so we might have not gotten to run, but still have a watchpoint stop726// reason, in which case this will indeed be for us.727if (stop_info_sp728&& stop_info_sp->GetStopReason() == eStopReasonWatchpoint)729return true;730return false;731}732733void DidPop() override {734// Don't artifically keep the watchpoint alive.735m_watch_sp.reset();736}737738bool ShouldStop(Event *event_ptr) override {739bool should_stop = ThreadPlanStepInstruction::ShouldStop(event_ptr);740bool plan_done = MischiefManaged();741if (plan_done) {742m_stop_info_sp->SetStepOverPlanComplete();743GetThread().SetStopInfo(m_stop_info_sp);744ResetWatchpoint();745}746return should_stop;747}748749bool ShouldRunBeforePublicStop() override {750return true;751}752753protected:754void ResetWatchpoint() {755if (!m_did_disable_wp)756return;757m_did_disable_wp = true;758GetThread().GetProcess()->EnableWatchpoint(m_watch_sp, true);759}760761private:762StopInfoWatchpointSP m_stop_info_sp;763WatchpointSP m_watch_sp;764bool m_did_disable_wp = false;765};766767bool ShouldStopSynchronous(Event *event_ptr) override {768// If we are running our step-over the watchpoint plan, stop if it's done769// and continue if it's not:770if (m_should_stop_is_valid)771return m_should_stop;772773// If we are running our step over plan, then stop here and let the regular774// ShouldStop figure out what we should do: Otherwise, give our plan775// more time to get run:776if (m_using_step_over_plan)777return m_step_over_plan_complete;778779Log *log = GetLog(LLDBLog::Process);780ThreadSP thread_sp(m_thread_wp.lock());781assert(thread_sp);782783if (thread_sp->GetTemporaryResumeState() == eStateSuspended) {784// This is the second firing of a watchpoint so don't process it again.785LLDB_LOG(log, "We didn't run but stopped with a StopInfoWatchpoint, we "786"have already handled this one, don't do it again.");787m_should_stop = false;788m_should_stop_is_valid = true;789return m_should_stop;790}791792WatchpointSP wp_sp(793thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue()));794// If we can no longer find the watchpoint, we just have to stop:795if (!wp_sp) {796797LLDB_LOGF(log,798"Process::%s could not find watchpoint location id: %" PRId64799"...",800__FUNCTION__, GetValue());801802m_should_stop = true;803m_should_stop_is_valid = true;804return true;805}806807ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));808StoppointCallbackContext context(event_ptr, exe_ctx, true);809m_should_stop = wp_sp->ShouldStop(&context);810if (!m_should_stop) {811// This won't happen at present because we only allow one watchpoint per812// watched range. So we won't stop at a watched address with a disabled813// watchpoint. If we start allowing overlapping watchpoints, then we814// will have to make watchpoints be real "WatchpointSite" and delegate to815// all the watchpoints sharing the site. In that case, the code below816// would be the right thing to do.817m_should_stop_is_valid = true;818return m_should_stop;819}820// If this is a system where we need to execute the watchpoint by hand821// after the hit, queue a thread plan to do that, and then say not to stop.822// Otherwise, let the async action figure out whether the watchpoint should823// stop824825ProcessSP process_sp = exe_ctx.GetProcessSP();826bool wp_triggers_after = process_sp->GetWatchpointReportedAfter();827828if (!wp_triggers_after) {829// We have to step over the watchpoint before we know what to do:830StopInfoWatchpointSP me_as_siwp_sp831= std::static_pointer_cast<StopInfoWatchpoint>(shared_from_this());832ThreadPlanSP step_over_wp_sp(new ThreadPlanStepOverWatchpoint(833*(thread_sp.get()), me_as_siwp_sp, wp_sp));834// When this plan is done we want to stop, so set this as a Controlling835// plan.836step_over_wp_sp->SetIsControllingPlan(true);837step_over_wp_sp->SetOkayToDiscard(false);838839Status error;840error = thread_sp->QueueThreadPlan(step_over_wp_sp, false);841// If we couldn't push the thread plan, just stop here:842if (!error.Success()) {843LLDB_LOGF(log, "Could not push our step over watchpoint plan: %s",844error.AsCString());845846m_should_stop = true;847m_should_stop_is_valid = true;848return true;849} else {850// Otherwise, don't set m_should_stop, we don't know that yet. Just851// say we should continue, and tell the thread we really should do so:852thread_sp->SetShouldRunBeforePublicStop(true);853m_using_step_over_plan = true;854return false;855}856} else {857// We didn't have to do anything special858m_should_stop_is_valid = true;859return m_should_stop;860}861862return m_should_stop;863}864865bool ShouldStop(Event *event_ptr) override {866// This just reports the work done by PerformAction or the synchronous867// stop. It should only ever get called after they have had a chance to868// run.869assert(m_should_stop_is_valid);870return m_should_stop;871}872873void PerformAction(Event *event_ptr) override {874Log *log = GetLog(LLDBLog::Watchpoints);875// We're going to calculate if we should stop or not in some way during the876// course of this code. Also by default we're going to stop, so set that877// here.878m_should_stop = true;879880881ThreadSP thread_sp(m_thread_wp.lock());882if (thread_sp) {883884WatchpointSP wp_sp(885thread_sp->CalculateTarget()->GetWatchpointList().FindByID(886GetValue()));887if (wp_sp) {888// This sentry object makes sure the current watchpoint is disabled889// while performing watchpoint actions, and it is then enabled after we890// are finished.891ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));892ProcessSP process_sp = exe_ctx.GetProcessSP();893894WatchpointSentry sentry(process_sp, wp_sp);895896if (m_silently_skip_wp) {897m_should_stop = false;898wp_sp->UndoHitCount();899}900901if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) {902m_should_stop = false;903m_should_stop_is_valid = true;904}905906Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();907908if (m_should_stop && wp_sp->GetConditionText() != nullptr) {909// We need to make sure the user sees any parse errors in their910// condition, so we'll hook the constructor errors up to the911// debugger's Async I/O.912ExpressionResults result_code;913EvaluateExpressionOptions expr_options;914expr_options.SetUnwindOnError(true);915expr_options.SetIgnoreBreakpoints(true);916ValueObjectSP result_value_sp;917Status error;918result_code = UserExpression::Evaluate(919exe_ctx, expr_options, wp_sp->GetConditionText(),920llvm::StringRef(), result_value_sp, error);921922if (result_code == eExpressionCompleted) {923if (result_value_sp) {924Scalar scalar_value;925if (result_value_sp->ResolveValue(scalar_value)) {926if (scalar_value.ULongLong(1) == 0) {927// The condition failed, which we consider "not having hit928// the watchpoint" so undo the hit count here.929wp_sp->UndoHitCount();930m_should_stop = false;931} else932m_should_stop = true;933LLDB_LOGF(log,934"Condition successfully evaluated, result is %s.\n",935m_should_stop ? "true" : "false");936} else {937m_should_stop = true;938LLDB_LOGF(939log,940"Failed to get an integer result from the expression.");941}942}943} else {944const char *err_str = error.AsCString("<unknown error>");945LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);946947StreamString strm;948strm << "stopped due to an error evaluating condition of "949"watchpoint ";950wp_sp->GetDescription(&strm, eDescriptionLevelBrief);951strm << ": \"" << wp_sp->GetConditionText() << "\"\n";952strm << err_str;953954Debugger::ReportError(strm.GetString().str(),955exe_ctx.GetTargetRef().GetDebugger().GetID());956}957}958959// If the condition says to stop, we run the callback to further decide960// whether to stop.961if (m_should_stop) {962// FIXME: For now the callbacks have to run in async mode - the963// first time we restart we need964// to get out of there. So set it here.965// When we figure out how to nest watchpoint hits then this will966// change.967968bool old_async = debugger.GetAsyncExecution();969debugger.SetAsyncExecution(true);970971StoppointCallbackContext context(event_ptr, exe_ctx, false);972bool stop_requested = wp_sp->InvokeCallback(&context);973974debugger.SetAsyncExecution(old_async);975976// Also make sure that the callback hasn't continued the target. If977// it did, when we'll set m_should_stop to false and get out of here.978if (HasTargetRunSinceMe())979m_should_stop = false;980981if (m_should_stop && !stop_requested) {982// We have been vetoed by the callback mechanism.983m_should_stop = false;984}985}986987// Don't stop if the watched region value is unmodified, and988// this is a Modify-type watchpoint.989if (m_should_stop && !wp_sp->WatchedValueReportable(exe_ctx)) {990wp_sp->UndoHitCount();991m_should_stop = false;992}993994// Finally, if we are going to stop, print out the new & old values:995if (m_should_stop) {996wp_sp->CaptureWatchedValue(exe_ctx);997998Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();999StreamSP output_sp = debugger.GetAsyncOutputStream();1000if (wp_sp->DumpSnapshots(output_sp.get())) {1001output_sp->EOL();1002output_sp->Flush();1003}1004}10051006} else {1007Log *log_process(GetLog(LLDBLog::Process));10081009LLDB_LOGF(log_process,1010"Process::%s could not find watchpoint id: %" PRId64 "...",1011__FUNCTION__, m_value);1012}1013LLDB_LOGF(log,1014"Process::%s returning from action with m_should_stop: %d.",1015__FUNCTION__, m_should_stop);10161017m_should_stop_is_valid = true;1018}1019}10201021private:1022void SetStepOverPlanComplete() {1023assert(m_using_step_over_plan);1024m_step_over_plan_complete = true;1025}10261027bool m_should_stop = false;1028bool m_should_stop_is_valid = false;1029// A false watchpoint hit has happened -1030// the thread stopped with a watchpoint1031// hit notification, but the watched region1032// was not actually accessed (as determined1033// by the gdb stub we're talking to).1034// Continue past this watchpoint without1035// notifying the user; on some targets this1036// may mean disable wp, instruction step,1037// re-enable wp, continue.1038// On others, just continue.1039bool m_silently_skip_wp = false;1040bool m_step_over_plan_complete = false;1041bool m_using_step_over_plan = false;1042};10431044// StopInfoUnixSignal10451046class StopInfoUnixSignal : public StopInfo {1047public:1048StopInfoUnixSignal(Thread &thread, int signo, const char *description,1049std::optional<int> code)1050: StopInfo(thread, signo), m_code(code) {1051SetDescription(description);1052}10531054~StopInfoUnixSignal() override = default;10551056StopReason GetStopReason() const override { return eStopReasonSignal; }10571058bool ShouldStopSynchronous(Event *event_ptr) override {1059ThreadSP thread_sp(m_thread_wp.lock());1060if (thread_sp)1061return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);1062return false;1063}10641065bool ShouldStop(Event *event_ptr) override {1066ThreadSP thread_sp(m_thread_wp.lock());1067if (thread_sp)1068return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);1069return false;1070}10711072// If should stop returns false, check if we should notify of this event1073bool DoShouldNotify(Event *event_ptr) override {1074ThreadSP thread_sp(m_thread_wp.lock());1075if (thread_sp) {1076bool should_notify =1077thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value);1078if (should_notify) {1079StreamString strm;1080strm.Format(1081"thread {0:d} received signal: {1}", thread_sp->GetIndexID(),1082thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsStringRef(1083m_value));1084Process::ProcessEventData::AddRestartedReason(event_ptr,1085strm.GetData());1086}1087return should_notify;1088}1089return true;1090}10911092void WillResume(lldb::StateType resume_state) override {1093ThreadSP thread_sp(m_thread_wp.lock());1094if (thread_sp) {1095if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(1096m_value))1097thread_sp->SetResumeSignal(m_value);1098}1099}11001101const char *GetDescription() override {1102if (m_description.empty()) {1103ThreadSP thread_sp(m_thread_wp.lock());1104if (thread_sp) {1105UnixSignalsSP unix_signals = thread_sp->GetProcess()->GetUnixSignals();1106StreamString strm;1107strm << "signal ";11081109std::string signal_name =1110unix_signals->GetSignalDescription(m_value, m_code);1111if (signal_name.size())1112strm << signal_name;1113else1114strm.Printf("%" PRIi64, m_value);11151116m_description = std::string(strm.GetString());1117}1118}1119return m_description.c_str();1120}11211122private:1123// In siginfo_t terms, if m_value is si_signo, m_code is si_code.1124std::optional<int> m_code;1125};11261127// StopInfoTrace11281129class StopInfoTrace : public StopInfo {1130public:1131StopInfoTrace(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}11321133~StopInfoTrace() override = default;11341135StopReason GetStopReason() const override { return eStopReasonTrace; }11361137const char *GetDescription() override {1138if (m_description.empty())1139return "trace";1140else1141return m_description.c_str();1142}1143};11441145// StopInfoException11461147class StopInfoException : public StopInfo {1148public:1149StopInfoException(Thread &thread, const char *description)1150: StopInfo(thread, LLDB_INVALID_UID) {1151if (description)1152SetDescription(description);1153}11541155~StopInfoException() override = default;11561157StopReason GetStopReason() const override { return eStopReasonException; }11581159const char *GetDescription() override {1160if (m_description.empty())1161return "exception";1162else1163return m_description.c_str();1164}1165};11661167// StopInfoProcessorTrace11681169class StopInfoProcessorTrace : public StopInfo {1170public:1171StopInfoProcessorTrace(Thread &thread, const char *description)1172: StopInfo(thread, LLDB_INVALID_UID) {1173if (description)1174SetDescription(description);1175}11761177~StopInfoProcessorTrace() override = default;11781179StopReason GetStopReason() const override {1180return eStopReasonProcessorTrace;1181}11821183const char *GetDescription() override {1184if (m_description.empty())1185return "processor trace event";1186else1187return m_description.c_str();1188}1189};11901191// StopInfoThreadPlan11921193class StopInfoThreadPlan : public StopInfo {1194public:1195StopInfoThreadPlan(ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp,1196ExpressionVariableSP &expression_variable_sp)1197: StopInfo(plan_sp->GetThread(), LLDB_INVALID_UID), m_plan_sp(plan_sp),1198m_return_valobj_sp(return_valobj_sp),1199m_expression_variable_sp(expression_variable_sp) {}12001201~StopInfoThreadPlan() override = default;12021203StopReason GetStopReason() const override { return eStopReasonPlanComplete; }12041205const char *GetDescription() override {1206if (m_description.empty()) {1207StreamString strm;1208m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief);1209m_description = std::string(strm.GetString());1210}1211return m_description.c_str();1212}12131214ValueObjectSP GetReturnValueObject() { return m_return_valobj_sp; }12151216ExpressionVariableSP GetExpressionVariable() {1217return m_expression_variable_sp;1218}12191220protected:1221bool ShouldStop(Event *event_ptr) override {1222if (m_plan_sp)1223return m_plan_sp->ShouldStop(event_ptr);1224else1225return StopInfo::ShouldStop(event_ptr);1226}12271228private:1229ThreadPlanSP m_plan_sp;1230ValueObjectSP m_return_valobj_sp;1231ExpressionVariableSP m_expression_variable_sp;1232};12331234// StopInfoExec12351236class StopInfoExec : public StopInfo {1237public:1238StopInfoExec(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}12391240~StopInfoExec() override = default;12411242bool ShouldStop(Event *event_ptr) override {1243ThreadSP thread_sp(m_thread_wp.lock());1244if (thread_sp)1245return thread_sp->GetProcess()->GetStopOnExec();1246return false;1247}12481249StopReason GetStopReason() const override { return eStopReasonExec; }12501251const char *GetDescription() override { return "exec"; }12521253protected:1254void PerformAction(Event *event_ptr) override {1255// Only perform the action once1256if (m_performed_action)1257return;1258m_performed_action = true;1259ThreadSP thread_sp(m_thread_wp.lock());1260if (thread_sp)1261thread_sp->GetProcess()->DidExec();1262}12631264bool m_performed_action = false;1265};12661267// StopInfoFork12681269class StopInfoFork : public StopInfo {1270public:1271StopInfoFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)1272: StopInfo(thread, child_pid), m_child_pid(child_pid),1273m_child_tid(child_tid) {}12741275~StopInfoFork() override = default;12761277bool ShouldStop(Event *event_ptr) override { return false; }12781279StopReason GetStopReason() const override { return eStopReasonFork; }12801281const char *GetDescription() override { return "fork"; }12821283protected:1284void PerformAction(Event *event_ptr) override {1285// Only perform the action once1286if (m_performed_action)1287return;1288m_performed_action = true;1289ThreadSP thread_sp(m_thread_wp.lock());1290if (thread_sp)1291thread_sp->GetProcess()->DidFork(m_child_pid, m_child_tid);1292}12931294bool m_performed_action = false;12951296private:1297lldb::pid_t m_child_pid;1298lldb::tid_t m_child_tid;1299};13001301// StopInfoVFork13021303class StopInfoVFork : public StopInfo {1304public:1305StopInfoVFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)1306: StopInfo(thread, child_pid), m_child_pid(child_pid),1307m_child_tid(child_tid) {}13081309~StopInfoVFork() override = default;13101311bool ShouldStop(Event *event_ptr) override { return false; }13121313StopReason GetStopReason() const override { return eStopReasonVFork; }13141315const char *GetDescription() override { return "vfork"; }13161317protected:1318void PerformAction(Event *event_ptr) override {1319// Only perform the action once1320if (m_performed_action)1321return;1322m_performed_action = true;1323ThreadSP thread_sp(m_thread_wp.lock());1324if (thread_sp)1325thread_sp->GetProcess()->DidVFork(m_child_pid, m_child_tid);1326}13271328bool m_performed_action = false;13291330private:1331lldb::pid_t m_child_pid;1332lldb::tid_t m_child_tid;1333};13341335// StopInfoVForkDone13361337class StopInfoVForkDone : public StopInfo {1338public:1339StopInfoVForkDone(Thread &thread) : StopInfo(thread, 0) {}13401341~StopInfoVForkDone() override = default;13421343bool ShouldStop(Event *event_ptr) override { return false; }13441345StopReason GetStopReason() const override { return eStopReasonVForkDone; }13461347const char *GetDescription() override { return "vforkdone"; }13481349protected:1350void PerformAction(Event *event_ptr) override {1351// Only perform the action once1352if (m_performed_action)1353return;1354m_performed_action = true;1355ThreadSP thread_sp(m_thread_wp.lock());1356if (thread_sp)1357thread_sp->GetProcess()->DidVForkDone();1358}13591360bool m_performed_action = false;1361};13621363} // namespace lldb_private13641365StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,1366break_id_t break_id) {1367return StopInfoSP(new StopInfoBreakpoint(thread, break_id));1368}13691370StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,1371break_id_t break_id,1372bool should_stop) {1373return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));1374}13751376// LWP_TODO: We'll need a CreateStopReasonWithWatchpointResourceID akin1377// to CreateStopReasonWithBreakpointSiteID1378StopInfoSP StopInfo::CreateStopReasonWithWatchpointID(Thread &thread,1379break_id_t watch_id,1380bool silently_continue) {1381return StopInfoSP(1382new StopInfoWatchpoint(thread, watch_id, silently_continue));1383}13841385StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,1386const char *description,1387std::optional<int> code) {1388thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);1389return StopInfoSP(new StopInfoUnixSignal(thread, signo, description, code));1390}13911392StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {1393return StopInfoSP(new StopInfoTrace(thread));1394}13951396StopInfoSP StopInfo::CreateStopReasonWithPlan(1397ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp,1398ExpressionVariableSP expression_variable_sp) {1399return StopInfoSP(new StopInfoThreadPlan(plan_sp, return_valobj_sp,1400expression_variable_sp));1401}14021403StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread,1404const char *description) {1405return StopInfoSP(new StopInfoException(thread, description));1406}14071408StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,1409const char *description) {1410return StopInfoSP(new StopInfoProcessorTrace(thread, description));1411}14121413StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {1414return StopInfoSP(new StopInfoExec(thread));1415}14161417StopInfoSP StopInfo::CreateStopReasonFork(Thread &thread,1418lldb::pid_t child_pid,1419lldb::tid_t child_tid) {1420return StopInfoSP(new StopInfoFork(thread, child_pid, child_tid));1421}142214231424StopInfoSP StopInfo::CreateStopReasonVFork(Thread &thread,1425lldb::pid_t child_pid,1426lldb::tid_t child_tid) {1427return StopInfoSP(new StopInfoVFork(thread, child_pid, child_tid));1428}14291430StopInfoSP StopInfo::CreateStopReasonVForkDone(Thread &thread) {1431return StopInfoSP(new StopInfoVForkDone(thread));1432}14331434ValueObjectSP StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) {1435if (stop_info_sp &&1436stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {1437StopInfoThreadPlan *plan_stop_info =1438static_cast<StopInfoThreadPlan *>(stop_info_sp.get());1439return plan_stop_info->GetReturnValueObject();1440} else1441return ValueObjectSP();1442}14431444ExpressionVariableSP StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) {1445if (stop_info_sp &&1446stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {1447StopInfoThreadPlan *plan_stop_info =1448static_cast<StopInfoThreadPlan *>(stop_info_sp.get());1449return plan_stop_info->GetExpressionVariable();1450} else1451return ExpressionVariableSP();1452}14531454lldb::ValueObjectSP1455StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,1456lldb::addr_t *crashing_address) {1457if (!stop_info_sp) {1458return ValueObjectSP();1459}14601461const char *description = stop_info_sp->GetDescription();1462if (!description) {1463return ValueObjectSP();1464}14651466ThreadSP thread_sp = stop_info_sp->GetThread();1467if (!thread_sp) {1468return ValueObjectSP();1469}14701471StackFrameSP frame_sp =1472thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);14731474if (!frame_sp) {1475return ValueObjectSP();1476}14771478const char address_string[] = "address=";14791480const char *address_loc = strstr(description, address_string);1481if (!address_loc) {1482return ValueObjectSP();1483}14841485address_loc += (sizeof(address_string) - 1);14861487uint64_t address = strtoull(address_loc, nullptr, 0);1488if (crashing_address) {1489*crashing_address = address;1490}14911492return frame_sp->GuessValueForAddress(address);1493}149414951496