diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/StopInfo.cpp')
| -rw-r--r-- | contrib/llvm/tools/lldb/source/Target/StopInfo.cpp | 2044 | 
1 files changed, 1003 insertions, 1041 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp index 7c244363ffd2..23dea41f61fb 100644 --- a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp +++ b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp @@ -13,1209 +13,1171 @@  // Other libraries and framework includes  // Project includes -#include "lldb/Target/StopInfo.h" -#include "lldb/Core/Log.h"  #include "lldb/Breakpoint/Breakpoint.h"  #include "lldb/Breakpoint/BreakpointLocation.h"  #include "lldb/Breakpoint/StoppointCallbackContext.h"  #include "lldb/Breakpoint/Watchpoint.h"  #include "lldb/Core/Debugger.h" +#include "lldb/Core/Log.h"  #include "lldb/Core/StreamString.h"  #include "lldb/Core/ValueObject.h"  #include "lldb/Expression/UserExpression.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Thread.h"  #include "lldb/Target/ThreadPlan.h" -#include "lldb/Target/Process.h"  #include "lldb/Target/UnixSignals.h"  using namespace lldb;  using namespace lldb_private; -StopInfo::StopInfo (Thread &thread, uint64_t value) : -    m_thread_wp (thread.shared_from_this()), -    m_stop_id (thread.GetProcess()->GetStopID()), -    m_resume_id (thread.GetProcess()->GetResumeID()), -    m_value (value), -    m_description (), -    m_override_should_notify (eLazyBoolCalculate), -    m_override_should_stop (eLazyBoolCalculate), -    m_extended_info() -{ -} - -bool -StopInfo::IsValid () const -{ -    ThreadSP thread_sp (m_thread_wp.lock()); -    if (thread_sp) -        return thread_sp->GetProcess()->GetStopID() == m_stop_id; -    return false; +StopInfo::StopInfo(Thread &thread, uint64_t value) +    : m_thread_wp(thread.shared_from_this()), +      m_stop_id(thread.GetProcess()->GetStopID()), +      m_resume_id(thread.GetProcess()->GetResumeID()), m_value(value), +      m_description(), m_override_should_notify(eLazyBoolCalculate), +      m_override_should_stop(eLazyBoolCalculate), m_extended_info() {} + +bool StopInfo::IsValid() const { +  ThreadSP thread_sp(m_thread_wp.lock()); +  if (thread_sp) +    return thread_sp->GetProcess()->GetStopID() == m_stop_id; +  return false;  } -void -StopInfo::MakeStopInfoValid () -{ -    ThreadSP thread_sp (m_thread_wp.lock()); -    if (thread_sp) -    { -        m_stop_id = thread_sp->GetProcess()->GetStopID(); -        m_resume_id = thread_sp->GetProcess()->GetResumeID(); -    } +void StopInfo::MakeStopInfoValid() { +  ThreadSP thread_sp(m_thread_wp.lock()); +  if (thread_sp) { +    m_stop_id = thread_sp->GetProcess()->GetStopID(); +    m_resume_id = thread_sp->GetProcess()->GetResumeID(); +  }  } -bool -StopInfo::HasTargetRunSinceMe () -{ -    ThreadSP thread_sp (m_thread_wp.lock()); - -    if (thread_sp) -    { -        lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState(); -        if (ret_type == eStateRunning) -        { -            return true; -        } -        else if (ret_type == eStateStopped) -        { -            // This is a little tricky.  We want to count "run and stopped again before you could -            // ask this question as a "TRUE" answer to HasTargetRunSinceMe.  But we don't want to  -            // include any running of the target done for expressions.  So we track both resumes, -            // and resumes caused by expressions, and check if there are any resumes NOT caused -            // by expressions. -             -            uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID(); -            uint32_t last_user_expression_id = thread_sp->GetProcess()->GetLastUserExpressionResumeID (); -            if (curr_resume_id == m_resume_id) -            { -                return false; -            } -            else if (curr_resume_id > last_user_expression_id) -            { -                return true; -            } -        } +bool StopInfo::HasTargetRunSinceMe() { +  ThreadSP thread_sp(m_thread_wp.lock()); + +  if (thread_sp) { +    lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState(); +    if (ret_type == eStateRunning) { +      return true; +    } else if (ret_type == eStateStopped) { +      // This is a little tricky.  We want to count "run and stopped again +      // before you could +      // ask this question as a "TRUE" answer to HasTargetRunSinceMe.  But we +      // don't want to +      // include any running of the target done for expressions.  So we track +      // both resumes, +      // and resumes caused by expressions, and check if there are any resumes +      // NOT caused +      // by expressions. + +      uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID(); +      uint32_t last_user_expression_id = +          thread_sp->GetProcess()->GetLastUserExpressionResumeID(); +      if (curr_resume_id == m_resume_id) { +        return false; +      } else if (curr_resume_id > last_user_expression_id) { +        return true; +      }      } -    return false; +  } +  return false;  }  //----------------------------------------------------------------------  // StopInfoBreakpoint  //---------------------------------------------------------------------- -namespace lldb_private -{ -class StopInfoBreakpoint : public StopInfo -{ +namespace lldb_private { +class StopInfoBreakpoint : public StopInfo {  public: -    StopInfoBreakpoint (Thread &thread, break_id_t break_id) : -        StopInfo (thread, break_id), -        m_should_stop (false), -        m_should_stop_is_valid (false), -        m_should_perform_action (true), -        m_address (LLDB_INVALID_ADDRESS), -        m_break_id(LLDB_INVALID_BREAK_ID), -        m_was_one_shot (false) -    { -        StoreBPInfo(); +  StopInfoBreakpoint(Thread &thread, break_id_t break_id) +      : StopInfo(thread, break_id), m_should_stop(false), +        m_should_stop_is_valid(false), m_should_perform_action(true), +        m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID), +        m_was_one_shot(false) { +    StoreBPInfo(); +  } + +  StopInfoBreakpoint(Thread &thread, break_id_t break_id, bool should_stop) +      : StopInfo(thread, break_id), m_should_stop(should_stop), +        m_should_stop_is_valid(true), m_should_perform_action(true), +        m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID), +        m_was_one_shot(false) { +    StoreBPInfo(); +  } + +  ~StopInfoBreakpoint() override = default; + +  void StoreBPInfo() { +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) { +      BreakpointSiteSP bp_site_sp( +          thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value)); +      if (bp_site_sp) { +        if (bp_site_sp->GetNumberOfOwners() == 1) { +          BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0); +          if (bp_loc_sp) { +            m_break_id = bp_loc_sp->GetBreakpoint().GetID(); +            m_was_one_shot = bp_loc_sp->GetBreakpoint().IsOneShot(); +          } +        } +        m_address = bp_site_sp->GetLoadAddress(); +      }      } - -    StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) : -        StopInfo (thread, break_id), -        m_should_stop (should_stop), -        m_should_stop_is_valid (true), -        m_should_perform_action (true), -        m_address (LLDB_INVALID_ADDRESS), -        m_break_id(LLDB_INVALID_BREAK_ID), -        m_was_one_shot (false) -    { -        StoreBPInfo(); +  } + +  bool IsValidForOperatingSystemThread(Thread &thread) override { +    ProcessSP process_sp(thread.GetProcess()); +    if (process_sp) { +      BreakpointSiteSP bp_site_sp( +          process_sp->GetBreakpointSiteList().FindByID(m_value)); +      if (bp_site_sp) +        return bp_site_sp->ValidForThisThread(&thread);      } - -    ~StopInfoBreakpoint() override = default; - -    void -    StoreBPInfo () -    { -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -        { -            BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value)); -            if (bp_site_sp) -            { -                if (bp_site_sp->GetNumberOfOwners() == 1) -                { -                    BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0); -                    if (bp_loc_sp) -                    { -                        m_break_id = bp_loc_sp->GetBreakpoint().GetID(); -                        m_was_one_shot = bp_loc_sp->GetBreakpoint().IsOneShot(); -                    } -                } -                m_address = bp_site_sp->GetLoadAddress(); -            } +    return false; +  } + +  StopReason GetStopReason() const override { return eStopReasonBreakpoint; } + +  bool ShouldStopSynchronous(Event *event_ptr) override { +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) { +      if (!m_should_stop_is_valid) { +        // Only check once if we should stop at a breakpoint +        BreakpointSiteSP bp_site_sp( +            thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value)); +        if (bp_site_sp) { +          ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); +          StoppointCallbackContext context(event_ptr, exe_ctx, true); +          bp_site_sp->BumpHitCounts(); +          m_should_stop = bp_site_sp->ShouldStop(&context); +        } else { +          Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + +          if (log) +            log->Printf( +                "Process::%s could not find breakpoint site id: %" PRId64 "...", +                __FUNCTION__, m_value); + +          m_should_stop = true;          } +        m_should_stop_is_valid = true; +      } +      return m_should_stop;      } - -    bool -    IsValidForOperatingSystemThread(Thread &thread) override -    { -        ProcessSP process_sp (thread.GetProcess()); -        if (process_sp) -        { -            BreakpointSiteSP bp_site_sp (process_sp->GetBreakpointSiteList().FindByID (m_value)); -            if (bp_site_sp) -                return bp_site_sp->ValidForThisThread (&thread); +    return false; +  } + +  bool DoShouldNotify(Event *event_ptr) override { +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) { +      BreakpointSiteSP bp_site_sp( +          thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value)); +      if (bp_site_sp) { +        bool all_internal = true; + +        for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) { +          if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) { +            all_internal = false; +            break; +          }          } -        return false; -    } - -    StopReason -    GetStopReason() const override -    { -        return eStopReasonBreakpoint; +        return !all_internal; +      }      } - -    bool -    ShouldStopSynchronous(Event *event_ptr) override -    { -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -        { -            if (!m_should_stop_is_valid) -            { -                // Only check once if we should stop at a breakpoint -                BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value)); -                if (bp_site_sp) -                { -                    ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0)); -                    StoppointCallbackContext context (event_ptr, exe_ctx, true); -                    bp_site_sp->BumpHitCounts(); -                    m_should_stop = bp_site_sp->ShouldStop (&context); -                } +    return true; +  } + +  const char *GetDescription() override { +    if (m_description.empty()) { +      ThreadSP thread_sp(m_thread_wp.lock()); +      if (thread_sp) { +        BreakpointSiteSP bp_site_sp( +            thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value)); +        if (bp_site_sp) { +          StreamString strm; +          // If we have just hit an internal breakpoint, and it has a kind +          // description, print that instead of the +          // full breakpoint printing: +          if (bp_site_sp->IsInternal()) { +            size_t num_owners = bp_site_sp->GetNumberOfOwners(); +            for (size_t idx = 0; idx < num_owners; idx++) { +              const char *kind = bp_site_sp->GetOwnerAtIndex(idx) +                                     ->GetBreakpoint() +                                     .GetBreakpointKind(); +              if (kind != nullptr) { +                m_description.assign(kind); +                return kind; +              } +            } +          } + +          strm.Printf("breakpoint "); +          bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief); +          m_description = strm.GetString(); +        } else { +          StreamString strm; +          if (m_break_id != LLDB_INVALID_BREAK_ID) { +            BreakpointSP break_sp = +                thread_sp->GetProcess()->GetTarget().GetBreakpointByID( +                    m_break_id); +            if (break_sp) { +              if (break_sp->IsInternal()) { +                const char *kind = break_sp->GetBreakpointKind(); +                if (kind) +                  strm.Printf("internal %s breakpoint(%d).", kind, m_break_id);                  else -                { -                    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - -                    if (log) -                        log->Printf ("Process::%s could not find breakpoint site id: %" PRId64 "...", __FUNCTION__, m_value); - -                    m_should_stop = true; -                } -                m_should_stop_is_valid = true; +                  strm.Printf("internal breakpoint(%d).", m_break_id); +              } else { +                strm.Printf("breakpoint %d.", m_break_id); +              } +            } else { +              if (m_was_one_shot) +                strm.Printf("one-shot breakpoint %d", m_break_id); +              else +                strm.Printf("breakpoint %d which has been deleted.", +                            m_break_id);              } -            return m_should_stop; +          } else if (m_address == LLDB_INVALID_ADDRESS) +            strm.Printf("breakpoint site %" PRIi64 +                        " which has been deleted - unknown address", +                        m_value); +          else +            strm.Printf("breakpoint site %" PRIi64 +                        " which has been deleted - was at 0x%" PRIx64, +                        m_value, m_address); + +          m_description = strm.GetString();          } -        return false; +      }      } +    return m_description.c_str(); +  } -    bool -    DoShouldNotify(Event *event_ptr) override -    { -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -        { -            BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value)); -            if (bp_site_sp) -            { -                bool all_internal = true; - -                for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) -                { -                    if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) -                    { -                        all_internal = false; -                        break; -                    } +protected: +  bool ShouldStop(Event *event_ptr) override { +    // This just reports the work done by PerformAction or the synchronous stop. +    // It should +    // only ever get called after they have had a chance to run. +    assert(m_should_stop_is_valid); +    return m_should_stop; +  } + +  void PerformAction(Event *event_ptr) override { +    if (!m_should_perform_action) +      return; +    m_should_perform_action = false; + +    ThreadSP thread_sp(m_thread_wp.lock()); + +    if (thread_sp) { +      Log *log = lldb_private::GetLogIfAnyCategoriesSet( +          LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_STEP); + +      if (!thread_sp->IsValid()) { +        // This shouldn't ever happen, but just in case, don't do more harm. +        if (log) { +          log->Printf("PerformAction got called with an invalid thread."); +        } +        m_should_stop = true; +        m_should_stop_is_valid = true; +        return; +      } + +      BreakpointSiteSP bp_site_sp( +          thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value)); +      std::unordered_set<break_id_t> precondition_breakpoints; + +      if (bp_site_sp) { +        // Let's copy the owners list out of the site and store them in a local +        // list.  That way if +        // one of the breakpoint actions changes the site, then we won't be +        // operating on a bad list. +        BreakpointLocationCollection site_locations; +        size_t num_owners = bp_site_sp->CopyOwnersList(site_locations); + +        if (num_owners == 0) { +          m_should_stop = true; +        } else { +          // We go through each location, and test first its precondition - this +          // overrides everything.  Note, +          // we only do this once per breakpoint - not once per location... +          // Then check the condition.  If the condition says to stop, +          // then we run the callback for that location.  If that callback says +          // to stop as well, then +          // we set m_should_stop to true; we are going to stop. +          // But we still want to give all the breakpoints whose conditions say +          // we are going to stop a +          // chance to run their callbacks. +          // Of course if any callback restarts the target by putting "continue" +          // in the callback, then +          // we're going to restart, without running the rest of the callbacks. +          // And in this case we will +          // end up not stopping even if another location said we should stop. +          // But that's better than not +          // running all the callbacks. + +          m_should_stop = false; + +          // We don't select threads as we go through them testing breakpoint +          // conditions and running commands. +          // So we need to set the thread for expression evaluation here: +          ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp); + +          ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); +          Process *process = exe_ctx.GetProcessPtr(); +          if (process->GetModIDRef().IsLastResumeForUserExpression()) { +            // If we are in the middle of evaluating an expression, don't run +            // asynchronous breakpoint commands or +            // expressions.  That could lead to infinite recursion if the +            // command or condition re-calls the function +            // with this breakpoint. +            // TODO: We can keep a list of the breakpoints we've seen while +            // running expressions in the nested +            // PerformAction calls that can arise when the action runs a +            // function that hits another breakpoint, +            // and only stop running commands when we see the same breakpoint +            // hit a second time. + +            m_should_stop_is_valid = true; +            if (log) +              log->Printf("StopInfoBreakpoint::PerformAction - Hit a " +                          "breakpoint while running an expression," +                          " not running commands to avoid recursion."); +            bool ignoring_breakpoints = +                process->GetIgnoreBreakpointsInExpressions(); +            if (ignoring_breakpoints) { +              m_should_stop = false; +              // Internal breakpoints will always stop. +              for (size_t j = 0; j < num_owners; j++) { +                lldb::BreakpointLocationSP bp_loc_sp = +                    bp_site_sp->GetOwnerAtIndex(j); +                if (bp_loc_sp->GetBreakpoint().IsInternal()) { +                  m_should_stop = true; +                  break;                  } -                return !all_internal; +              } +            } else { +              m_should_stop = true; +            } +            if (log) +              log->Printf("StopInfoBreakpoint::PerformAction - in expression, " +                          "continuing: %s.", +                          m_should_stop ? "true" : "false"); +            process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf( +                "Warning: hit breakpoint while " +                "running function, skipping commands and conditions to prevent " +                "recursion."); +            return; +          } + +          StoppointCallbackContext context(event_ptr, exe_ctx, false); + +          // For safety's sake let's also grab an extra reference to the +          // breakpoint owners of the locations we're +          // going to examine, since the locations are going to have to get back +          // to their breakpoints, and the +          // locations don't keep their owners alive.  I'm just sticking the +          // BreakpointSP's in a vector since +          // I'm only using it to locally increment their retain counts. + +          std::vector<lldb::BreakpointSP> location_owners; + +          for (size_t j = 0; j < num_owners; j++) { +            BreakpointLocationSP loc(site_locations.GetByIndex(j)); +            location_owners.push_back(loc->GetBreakpoint().shared_from_this()); +          } + +          for (size_t j = 0; j < num_owners; j++) { +            lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j); + +            // If another action disabled this breakpoint or its location, then +            // don't run the actions. +            if (!bp_loc_sp->IsEnabled() || +                !bp_loc_sp->GetBreakpoint().IsEnabled()) +              continue; + +            // The breakpoint site may have many locations associated with it, +            // not all of them valid for +            // this thread.  Skip the ones that aren't: +            if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) { +              if (log) { +                StreamString s; +                bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief); +                log->Printf("Breakpoint %s hit on thread 0x%llx but it was not " +                            "for this thread, continuing.", +                            s.GetData(), static_cast<unsigned long long>( +                                             thread_sp->GetID())); +              } +              continue;              } -        } -        return true; -    } -    const char * -    GetDescription() override -    { -        if (m_description.empty()) -        { -            ThreadSP thread_sp (m_thread_wp.lock()); -            if (thread_sp) -            { -                BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value)); -                if (bp_site_sp) -                { -                    StreamString strm; -                    // If we have just hit an internal breakpoint, and it has a kind description, print that instead of the -                    // full breakpoint printing: -                    if (bp_site_sp->IsInternal()) -                    { -                        size_t num_owners = bp_site_sp->GetNumberOfOwners(); -                        for (size_t idx = 0; idx < num_owners; idx++) -                        { -                            const char *kind = bp_site_sp->GetOwnerAtIndex(idx)->GetBreakpoint().GetBreakpointKind(); -                            if (kind != nullptr) -                            { -                                m_description.assign (kind); -                                return kind; -                            } -                        } -                    } - -                    strm.Printf("breakpoint "); -                    bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief); -                    m_description.swap (strm.GetString()); +            // First run the precondition, but since the precondition is per +            // breakpoint, only run it once +            // per breakpoint. +            std::pair<std::unordered_set<break_id_t>::iterator, bool> result = +                precondition_breakpoints.insert( +                    bp_loc_sp->GetBreakpoint().GetID()); +            if (!result.second) +              continue; + +            bool precondition_result = +                bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context); +            if (!precondition_result) +              continue; + +            // Next run the condition for the breakpoint.  If that says we +            // should stop, then we'll run +            // the callback for the breakpoint.  If the callback says we +            // shouldn't stop that will win. + +            if (bp_loc_sp->GetConditionText() != nullptr) { +              Error condition_error; +              bool condition_says_stop = +                  bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error); + +              if (!condition_error.Success()) { +                Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); +                StreamSP error_sp = debugger.GetAsyncErrorStream(); +                error_sp->Printf("Stopped due to an error evaluating condition " +                                 "of breakpoint "); +                bp_loc_sp->GetDescription(error_sp.get(), +                                          eDescriptionLevelBrief); +                error_sp->Printf(": \"%s\"", bp_loc_sp->GetConditionText()); +                error_sp->EOL(); +                const char *err_str = +                    condition_error.AsCString("<Unknown Error>"); +                if (log) +                  log->Printf("Error evaluating condition: \"%s\"\n", err_str); + +                error_sp->PutCString(err_str); +                error_sp->EOL(); +                error_sp->Flush(); +              } else { +                if (log) { +                  StreamString s; +                  bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief); +                  log->Printf("Condition evaluated for breakpoint %s on thread " +                              "0x%llx conditon_says_stop: %i.", +                              s.GetData(), static_cast<unsigned long long>( +                                               thread_sp->GetID()), +                              condition_says_stop);                  } -                else -                { -                    StreamString strm; -                    if (m_break_id != LLDB_INVALID_BREAK_ID) -                    { -                        BreakpointSP break_sp = thread_sp->GetProcess()->GetTarget().GetBreakpointByID(m_break_id); -                        if (break_sp) -                        { -                            if (break_sp->IsInternal()) -                            { -                                const char *kind = break_sp->GetBreakpointKind(); -                                if (kind) -                                    strm.Printf ("internal %s breakpoint(%d).", kind, m_break_id); -                                else -                                    strm.Printf ("internal breakpoint(%d).", m_break_id); -                            } -                            else -                            { -                                strm.Printf ("breakpoint %d.", m_break_id); -                            } -                        }  -                        else -                        { -                            if (m_was_one_shot) -                                strm.Printf ("one-shot breakpoint %d", m_break_id); -                            else -                                strm.Printf ("breakpoint %d which has been deleted.", m_break_id); -                        } -                    } -                    else if (m_address == LLDB_INVALID_ADDRESS) -                        strm.Printf("breakpoint site %" PRIi64 " which has been deleted - unknown address", m_value); -                    else -                        strm.Printf("breakpoint site %" PRIi64 " which has been deleted - was at 0x%" PRIx64, m_value, m_address); - -                    m_description.swap (strm.GetString()); +                if (!condition_says_stop) { +                  // We don't want to increment the hit count of breakpoints if +                  // the condition fails. +                  // We've already bumped it by the time we get here, so undo +                  // the bump: +                  bp_loc_sp->UndoBumpHitCount(); +                  continue;                  } +              }              } -        } -        return m_description.c_str(); -    } -protected: -    bool -    ShouldStop(Event *event_ptr) override -    { -        // This just reports the work done by PerformAction or the synchronous stop.  It should -        // only ever get called after they have had a chance to run. -        assert (m_should_stop_is_valid); -        return m_should_stop; -    } - -    void -    PerformAction(Event *event_ptr) override -    { -        if (!m_should_perform_action) -            return; -        m_should_perform_action = false; +            bool callback_says_stop; -        ThreadSP thread_sp (m_thread_wp.lock()); +            // FIXME: For now the callbacks have to run in async mode - the +            // first time we restart we need +            // to get out of there.  So set it here. +            // When we figure out how to nest breakpoint hits then this will +            // change. -        if (thread_sp) -        { -            Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_STEP); +            Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger(); +            bool old_async = debugger.GetAsyncExecution(); +            debugger.SetAsyncExecution(true); -            if (!thread_sp->IsValid()) -            { -                // This shouldn't ever happen, but just in case, don't do more harm. -                if (log) -                { -                    log->Printf ("PerformAction got called with an invalid thread."); -                } -                m_should_stop = true; -                m_should_stop_is_valid = true; -                return; -            } +            callback_says_stop = bp_loc_sp->InvokeCallback(&context); -            BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value)); -            std::unordered_set<break_id_t> precondition_breakpoints; +            debugger.SetAsyncExecution(old_async); -            if (bp_site_sp) -            { -                // Let's copy the owners list out of the site and store them in a local list.  That way if -                // one of the breakpoint actions changes the site, then we won't be operating on a bad list. -                BreakpointLocationCollection site_locations; -                size_t num_owners = bp_site_sp->CopyOwnersList(site_locations); +            if (callback_says_stop) +              m_should_stop = true; -                if (num_owners == 0) -                { -                    m_should_stop = true; -                } -                else -                { -                    // We go through each location, and test first its precondition - this overrides everything.  Note, -                    // we only do this once per breakpoint - not once per location... -                    // Then check the condition.  If the condition says to stop, -                    // then we run the callback for that location.  If that callback says to stop as well, then  -                    // we set m_should_stop to true; we are going to stop. -                    // But we still want to give all the breakpoints whose conditions say we are going to stop a -                    // chance to run their callbacks. -                    // Of course if any callback restarts the target by putting "continue" in the callback, then  -                    // we're going to restart, without running the rest of the callbacks.  And in this case we will -                    // end up not stopping even if another location said we should stop.  But that's better than not -                    // running all the callbacks. - -                    m_should_stop = false; -                     -                    // We don't select threads as we go through them testing breakpoint conditions and running commands. -                    // So we need to set the thread for expression evaluation here: -                    ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp); - -                    ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0)); -                    Process *process  = exe_ctx.GetProcessPtr(); -                    if (process->GetModIDRef().IsLastResumeForUserExpression()) -                    { -                        // If we are in the middle of evaluating an expression, don't run asynchronous breakpoint commands or -                        // expressions.  That could lead to infinite recursion if the command or condition re-calls the function -                        // with this breakpoint. -                        // TODO: We can keep a list of the breakpoints we've seen while running expressions in the nested -                        // PerformAction calls that can arise when the action runs a function that hits another breakpoint, -                        // and only stop running commands when we see the same breakpoint hit a second time. - -                        m_should_stop_is_valid = true; -                        if (log) -                            log->Printf ("StopInfoBreakpoint::PerformAction - Hit a breakpoint while running an expression," -                                         " not running commands to avoid recursion."); -                        bool ignoring_breakpoints = process->GetIgnoreBreakpointsInExpressions(); -                        if (ignoring_breakpoints) -                        { -                            m_should_stop = false; -                            // Internal breakpoints will always stop.   -                            for (size_t j = 0; j < num_owners; j++) -                            { -                                lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); -                                if (bp_loc_sp->GetBreakpoint().IsInternal()) -                                { -                                    m_should_stop = true; -                                    break; -                                } -                            } -                        } -                        else -                        { -                            m_should_stop = true; -                        } -                        if (log) -                            log->Printf ("StopInfoBreakpoint::PerformAction - in expression, continuing: %s.", -                                         m_should_stop ? "true" : "false"); -                        process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: hit breakpoint while " -                                               "running function, skipping commands and conditions to prevent recursion."); -                        return; -                    } - -                    StoppointCallbackContext context (event_ptr, exe_ctx, false); - -                    // For safety's sake let's also grab an extra reference to the breakpoint owners of the locations we're -                    // going to examine, since the locations are going to have to get back to their breakpoints, and the -                    // locations don't keep their owners alive.  I'm just sticking the BreakpointSP's in a vector since -                    // I'm only using it to locally increment their retain counts. - -                    std::vector<lldb::BreakpointSP> location_owners; - -                    for (size_t j = 0; j < num_owners; j++) -                    { -                        BreakpointLocationSP loc(site_locations.GetByIndex(j)); -                        location_owners.push_back(loc->GetBreakpoint().shared_from_this()); - -                    } - -                    for (size_t j = 0; j < num_owners; j++) -                    { -                        lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j); - -                        // If another action disabled this breakpoint or its location, then don't run the actions. -                        if (!bp_loc_sp->IsEnabled() || !bp_loc_sp->GetBreakpoint().IsEnabled()) -                            continue; - -                        // The breakpoint site may have many locations associated with it, not all of them valid for -                        // this thread.  Skip the ones that aren't: -                        if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) -                        { -                            if (log) -                            { -                                StreamString s; -                                bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief); -                                log->Printf ("Breakpoint %s hit on thread 0x%llx but it was not for this thread, continuing.", -                                             s.GetData(), -                                             static_cast<unsigned long long>(thread_sp->GetID())); -                            } -                            continue; -                        } - -                        // First run the precondition, but since the precondition is per breakpoint, only run it once -                        // per breakpoint. -                        std::pair<std::unordered_set<break_id_t>::iterator, bool> result -                                = precondition_breakpoints.insert(bp_loc_sp->GetBreakpoint().GetID()); -                        if (!result.second) -                            continue; - -                        bool precondition_result = bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context); -                        if (!precondition_result) -                            continue; - -                        // Next run the condition for the breakpoint.  If that says we should stop, then we'll run -                        // the callback for the breakpoint.  If the callback says we shouldn't stop that will win.                     - -                        if (bp_loc_sp->GetConditionText() != nullptr) -                        { -                            Error condition_error; -                            bool condition_says_stop = bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error); - -                            if (!condition_error.Success()) -                            { -                                Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); -                                StreamSP error_sp = debugger.GetAsyncErrorStream (); -                                error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint "); -                                bp_loc_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); -                                error_sp->Printf (": \"%s\"", -                                                  bp_loc_sp->GetConditionText()); -                                error_sp->EOL(); -                                const char *err_str = condition_error.AsCString("<Unknown Error>"); -                                if (log) -                                    log->Printf("Error evaluating condition: \"%s\"\n", err_str); - -                                error_sp->PutCString (err_str); -                                error_sp->EOL(); -                                error_sp->Flush(); -                            } -                            else -                            { -                                if (log) -                                { -                                    StreamString s; -                                    bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief); -                                    log->Printf ("Condition evaluated for breakpoint %s on thread 0x%llx conditon_says_stop: %i.", -                                                 s.GetData(), -                                                 static_cast<unsigned long long>(thread_sp->GetID()), -                                                 condition_says_stop); -                                } -                                if (!condition_says_stop) -                                { -                                    // We don't want to increment the hit count of breakpoints if the condition fails. -                                    // We've already bumped it by the time we get here, so undo the bump: -                                    bp_loc_sp->UndoBumpHitCount(); -                                    continue; -                                } -                            } -                        } - -                        bool callback_says_stop; - -                        // FIXME: For now the callbacks have to run in async mode - the first time we restart we need -                        // to get out of there.  So set it here. -                        // When we figure out how to nest breakpoint hits then this will change. - -                        Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger(); -                        bool old_async = debugger.GetAsyncExecution(); -                        debugger.SetAsyncExecution (true); - -                        callback_says_stop = bp_loc_sp->InvokeCallback (&context); - -                        debugger.SetAsyncExecution (old_async); - -                        if (callback_says_stop) -                            m_should_stop = true; - -                        // If we are going to stop for this breakpoint, then remove the breakpoint. -                        if (callback_says_stop && bp_loc_sp && bp_loc_sp->GetBreakpoint().IsOneShot()) -                        { -                            thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID (bp_loc_sp->GetBreakpoint().GetID()); -                        } - -                        // Also make sure that the callback hasn't continued the target.   -                        // If it did, when we'll set m_should_start to false and get out of here. -                        if (HasTargetRunSinceMe ()) -                        { -                            m_should_stop = false; -                            break; -                        } -                    } -                } -                // We've figured out what this stop wants to do, so mark it as valid so we don't compute it again. -                m_should_stop_is_valid = true; +            // If we are going to stop for this breakpoint, then remove the +            // breakpoint. +            if (callback_says_stop && bp_loc_sp && +                bp_loc_sp->GetBreakpoint().IsOneShot()) { +              thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID( +                  bp_loc_sp->GetBreakpoint().GetID());              } -            else -            { -                m_should_stop = true; -                m_should_stop_is_valid = true; -                Log * log_process(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); -                if (log_process) -                    log_process->Printf ("Process::%s could not find breakpoint site id: %" PRId64 "...", __FUNCTION__, m_value); +            // Also make sure that the callback hasn't continued the target. +            // If it did, when we'll set m_should_start to false and get out of +            // here. +            if (HasTargetRunSinceMe()) { +              m_should_stop = false; +              break;              } -            if (log) -                log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); +          }          } +        // We've figured out what this stop wants to do, so mark it as valid so +        // we don't compute it again. +        m_should_stop_is_valid = true; +      } else { +        m_should_stop = true; +        m_should_stop_is_valid = true; +        Log *log_process( +            lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + +        if (log_process) +          log_process->Printf( +              "Process::%s could not find breakpoint site id: %" PRId64 "...", +              __FUNCTION__, m_value); +      } +      if (log) +        log->Printf("Process::%s returning from action with m_should_stop: %d.", +                    __FUNCTION__, m_should_stop);      } +  }  private: -    bool m_should_stop; -    bool m_should_stop_is_valid; -    bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions -                                  // etc. behind the users backs, we need to make sure we only REALLY perform the action once. -    lldb::addr_t m_address;       // We use this to capture the breakpoint site address when we create the StopInfo, -                                  // in case somebody deletes it between the time the StopInfo is made and the -                                  // description is asked for. -    lldb::break_id_t m_break_id; -    bool m_was_one_shot; +  bool m_should_stop; +  bool m_should_stop_is_valid; +  bool m_should_perform_action; // Since we are trying to preserve the "state" +                                // of the system even if we run functions +  // etc. behind the users backs, we need to make sure we only REALLY perform +  // the action once. +  lldb::addr_t m_address; // We use this to capture the breakpoint site address +                          // when we create the StopInfo, +  // in case somebody deletes it between the time the StopInfo is made and the +  // description is asked for. +  lldb::break_id_t m_break_id; +  bool m_was_one_shot;  };  //----------------------------------------------------------------------  // StopInfoWatchpoint  //---------------------------------------------------------------------- -class StopInfoWatchpoint : public StopInfo -{ +class StopInfoWatchpoint : public StopInfo {  public: -    // Make sure watchpoint is properly disabled and subsequently enabled while performing watchpoint actions. -    class WatchpointSentry { -    public: -        WatchpointSentry(Process *p, Watchpoint *w): -            process(p), -            watchpoint(w) -        { -            if (process && watchpoint) -            { -                const bool notify = false; -                watchpoint->TurnOnEphemeralMode(); -                process->DisableWatchpoint(watchpoint, notify); -            } +  // Make sure watchpoint is properly disabled and subsequently enabled while +  // performing watchpoint actions. +  class WatchpointSentry { +  public: +    WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),  +                     watchpoint_sp(w_sp) { +      if (process_sp && watchpoint_sp) { +        const bool notify = false; +        watchpoint_sp->TurnOnEphemeralMode(); +        process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); +        process_sp->AddPreResumeAction(SentryPreResumeAction, this); +      } +    } +     +    void DoReenable() { +      if (process_sp && watchpoint_sp) { +        bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode(); +        watchpoint_sp->TurnOffEphemeralMode(); +        const bool notify = false; +        if (was_disabled) { +          process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); +        } else { +          process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);          } +      } +    } +     +    ~WatchpointSentry() { +        DoReenable(); +        if (process_sp) +            process_sp->ClearPreResumeAction(SentryPreResumeAction, this); +    } +     +    static bool SentryPreResumeAction(void *sentry_void) { +        WatchpointSentry *sentry = (WatchpointSentry *) sentry_void; +        sentry->DoReenable(); +        return true; +    } -        ~WatchpointSentry() -        { -            if (process && watchpoint) -            { -                if (!watchpoint->IsDisabledDuringEphemeralMode()) -                { -                    const bool notify = false; -                    process->EnableWatchpoint(watchpoint, notify); -                } -                watchpoint->TurnOffEphemeralMode(); -            } -        } +  private: +    ProcessSP process_sp; +    WatchpointSP watchpoint_sp; +  }; -    private: -        Process *process; -        Watchpoint *watchpoint; -    }; - -    StopInfoWatchpoint (Thread &thread, break_id_t watch_id, lldb::addr_t watch_hit_addr) : -        StopInfo(thread, watch_id), -        m_should_stop(false), -        m_should_stop_is_valid(false), -        m_watch_hit_addr(watch_hit_addr) -    { -    } +  StopInfoWatchpoint(Thread &thread, break_id_t watch_id, +                     lldb::addr_t watch_hit_addr) +      : StopInfo(thread, watch_id), m_should_stop(false), +        m_should_stop_is_valid(false), m_watch_hit_addr(watch_hit_addr) {} -    ~StopInfoWatchpoint() override = default; +  ~StopInfoWatchpoint() override = default; -    StopReason -    GetStopReason() const override -    { -        return eStopReasonWatchpoint; -    } +  StopReason GetStopReason() const override { return eStopReasonWatchpoint; } -    const char * -    GetDescription() override -    { -        if (m_description.empty()) -        { -            StreamString strm; -            strm.Printf("watchpoint %" PRIi64, m_value); -            m_description.swap (strm.GetString()); -        } -        return m_description.c_str(); +  const char *GetDescription() override { +    if (m_description.empty()) { +      StreamString strm; +      strm.Printf("watchpoint %" PRIi64, m_value); +      m_description = strm.GetString();      } +    return m_description.c_str(); +  }  protected: -    bool -    ShouldStopSynchronous(Event *event_ptr) override -    { -        // ShouldStop() method is idempotent and should not affect hit count. -        // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent() -        // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()-> -        // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()-> -        // StopInfoWatchpoint::ShouldStop() and -        // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()-> -        // StopInfoWatchpoint::PerformAction(). -        if (m_should_stop_is_valid) -            return m_should_stop; - -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -        { -            WatchpointSP wp_sp (thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue())); -            if (wp_sp) -            { -                // Check if we should stop at a watchpoint. -                ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0)); -                StoppointCallbackContext context (event_ptr, exe_ctx, true); -                m_should_stop = wp_sp->ShouldStop (&context); -            } -            else -            { -                Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); +  bool ShouldStopSynchronous(Event *event_ptr) override { +    // ShouldStop() method is idempotent and should not affect hit count. +    // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent() +    // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()-> +    // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()-> +    // StopInfoWatchpoint::ShouldStop() and +    // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()-> +    // StopInfoWatchpoint::PerformAction(). +    if (m_should_stop_is_valid) +      return m_should_stop; + +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) { +      WatchpointSP wp_sp( +          thread_sp->CalculateTarget()->GetWatchpointList().FindByID( +              GetValue())); +      if (wp_sp) { +        // Check if we should stop at a watchpoint. +        ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); +        StoppointCallbackContext context(event_ptr, exe_ctx, true); +        m_should_stop = wp_sp->ShouldStop(&context); +      } else { +        Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + +        if (log) +          log->Printf( +              "Process::%s could not find watchpoint location id: %" PRId64 +              "...", +              __FUNCTION__, GetValue()); -                if (log) -                    log->Printf ("Process::%s could not find watchpoint location id: %" PRId64 "...", -                                 __FUNCTION__, GetValue()); - -                m_should_stop = true; -            } -        } -        m_should_stop_is_valid = true; -        return m_should_stop; -    } -     -    bool -    ShouldStop(Event *event_ptr) override -    { -        // This just reports the work done by PerformAction or the synchronous stop.  It should -        // only ever get called after they have had a chance to run. -        assert (m_should_stop_is_valid); -        return m_should_stop; +        m_should_stop = true; +      }      } +    m_should_stop_is_valid = true; +    return m_should_stop; +  } + +  bool ShouldStop(Event *event_ptr) override { +    // This just reports the work done by PerformAction or the synchronous stop. +    // It should +    // only ever get called after they have had a chance to run. +    assert(m_should_stop_is_valid); +    return m_should_stop; +  } + +  void PerformAction(Event *event_ptr) override { +    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS); +    // We're going to calculate if we should stop or not in some way during the +    // course of +    // this code.  Also by default we're going to stop, so set that here. +    m_should_stop = true; -    void -    PerformAction(Event *event_ptr) override -    { -        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS); -        // We're going to calculate if we should stop or not in some way during the course of -        // this code.  Also by default we're going to stop, so set that here. -        m_should_stop = true; -         -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -        { -            WatchpointSP wp_sp (thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue())); -            if (wp_sp) -            { -                ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0)); -                Process* process = exe_ctx.GetProcessPtr(); - -                // This sentry object makes sure the current watchpoint is disabled while performing watchpoint actions, -                // and it is then enabled after we are finished. -                WatchpointSentry sentry(process, wp_sp.get()); - -                { -                    // check if this process is running on an architecture where watchpoints trigger -                    // before the associated instruction runs. if so, disable the WP, single-step and then -                    // re-enable the watchpoint -                    if (process) -                    { -                        uint32_t num; -                        bool wp_triggers_after; -                        if (process->GetWatchpointSupportInfo(num, wp_triggers_after).Success()) -                        { -                            if (!wp_triggers_after) -                            { -                                StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo(); -                                assert (stored_stop_info_sp.get() == this); -                                 -                                ThreadPlanSP new_plan_sp(thread_sp->QueueThreadPlanForStepSingleInstruction(false, // step-over -                                                                                                            false,     // abort_other_plans -                                                                                                            true));    // stop_other_threads -                                new_plan_sp->SetIsMasterPlan (true); -                                new_plan_sp->SetOkayToDiscard (false); -                                new_plan_sp->SetPrivate (true); -                                process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID()); -                                process->ResumeSynchronous(nullptr); -                                process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID()); -                                thread_sp->SetStopInfo(stored_stop_info_sp); -                            } -                        } -                    } -                } - -                /* -                 * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For example: -                 * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', then -                 * watch exception is generated even when 'n' is read/written. To handle this case, -                 * server emulates the instruction at PC and finds the base address of the load/store -                 * instruction and appends it in the description of the stop-info packet. If watchpoint -                 * is not set on this address by user then this do not stop. -                */ -                if (m_watch_hit_addr != LLDB_INVALID_ADDRESS) -                { -                    WatchpointSP wp_hit_sp = thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress(m_watch_hit_addr); -                    if (!wp_hit_sp) -                    { -                        m_should_stop = false; -                        wp_sp->IncrementFalseAlarmsAndReviseHitCount(); -                    } -                } +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) { -                // TODO: This condition should be checked in the synchronous part of the watchpoint code -                // (Watchpoint::ShouldStop), so that we avoid pulling an event even if the watchpoint fails -                // the ignore count condition. It is moved here temporarily, because for archs with  -                // watchpoint_exceptions_received=before, the code in the previous lines takes care of moving -                // the inferior to next PC. We have to check the ignore count condition after this is done, -                // otherwise we will hit same watchpoint multiple times until we pass ignore condition, but we -                // won't actually be ignoring them. -                if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) -                    m_should_stop = false; - -                if (m_should_stop && wp_sp->GetConditionText() != nullptr) -                { -                    // We need to make sure the user sees any parse errors in their condition, so we'll hook the -                    // constructor errors up to the debugger's Async I/O. -                    ExpressionResults result_code; -                    EvaluateExpressionOptions expr_options; -                    expr_options.SetUnwindOnError(true); -                    expr_options.SetIgnoreBreakpoints(true); -                    ValueObjectSP result_value_sp; -                    Error error; -                    result_code = UserExpression::Evaluate(exe_ctx, -                                                           expr_options, -                                                           wp_sp->GetConditionText(), -                                                           nullptr, -                                                           result_value_sp, -                                                           error); -                                                             -                    if (result_code == eExpressionCompleted) -                    { -                        if (result_value_sp) -                        { -                            Scalar scalar_value; -                            if (result_value_sp->ResolveValue (scalar_value)) -                            { -                                if (scalar_value.ULongLong(1) == 0) -                                { -                                    // We have been vetoed.  This takes precedence over querying -                                    // the watchpoint whether it should stop (aka ignore count and -                                    // friends).  See also StopInfoWatchpoint::ShouldStop() as well -                                    // as Process::ProcessEventData::DoOnRemoval(). -                                    m_should_stop = false; -                                } -                                else -                                    m_should_stop = true; -                                if (log) -                                    log->Printf("Condition successfully evaluated, result is %s.\n",  -                                                m_should_stop ? "true" : "false"); -                            } -                            else -                            { -                                m_should_stop = true; -                                if (log) -                                    log->Printf("Failed to get an integer result from the expression."); -                            } -                        } -                    } -                    else -                    { -                        Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); -                        StreamSP error_sp = debugger.GetAsyncErrorStream (); -                        error_sp->Printf ("Stopped due to an error evaluating condition of watchpoint "); -                        wp_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief); -                        error_sp->Printf (": \"%s\"",  -                                          wp_sp->GetConditionText()); -                        error_sp->EOL(); -                        const char *err_str = error.AsCString("<Unknown Error>"); -                        if (log) -                            log->Printf("Error evaluating condition: \"%s\"\n", err_str); - -                        error_sp->PutCString (err_str); -                        error_sp->EOL();                        -                        error_sp->Flush(); -                        // If the condition fails to be parsed or run, we should stop. -                        m_should_stop = true; -                    } -                } +      WatchpointSP wp_sp( +          thread_sp->CalculateTarget()->GetWatchpointList().FindByID( +              GetValue()));       +      if (wp_sp) { +        ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); +        ProcessSP process_sp = exe_ctx.GetProcessSP(); -                // If the condition says to stop, we run the callback to further decide whether to stop. -                if (m_should_stop) -                { -                    StoppointCallbackContext context (event_ptr, exe_ctx, false); -                    bool stop_requested = wp_sp->InvokeCallback (&context); -                    // Also make sure that the callback hasn't continued the target.   -                    // If it did, when we'll set m_should_stop to false and get out of here. -                    if (HasTargetRunSinceMe ()) -                        m_should_stop = false; -                     -                    if (m_should_stop && !stop_requested) -                    { -                        // We have been vetoed by the callback mechanism. -                        m_should_stop = false; -                    } -                } -                // Finally, if we are going to stop, print out the new & old values: -                if (m_should_stop) -                { -                    wp_sp->CaptureWatchedValue(exe_ctx); -                     -                    Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); -                    StreamSP output_sp = debugger.GetAsyncOutputStream (); -                    wp_sp->DumpSnapshots(output_sp.get()); -                    output_sp->EOL(); -                    output_sp->Flush(); -                } -                 +        { +          // check if this process is running on an architecture where +          // watchpoints trigger +          // before the associated instruction runs. if so, disable the WP, +          // single-step and then +          // re-enable the watchpoint +          if (process_sp) { +            uint32_t num; +            bool wp_triggers_after; + +            if (process_sp->GetWatchpointSupportInfo(num, wp_triggers_after) +                    .Success()) { +              if (!wp_triggers_after) { +                // We need to preserve the watch_index before watchpoint  +                // is disable. Since Watchpoint::SetEnabled will clear the +                // watch index. +                // This will fix TestWatchpointIter failure +                Watchpoint *wp = wp_sp.get(); +                uint32_t watch_index = wp->GetHardwareIndex(); +                process_sp->DisableWatchpoint(wp, false); +                StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo(); +                assert(stored_stop_info_sp.get() == this); + +                ThreadPlanSP new_plan_sp( +                    thread_sp->QueueThreadPlanForStepSingleInstruction( +                        false,  // step-over +                        false,  // abort_other_plans +                        true)); // stop_other_threads +                new_plan_sp->SetIsMasterPlan(true); +                new_plan_sp->SetOkayToDiscard(false); +                new_plan_sp->SetPrivate(true); +                process_sp->GetThreadList().SetSelectedThreadByID( +                    thread_sp->GetID()); +                process_sp->ResumeSynchronous(nullptr); +                process_sp->GetThreadList().SetSelectedThreadByID( +                    thread_sp->GetID()); +                thread_sp->SetStopInfo(stored_stop_info_sp); +                process_sp->EnableWatchpoint(wp, false); +                wp->SetHardwareIndex(watch_index); +              }              } -            else -            { -                Log * log_process(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); +          } +        } + +        // This sentry object makes sure the current watchpoint is disabled +        // while performing watchpoint actions, +        // and it is then enabled after we are finished. +        WatchpointSentry sentry(process_sp, wp_sp); + +        /* +         * MIPS: Last 3bits of the watchpoint address are masked by the kernel. +         * For example: +         * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is +         * set at 'm', then +         * watch exception is generated even when 'n' is read/written. To handle +         * this case, +         * server emulates the instruction at PC and finds the base address of +         * the load/store +         * instruction and appends it in the description of the stop-info +         * packet. If watchpoint +         * is not set on this address by user then this do not stop. +        */ +        if (m_watch_hit_addr != LLDB_INVALID_ADDRESS) { +          WatchpointSP wp_hit_sp = +              thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress( +                  m_watch_hit_addr); +          if (!wp_hit_sp) { +            m_should_stop = false; +            wp_sp->IncrementFalseAlarmsAndReviseHitCount(); +          } +        } -                if (log_process) -                    log_process->Printf ("Process::%s could not find watchpoint id: %" PRId64 "...", __FUNCTION__, m_value); +        // TODO: This condition should be checked in the synchronous part of the +        // watchpoint code +        // (Watchpoint::ShouldStop), so that we avoid pulling an event even if +        // the watchpoint fails +        // the ignore count condition. It is moved here temporarily, because for +        // archs with +        // watchpoint_exceptions_received=before, the code in the previous lines +        // takes care of moving +        // the inferior to next PC. We have to check the ignore count condition +        // after this is done, +        // otherwise we will hit same watchpoint multiple times until we pass +        // ignore condition, but we +        // won't actually be ignoring them. +        if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) +          m_should_stop = false; + +        Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); + +        if (m_should_stop && wp_sp->GetConditionText() != nullptr) { +          // We need to make sure the user sees any parse errors in their +          // condition, so we'll hook the constructor errors up to the +          // debugger's Async I/O. +          ExpressionResults result_code; +          EvaluateExpressionOptions expr_options; +          expr_options.SetUnwindOnError(true); +          expr_options.SetIgnoreBreakpoints(true); +          ValueObjectSP result_value_sp; +          Error error; +          result_code = UserExpression::Evaluate( +              exe_ctx, expr_options, wp_sp->GetConditionText(), +              llvm::StringRef(), result_value_sp, error); + +          if (result_code == eExpressionCompleted) { +            if (result_value_sp) { +              Scalar scalar_value; +              if (result_value_sp->ResolveValue(scalar_value)) { +                if (scalar_value.ULongLong(1) == 0) { +                  // We have been vetoed.  This takes precedence over querying +                  // the watchpoint whether it should stop (aka ignore count and +                  // friends).  See also StopInfoWatchpoint::ShouldStop() as +                  // well as Process::ProcessEventData::DoOnRemoval(). +                  m_should_stop = false; +                } else +                  m_should_stop = true; +                if (log) +                  log->Printf( +                      "Condition successfully evaluated, result is %s.\n", +                      m_should_stop ? "true" : "false"); +              } else { +                m_should_stop = true; +                if (log) +                  log->Printf( +                      "Failed to get an integer result from the expression."); +              }              } +          } else { +            StreamSP error_sp = debugger.GetAsyncErrorStream(); +            error_sp->Printf( +                "Stopped due to an error evaluating condition of watchpoint "); +            wp_sp->GetDescription(error_sp.get(), eDescriptionLevelBrief); +            error_sp->Printf(": \"%s\"", wp_sp->GetConditionText()); +            error_sp->EOL(); +            const char *err_str = error.AsCString("<Unknown Error>");              if (log) -                log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); -             -            m_should_stop_is_valid = true; +              log->Printf("Error evaluating condition: \"%s\"\n", err_str); + +            error_sp->PutCString(err_str); +            error_sp->EOL(); +            error_sp->Flush(); +            // If the condition fails to be parsed or run, we should stop. +            m_should_stop = true; +          } +        } + +        // If the condition says to stop, we run the callback to further decide +        // whether to stop. +        if (m_should_stop) { +            // FIXME: For now the callbacks have to run in async mode - the +            // first time we restart we need +            // to get out of there.  So set it here. +            // When we figure out how to nest watchpoint hits then this will +            // change. + +          bool old_async = debugger.GetAsyncExecution(); +          debugger.SetAsyncExecution(true); +           +          StoppointCallbackContext context(event_ptr, exe_ctx, false); +          bool stop_requested = wp_sp->InvokeCallback(&context); +           +          debugger.SetAsyncExecution(old_async); +           +          // Also make sure that the callback hasn't continued the target. +          // If it did, when we'll set m_should_stop to false and get out of +          // here. +          if (HasTargetRunSinceMe()) +            m_should_stop = false; + +          if (m_should_stop && !stop_requested) { +            // We have been vetoed by the callback mechanism. +            m_should_stop = false; +          } +        } +        // Finally, if we are going to stop, print out the new & old values: +        if (m_should_stop) { +          wp_sp->CaptureWatchedValue(exe_ctx); + +          Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); +          StreamSP output_sp = debugger.GetAsyncOutputStream(); +          wp_sp->DumpSnapshots(output_sp.get()); +          output_sp->EOL(); +          output_sp->Flush();          } + +      } else { +        Log *log_process( +            lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + +        if (log_process) +          log_process->Printf( +              "Process::%s could not find watchpoint id: %" PRId64 "...", +              __FUNCTION__, m_value); +      } +      if (log) +        log->Printf("Process::%s returning from action with m_should_stop: %d.", +                    __FUNCTION__, m_should_stop); + +      m_should_stop_is_valid = true;      } -         +  } +  private: -    bool m_should_stop; -    bool m_should_stop_is_valid; -    lldb::addr_t m_watch_hit_addr; +  bool m_should_stop; +  bool m_should_stop_is_valid; +  lldb::addr_t m_watch_hit_addr;  };  //----------------------------------------------------------------------  // StopInfoUnixSignal  //---------------------------------------------------------------------- -class StopInfoUnixSignal : public StopInfo -{ +class StopInfoUnixSignal : public StopInfo {  public: -    StopInfoUnixSignal (Thread &thread, int signo, const char *description) : -        StopInfo (thread, signo) -    { -        SetDescription (description); -    } +  StopInfoUnixSignal(Thread &thread, int signo, const char *description) +      : StopInfo(thread, signo) { +    SetDescription(description); +  } -    ~StopInfoUnixSignal() override = default; +  ~StopInfoUnixSignal() override = default; -    StopReason -    GetStopReason() const override -    { -        return eStopReasonSignal; -    } +  StopReason GetStopReason() const override { return eStopReasonSignal; } -    bool -    ShouldStopSynchronous(Event *event_ptr) override -    { -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -            return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value); -        return false; -    } +  bool ShouldStopSynchronous(Event *event_ptr) override { +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) +      return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value); +    return false; +  } -    bool -    ShouldStop(Event *event_ptr) override -    { -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -            return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value); -        return false; +  bool ShouldStop(Event *event_ptr) override { +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) +      return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value); +    return false; +  } + +  // If should stop returns false, check if we should notify of this event +  bool DoShouldNotify(Event *event_ptr) override { +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) { +      bool should_notify = +          thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value); +      if (should_notify) { +        StreamString strm; +        strm.Printf( +            "thread %d received signal: %s", thread_sp->GetIndexID(), +            thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString( +                m_value)); +        Process::ProcessEventData::AddRestartedReason(event_ptr, +                                                      strm.GetData()); +      } +      return should_notify;      } - -    // If should stop returns false, check if we should notify of this event -    bool -    DoShouldNotify(Event *event_ptr) override -    { -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -        { -            bool should_notify = thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value); -            if (should_notify) -            { -                StreamString strm; -                strm.Printf ("thread %d received signal: %s", -                             thread_sp->GetIndexID(), -                             thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(m_value)); -                Process::ProcessEventData::AddRestartedReason(event_ptr, strm.GetData()); -            } -            return should_notify; -        } -        return true; +    return true; +  } + +  void WillResume(lldb::StateType resume_state) override { +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) { +      if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress( +              m_value)) +        thread_sp->SetResumeSignal(m_value);      } - -    void -    WillResume(lldb::StateType resume_state) override -    { -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -        { -            if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(m_value)) -                thread_sp->SetResumeSignal(m_value); -        } -    } - -    const char * -    GetDescription() override -    { -        if (m_description.empty()) -        { -            ThreadSP thread_sp (m_thread_wp.lock()); -            if (thread_sp) -            { -                StreamString strm; -                const char *signal_name = thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(m_value); -                if (signal_name) -                    strm.Printf("signal %s", signal_name); -                else -                    strm.Printf("signal %" PRIi64, m_value); -                m_description.swap (strm.GetString()); -            } -        } -        return m_description.c_str(); +  } + +  const char *GetDescription() override { +    if (m_description.empty()) { +      ThreadSP thread_sp(m_thread_wp.lock()); +      if (thread_sp) { +        StreamString strm; +        const char *signal_name = +            thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString( +                m_value); +        if (signal_name) +          strm.Printf("signal %s", signal_name); +        else +          strm.Printf("signal %" PRIi64, m_value); +        m_description = strm.GetString(); +      }      } +    return m_description.c_str(); +  }  };  //----------------------------------------------------------------------  // StopInfoTrace  //---------------------------------------------------------------------- -class StopInfoTrace : public StopInfo -{ +class StopInfoTrace : public StopInfo {  public: -    StopInfoTrace (Thread &thread) : -        StopInfo (thread, LLDB_INVALID_UID) -    { -    } +  StopInfoTrace(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {} -    ~StopInfoTrace() override = default; +  ~StopInfoTrace() override = default; -    StopReason -    GetStopReason() const override -    { -        return eStopReasonTrace; -    } +  StopReason GetStopReason() const override { return eStopReasonTrace; } -    const char * -    GetDescription() override -    { -        if (m_description.empty()) -            return "trace"; -        else -            return m_description.c_str(); -    } +  const char *GetDescription() override { +    if (m_description.empty()) +      return "trace"; +    else +      return m_description.c_str(); +  }  };  //----------------------------------------------------------------------  // StopInfoException  //---------------------------------------------------------------------- -class StopInfoException : public StopInfo -{ +class StopInfoException : public StopInfo {  public: -    StopInfoException (Thread &thread, const char *description) : -        StopInfo (thread, LLDB_INVALID_UID) -    { -        if (description) -            SetDescription (description); -    } +  StopInfoException(Thread &thread, const char *description) +      : StopInfo(thread, LLDB_INVALID_UID) { +    if (description) +      SetDescription(description); +  } -    ~StopInfoException() override = default; +  ~StopInfoException() override = default; -    StopReason -    GetStopReason() const override -    { -        return eStopReasonException; -    } -     -    const char * -    GetDescription() override -    { -        if (m_description.empty()) -            return "exception"; -        else -            return m_description.c_str(); -    } +  StopReason GetStopReason() const override { return eStopReasonException; } + +  const char *GetDescription() override { +    if (m_description.empty()) +      return "exception"; +    else +      return m_description.c_str(); +  }  };  //----------------------------------------------------------------------  // StopInfoThreadPlan  //---------------------------------------------------------------------- -class StopInfoThreadPlan : public StopInfo -{ +class StopInfoThreadPlan : public StopInfo {  public: -    StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp, ExpressionVariableSP &expression_variable_sp) : -        StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID), -        m_plan_sp (plan_sp), -        m_return_valobj_sp (return_valobj_sp), -        m_expression_variable_sp (expression_variable_sp) -    { -    } +  StopInfoThreadPlan(ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp, +                     ExpressionVariableSP &expression_variable_sp) +      : StopInfo(plan_sp->GetThread(), LLDB_INVALID_UID), m_plan_sp(plan_sp), +        m_return_valobj_sp(return_valobj_sp), +        m_expression_variable_sp(expression_variable_sp) {} -    ~StopInfoThreadPlan() override = default; +  ~StopInfoThreadPlan() override = default; -    StopReason -    GetStopReason() const override -    { -        return eStopReasonPlanComplete; -    } +  StopReason GetStopReason() const override { return eStopReasonPlanComplete; } -    const char * -    GetDescription() override -    { -        if (m_description.empty()) -        { -            StreamString strm;             -            m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief); -            m_description.swap (strm.GetString()); -        } -        return m_description.c_str(); -    } -     -    ValueObjectSP -    GetReturnValueObject() -    { -        return m_return_valobj_sp; -    } -     -    ExpressionVariableSP -    GetExpressionVariable() -    { -        return m_expression_variable_sp; +  const char *GetDescription() override { +    if (m_description.empty()) { +      StreamString strm; +      m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief); +      m_description = strm.GetString();      } -     +    return m_description.c_str(); +  } + +  ValueObjectSP GetReturnValueObject() { return m_return_valobj_sp; } + +  ExpressionVariableSP GetExpressionVariable() { +    return m_expression_variable_sp; +  } +  protected: -    bool -    ShouldStop(Event *event_ptr) override -    { -        if (m_plan_sp) -            return m_plan_sp->ShouldStop(event_ptr); -        else -            return StopInfo::ShouldStop(event_ptr); -    } +  bool ShouldStop(Event *event_ptr) override { +    if (m_plan_sp) +      return m_plan_sp->ShouldStop(event_ptr); +    else +      return StopInfo::ShouldStop(event_ptr); +  }  private: -    ThreadPlanSP m_plan_sp; -    ValueObjectSP m_return_valobj_sp; -    ExpressionVariableSP m_expression_variable_sp; +  ThreadPlanSP m_plan_sp; +  ValueObjectSP m_return_valobj_sp; +  ExpressionVariableSP m_expression_variable_sp;  }; -     -class StopInfoExec : public StopInfo -{ + +class StopInfoExec : public StopInfo {  public: -    StopInfoExec (Thread &thread) : -        StopInfo (thread, LLDB_INVALID_UID), -        m_performed_action (false) -    { -    } +  StopInfoExec(Thread &thread) +      : StopInfo(thread, LLDB_INVALID_UID), m_performed_action(false) {} -    ~StopInfoExec() override = default; +  ~StopInfoExec() override = default; -    StopReason -    GetStopReason() const override -    { -        return eStopReasonExec; -    } -     -    const char * -    GetDescription() override -    { -        return "exec"; -    } +  StopReason GetStopReason() const override { return eStopReasonExec; } + +  const char *GetDescription() override { return "exec"; }  protected: -    void -    PerformAction(Event *event_ptr) override -    { -        // Only perform the action once -        if (m_performed_action) -            return; -        m_performed_action = true; -        ThreadSP thread_sp (m_thread_wp.lock()); -        if (thread_sp) -            thread_sp->GetProcess()->DidExec(); -    } -     -    bool m_performed_action; +  void PerformAction(Event *event_ptr) override { +    // Only perform the action once +    if (m_performed_action) +      return; +    m_performed_action = true; +    ThreadSP thread_sp(m_thread_wp.lock()); +    if (thread_sp) +      thread_sp->GetProcess()->DidExec(); +  } + +  bool m_performed_action;  };  } // namespace lldb_private -StopInfoSP -StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id) -{ -    return StopInfoSP (new StopInfoBreakpoint (thread, break_id)); +StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread, +                                                          break_id_t break_id) { +  return StopInfoSP(new StopInfoBreakpoint(thread, break_id));  } -StopInfoSP -StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop) -{ -    return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop)); +StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread, +                                                          break_id_t break_id, +                                                          bool should_stop) { +  return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));  }  StopInfoSP -StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id, lldb::addr_t watch_hit_addr) -{ -    return StopInfoSP (new StopInfoWatchpoint (thread, watch_id, watch_hit_addr)); +StopInfo::CreateStopReasonWithWatchpointID(Thread &thread, break_id_t watch_id, +                                           lldb::addr_t watch_hit_addr) { +  return StopInfoSP(new StopInfoWatchpoint(thread, watch_id, watch_hit_addr));  } -StopInfoSP -StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo, const char *description) -{ -    return StopInfoSP (new StopInfoUnixSignal (thread, signo, description)); +StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo, +                                                const char *description) { +  return StopInfoSP(new StopInfoUnixSignal(thread, signo, description));  } -StopInfoSP -StopInfo::CreateStopReasonToTrace (Thread &thread) -{ -    return StopInfoSP (new StopInfoTrace (thread)); +StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) { +  return StopInfoSP(new StopInfoTrace(thread));  } -StopInfoSP -StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp, -                                    ValueObjectSP return_valobj_sp, -                                    ExpressionVariableSP expression_variable_sp) -{ -    return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp, expression_variable_sp)); +StopInfoSP StopInfo::CreateStopReasonWithPlan( +    ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp, +    ExpressionVariableSP expression_variable_sp) { +  return StopInfoSP(new StopInfoThreadPlan(plan_sp, return_valobj_sp, +                                           expression_variable_sp));  } -StopInfoSP -StopInfo::CreateStopReasonWithException (Thread &thread, const char *description) -{ -    return StopInfoSP (new StopInfoException (thread, description)); +StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread, +                                                   const char *description) { +  return StopInfoSP(new StopInfoException(thread, description));  } -StopInfoSP -StopInfo::CreateStopReasonWithExec (Thread &thread) -{ -    return StopInfoSP (new StopInfoExec (thread)); +StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) { +  return StopInfoSP(new StopInfoExec(thread));  } -ValueObjectSP -StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) -{ -    if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete) -    { -        StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get()); -        return plan_stop_info->GetReturnValueObject(); -    } -    else -        return ValueObjectSP(); +ValueObjectSP StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) { +  if (stop_info_sp && +      stop_info_sp->GetStopReason() == eStopReasonPlanComplete) { +    StopInfoThreadPlan *plan_stop_info = +        static_cast<StopInfoThreadPlan *>(stop_info_sp.get()); +    return plan_stop_info->GetReturnValueObject(); +  } else +    return ValueObjectSP();  } -ExpressionVariableSP -StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) -{ -    if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete) -    { -        StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get()); -        return plan_stop_info->GetExpressionVariable(); -    } -    else -        return ExpressionVariableSP(); +ExpressionVariableSP StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) { +  if (stop_info_sp && +      stop_info_sp->GetStopReason() == eStopReasonPlanComplete) { +    StopInfoThreadPlan *plan_stop_info = +        static_cast<StopInfoThreadPlan *>(stop_info_sp.get()); +    return plan_stop_info->GetExpressionVariable(); +  } else +    return ExpressionVariableSP(); +} + +lldb::ValueObjectSP +StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp, +                                 lldb::addr_t *crashing_address) { +  if (!stop_info_sp) { +    return ValueObjectSP(); +  } + +  const char *description = stop_info_sp->GetDescription(); +  if (!description) { +    return ValueObjectSP(); +  } + +  ThreadSP thread_sp = stop_info_sp->GetThread(); +  if (!thread_sp) { +    return ValueObjectSP(); +  } + +  StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + +  if (!frame_sp) { +    return ValueObjectSP(); +  } + +  const char address_string[] = "address="; + +  const char *address_loc = strstr(description, address_string); +  if (!address_loc) { +    return ValueObjectSP(); +  } + +  address_loc += (sizeof(address_string) - 1); + +  uint64_t address = strtoull(address_loc, 0, 0); +  if (crashing_address) { +    *crashing_address = address; +  } + +  return frame_sp->GuessValueForAddress(address);  }  | 
