brintos

brintos / llvm-project-archived public Read only

0
0
Text · 61.0 KiB · e9e534a Raw
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