summaryrefslogtreecommitdiffstats
path: root/lldb/source/Target/StopInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Target/StopInfo.cpp')
-rw-r--r--lldb/source/Target/StopInfo.cpp2042
1 files changed, 959 insertions, 1083 deletions
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 68db6654d5d..294ccf366ca 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -13,1255 +13,1131 @@
// 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()
-{
+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;
}
-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;
+ return !all_internal;
+ }
}
-
- 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);
- }
+ 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());
+ } 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.swap(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;
- }
+ bool callback_says_stop;
- void
- PerformAction(Event *event_ptr) override
- {
- if (!m_should_perform_action)
- return;
- m_should_perform_action = false;
+ // 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.
- ThreadSP thread_sp (m_thread_wp.lock());
+ Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
+ bool old_async = debugger.GetAsyncExecution();
+ debugger.SetAsyncExecution(true);
- if (thread_sp)
- {
- Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_STEP);
+ callback_says_stop = bp_loc_sp->InvokeCallback(&context);
- 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;
+ 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(Process *p, Watchpoint *w) : process(p), watchpoint(w) {
+ if (process && watchpoint) {
+ const bool notify = false;
+ watchpoint->TurnOnEphemeralMode();
+ process->DisableWatchpoint(watchpoint, notify);
+ }
+ }
- ~WatchpointSentry()
- {
- if (process && watchpoint)
- {
- if (!watchpoint->IsDisabledDuringEphemeralMode())
- {
- const bool notify = false;
- process->EnableWatchpoint(watchpoint, notify);
- }
- watchpoint->TurnOffEphemeralMode();
- }
+ ~WatchpointSentry() {
+ if (process && watchpoint) {
+ if (!watchpoint->IsDisabledDuringEphemeralMode()) {
+ const bool notify = false;
+ process->EnableWatchpoint(watchpoint, notify);
}
-
- 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)
- {
+ watchpoint->TurnOffEphemeralMode();
+ }
}
- ~StopInfoWatchpoint() override = default;
+ private:
+ Process *process;
+ Watchpoint *watchpoint;
+ };
- StopReason
- GetStopReason() const override
- {
- return eStopReasonWatchpoint;
- }
+ 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) {}
- 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();
+ ~StopInfoWatchpoint() override = default;
+
+ 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();
+ }
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)
+ 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());
+
+ 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;
+
+ 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());
+
{
- 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);
+ // 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);
+ }
}
- else
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ }
+ }
- if (log)
- log->Printf ("Process::%s could not find watchpoint location id: %" PRId64 "...",
- __FUNCTION__, GetValue());
+ /*
+ * 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();
+ }
+ }
+ // 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;
+ }
}
- 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;
-
- 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();
- }
- }
+ // 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();
+ }
- // 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;
- }
- }
+ } else {
+ Log *log_process(
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- // 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();
- }
-
- }
- 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);
- 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;
- }
+ 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() override = default;
+ StopInfoUnixSignal(Thread &thread, int signo, const char *description)
+ : StopInfo(thread, signo) {
+ SetDescription(description);
+ }
- StopReason
- GetStopReason() const override
- {
- return eStopReasonSignal;
- }
+ ~StopInfoUnixSignal() override = default;
- 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;
- }
+ StopReason GetStopReason() const override { return eStopReasonSignal; }
- 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 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;
+ }
- // 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;
+ 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;
}
-
- 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);
- }
+ 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);
}
-
- 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.swap(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;
+ const char *GetDescription() override {
+ if (m_description.empty()) {
+ StreamString strm;
+ m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief);
+ m_description.swap(strm.GetString());
}
-
- ExpressionVariableSP
- GetExpressionVariable()
- {
- return m_expression_variable_sp;
- }
-
+ 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();
- }
+StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,
+ lldb::addr_t *crashing_address) {
+ if (!stop_info_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);
+ 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);
}
OpenPOWER on IntegriCloud