[Lldb-commits] [lldb] r180749 - lldb_private::StopInfo now holds onto a ThreadWP (a std::weak_ptr<lldb_private::Thread>) in case the thread goes away while the stop info still exists.
Greg Clayton
gclayton at apple.com
Mon Apr 29 16:30:46 PDT 2013
Author: gclayton
Date: Mon Apr 29 18:30:46 2013
New Revision: 180749
URL: http://llvm.org/viewvc/llvm-project?rev=180749&view=rev
Log:
lldb_private::StopInfo now holds onto a ThreadWP (a std::weak_ptr<lldb_private::Thread>) in case the thread goes away while the stop info still exists.
Modified:
lldb/trunk/include/lldb/Target/StopInfo.h
lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp
lldb/trunk/source/Target/StopInfo.cpp
Modified: lldb/trunk/include/lldb/Target/StopInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StopInfo.h?rev=180749&r1=180748&r2=180749&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StopInfo.h (original)
+++ lldb/trunk/include/lldb/Target/StopInfo.h Mon Apr 29 18:30:46 2013
@@ -40,16 +40,10 @@ public:
bool
IsValid () const;
- Thread &
- GetThread()
- {
- return m_thread;
- }
-
- const Thread &
+ lldb::ThreadSP
GetThread() const
{
- return m_thread;
+ return m_thread_wp.lock();
}
// The value of the StopInfo depends on the StopReason.
@@ -184,7 +178,7 @@ protected:
//------------------------------------------------------------------
// Classes that inherit from StackID can see and modify these
//------------------------------------------------------------------
- Thread & m_thread; // The thread corresponding to the stop reason.
+ lldb::ThreadWP m_thread_wp; // The thread corresponding to the stop reason.
uint32_t m_stop_id; // The process stop ID for which this stop info is valid
uint32_t m_resume_id; // This is the resume ID when we made this stop ID.
uint64_t m_value; // A generic value that can be used for things pertaining to this stop info
Modified: lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp?rev=180749&r1=180748&r2=180749&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/StopInfoMachException.cpp Mon Apr 29 18:30:46 2013
@@ -34,7 +34,7 @@ StopInfoMachException::GetDescription ()
{
if (m_description.empty() && m_value != 0)
{
- ExecutionContext exe_ctx (m_thread.shared_from_this());
+ ExecutionContext exe_ctx (m_thread_wp.lock());
Target *target = exe_ctx.GetTargetPtr();
const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=180749&r1=180748&r2=180749&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Mon Apr 29 18:30:46 2013
@@ -35,7 +35,7 @@ using namespace lldb;
using namespace lldb_private;
StopInfo::StopInfo (Thread &thread, uint64_t value) :
- m_thread (thread),
+ m_thread_wp (thread.shared_from_this()),
m_stop_id (thread.GetProcess()->GetStopID()),
m_resume_id (thread.GetProcess()->GetResumeID()),
m_value (value),
@@ -47,41 +47,53 @@ StopInfo::StopInfo (Thread &thread, uint
bool
StopInfo::IsValid () const
{
- return m_thread.GetProcess()->GetStopID() == m_stop_id;
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
+ return thread_sp->GetProcess()->GetStopID() == m_stop_id;
+ return false;
}
void
StopInfo::MakeStopInfoValid ()
{
- m_stop_id = m_thread.GetProcess()->GetStopID();
- m_resume_id = m_thread.GetProcess()->GetResumeID();
+ 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 ()
{
- lldb::StateType ret_type = m_thread.GetProcess()->GetPrivateState();
- if (ret_type == eStateRunning)
- {
- return true;
- }
- else if (ret_type == eStateStopped)
+ ThreadSP thread_sp (m_thread_wp.lock());
+
+ if (thread_sp)
{
- // 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 = m_thread.GetProcess()->GetResumeID();
- uint32_t last_user_expression_id = m_thread.GetProcess()->GetLastUserExpressionResumeID ();
- if (curr_resume_id == m_resume_id)
+ lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState();
+ if (ret_type == eStateRunning)
{
- return false;
+ return true;
}
- else if (curr_resume_id > last_user_expression_id)
+ else if (ret_type == eStateStopped)
{
- return true;
+ // 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;
@@ -123,21 +135,26 @@ public:
StoreBPInfo();
}
- void StoreBPInfo ()
+ void
+ StoreBPInfo ()
{
- BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (m_value));
- if (bp_site_sp)
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
{
- if (bp_site_sp->GetNumberOfOwners() == 1)
+ BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
+ if (bp_site_sp)
{
- BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0);
- if (bp_loc_sp)
+ if (bp_site_sp->GetNumberOfOwners() == 1)
{
- m_break_id = bp_loc_sp->GetBreakpoint().GetID();
- m_was_one_shot = bp_loc_sp->GetBreakpoint().IsOneShot();
+ 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();
}
- m_address = bp_site_sp->GetLoadAddress();
}
}
@@ -154,47 +171,56 @@ public:
virtual bool
ShouldStopSynchronous (Event *event_ptr)
{
- if (!m_should_stop_is_valid)
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
{
- // Only check once if we should stop at a breakpoint
- BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (m_value));
- if (bp_site_sp)
- {
- ExecutionContext exe_ctx (m_thread.GetStackFrameAtIndex(0));
- StoppointCallbackContext context (event_ptr, exe_ctx, true);
- m_should_stop = bp_site_sp->ShouldStop (&context);
- }
- else
+ if (!m_should_stop_is_valid)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ // 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);
+ 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);
+ if (log)
+ log->Printf ("Process::%s could not find breakpoint site id: %" PRId64 "...", __FUNCTION__, m_value);
- m_should_stop = true;
+ m_should_stop = true;
+ }
+ m_should_stop_is_valid = true;
}
- m_should_stop_is_valid = true;
+ return m_should_stop;
}
- return m_should_stop;
+ return false;
}
virtual bool
ShouldNotify (Event *event_ptr)
{
- BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (m_value));
- if (bp_site_sp)
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
{
- bool all_internal = true;
-
- for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
+ BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
+ if (bp_site_sp)
{
- if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
+ bool all_internal = true;
+
+ for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
{
- all_internal = false;
- break;
+ if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
+ {
+ all_internal = false;
+ break;
+ }
}
+ return all_internal == false;
}
- return all_internal == false;
}
return true;
}
@@ -204,65 +230,69 @@ public:
{
if (m_description.empty())
{
- BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (m_value));
- if (bp_site_sp)
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_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())
+ BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
+ if (bp_site_sp)
{
- size_t num_owners = bp_site_sp->GetNumberOfOwners();
- for (size_t idx = 0; idx < num_owners; idx++)
+ 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())
{
- const char *kind = bp_site_sp->GetOwnerAtIndex(idx)->GetBreakpoint().GetBreakpointKind();
- if (kind != NULL)
+ size_t num_owners = bp_site_sp->GetNumberOfOwners();
+ for (size_t idx = 0; idx < num_owners; idx++)
{
- m_description.assign (kind);
- return kind;
+ const char *kind = bp_site_sp->GetOwnerAtIndex(idx)->GetBreakpoint().GetBreakpointKind();
+ if (kind != NULL)
+ {
+ m_description.assign (kind);
+ return kind;
+ }
}
}
+
+ strm.Printf("breakpoint ");
+ bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
+ m_description.swap (strm.GetString());
}
-
- 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)
+ else
{
- BreakpointSP break_sp = m_thread.GetProcess()->GetTarget().GetBreakpointByID(m_break_id);
- if (break_sp)
+ StreamString strm;
+ if (m_break_id != LLDB_INVALID_BREAK_ID)
{
- if (break_sp->IsInternal())
+ BreakpointSP break_sp = thread_sp->GetProcess()->GetTarget().GetBreakpointByID(m_break_id);
+ if (break_sp)
{
- const char *kind = break_sp->GetBreakpointKind();
- if (kind)
- strm.Printf ("internal %s breakpoint(%d).", kind, m_break_id);
+ 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 ("internal breakpoint(%d).", m_break_id);
- }
+ {
+ strm.Printf ("breakpoint %d.", m_break_id);
+ }
+ }
else
{
- strm.Printf ("breakpoint %d.", m_break_id);
+ 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_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());
}
- 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 m_description.c_str();
@@ -285,186 +315,191 @@ protected:
return;
m_should_perform_action = false;
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
-
- if (!m_thread.IsValid())
- {
- // This shouldn't ever happen, but just in case, don't do more harm.
- log->Printf ("PerformAction got called with an invalid thread.");
- m_should_stop = true;
- m_should_stop_is_valid = true;
- return;
- }
-
- BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (m_value));
-
- if (bp_site_sp)
+ ThreadSP thread_sp (m_thread_wp.lock());
+
+ if (thread_sp)
{
- size_t num_owners = bp_site_sp->GetNumberOfOwners();
-
- if (num_owners == 0)
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+ if (!thread_sp->IsValid())
{
+ // This shouldn't ever happen, but just in case, don't do more harm.
+ log->Printf ("PerformAction got called with an invalid thread.");
m_should_stop = true;
+ m_should_stop_is_valid = true;
+ return;
}
- else
+
+ BreakpointSiteSP bp_site_sp (thread_sp->GetProcess()->GetBreakpointSiteList().FindByID (m_value));
+
+ if (bp_site_sp)
{
- // We go through each location, and test first its 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;
-
- ExecutionContext exe_ctx (m_thread.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.
+ size_t num_owners = bp_site_sp->GetNumberOfOwners();
- 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;
+ if (num_owners == 0)
+ {
+ m_should_stop = true;
}
-
- StoppointCallbackContext context (event_ptr, exe_ctx, false);
-
- // Let's copy the breakpoint locations 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;
- for (size_t j = 0; j < num_owners; j++)
- site_locations.Add(bp_site_sp->GetOwnerAtIndex(j));
-
- for (size_t j = 0; j < num_owners; j++)
+ else
{
- lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
+ // We go through each location, and test first its 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.
- // 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(&m_thread))
- continue;
-
- // First 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() != NULL)
+ m_should_stop = false;
+
+ ExecutionContext exe_ctx (thread_sp->GetStackFrameAtIndex(0));
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process->GetModIDRef().IsLastResumeForUserExpression())
{
- Error condition_error;
- bool condition_says_stop = bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);
+ // 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.
- if (!condition_error.Success())
+ 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)
{
- 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();
- // If the condition fails to be parsed or run, we should stop.
- condition_says_stop = true;
+ 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
{
- if (!condition_says_stop)
- continue;
+ 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;
}
-
- 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 = m_thread.CalculateTarget()->GetDebugger();
- bool old_async = debugger.GetAsyncExecution();
- debugger.SetAsyncExecution (true);
- callback_says_stop = bp_loc_sp->InvokeCallback (&context);
+ StoppointCallbackContext context (event_ptr, exe_ctx, false);
- debugger.SetAsyncExecution (old_async);
+ // Let's copy the breakpoint locations 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.
- 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())
+ BreakpointLocationCollection site_locations;
+ for (size_t j = 0; j < num_owners; j++)
+ site_locations.Add(bp_site_sp->GetOwnerAtIndex(j));
+
+ for (size_t j = 0; j < num_owners; j++)
{
- m_thread.GetProcess()->GetTarget().RemoveBreakpointByID (bp_loc_sp->GetBreakpoint().GetID());
- }
+ lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
- // 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 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()))
+ continue;
+
+ // First 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() != NULL)
+ {
+ 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();
+ // If the condition fails to be parsed or run, we should stop.
+ condition_says_stop = true;
+ }
+ else
+ {
+ if (!condition_says_stop)
+ 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;
+ // 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));
+ }
+ 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_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);
}
- if (log)
- log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
}
private:
@@ -563,24 +598,27 @@ protected:
if (m_should_stop_is_valid)
return m_should_stop;
- WatchpointSP wp_sp =
- m_thread.CalculateTarget()->GetWatchpointList().FindByID(GetValue());
- if (wp_sp)
- {
- // Check if we should stop at a watchpoint.
- ExecutionContext exe_ctx (m_thread.GetStackFrameAtIndex(0));
- StoppointCallbackContext context (event_ptr, exe_ctx, true);
- m_should_stop = wp_sp->ShouldStop (&context);
- }
- else
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ 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 = true;
+ }
}
m_should_stop_is_valid = true;
return m_should_stop;
@@ -603,155 +641,158 @@ protected:
// this code. Also by default we're going to stop, so set that here.
m_should_stop = true;
- WatchpointSP wp_sp =
- m_thread.CalculateTarget()->GetWatchpointList().FindByID(GetValue());
- if (wp_sp)
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
{
- ExecutionContext exe_ctx (m_thread.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 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)
+ 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());
+
{
- uint32_t num; bool wp_triggers_after;
- if (process->GetWatchpointSupportInfo(num, wp_triggers_after).Success())
+ // 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)
{
- if (!wp_triggers_after)
+ uint32_t num; bool wp_triggers_after;
+ if (process->GetWatchpointSupportInfo(num, wp_triggers_after).Success())
{
- ThreadPlan *new_plan = m_thread.QueueThreadPlanForStepSingleInstruction(false, // step-over
- false, // abort_other_plans
- true); // stop_other_threads
- new_plan->SetIsMasterPlan (true);
- new_plan->SetOkayToDiscard (false);
- process->GetThreadList().SetSelectedThreadByID (m_thread.GetID());
- process->Resume ();
- process->WaitForProcessToStop (NULL);
- process->GetThreadList().SetSelectedThreadByID (m_thread.GetID());
- MakeStopInfoValid(); // make sure we do not fail to stop because of the single-step taken above
+ if (!wp_triggers_after)
+ {
+ ThreadPlan *new_plan = thread_sp->QueueThreadPlanForStepSingleInstruction(false, // step-over
+ false, // abort_other_plans
+ true); // stop_other_threads
+ new_plan->SetIsMasterPlan (true);
+ new_plan->SetOkayToDiscard (false);
+ process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
+ process->Resume ();
+ process->WaitForProcessToStop (NULL);
+ process->GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
+ MakeStopInfoValid(); // make sure we do not fail to stop because of the single-step taken above
+ }
}
}
}
- }
- if (m_should_stop && wp_sp->GetConditionText() != NULL)
- {
- // 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.
- ExecutionResults result_code;
- ValueObjectSP result_value_sp;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
- Error error;
- result_code = ClangUserExpression::EvaluateWithError (exe_ctx,
- eExecutionPolicyOnlyWhenNeeded,
- lldb::eLanguageTypeUnknown,
- ClangUserExpression::eResultTypeAny,
- unwind_on_error,
- ignore_breakpoints,
- wp_sp->GetConditionText(),
- NULL,
- result_value_sp,
- error,
- true,
- ClangUserExpression::kDefaultTimeout);
- if (result_code == eExecutionCompleted)
+ if (m_should_stop && wp_sp->GetConditionText() != NULL)
{
- if (result_value_sp)
+ // 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.
+ ExecutionResults result_code;
+ ValueObjectSP result_value_sp;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
+ Error error;
+ result_code = ClangUserExpression::EvaluateWithError (exe_ctx,
+ eExecutionPolicyOnlyWhenNeeded,
+ lldb::eLanguageTypeUnknown,
+ ClangUserExpression::eResultTypeAny,
+ unwind_on_error,
+ ignore_breakpoints,
+ wp_sp->GetConditionText(),
+ NULL,
+ result_value_sp,
+ error,
+ true,
+ ClangUserExpression::kDefaultTimeout);
+ if (result_code == eExecutionCompleted)
{
- Scalar scalar_value;
- if (result_value_sp->ResolveValue (scalar_value))
+ if (result_value_sp)
{
- if (scalar_value.ULongLong(1) == 0)
+ Scalar scalar_value;
+ if (result_value_sp->ResolveValue (scalar_value))
{
- // 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;
+ 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("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.");
+ 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
- {
- 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;
+ // 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;
+ }
}
- }
-
- // 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)
+ // Finally, if we are going to stop, print out the new & old values:
+ if (m_should_stop)
{
- // We have been vetoed by the callback mechanism.
- m_should_stop = false;
+ 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();
}
+
}
- // Finally, if we are going to stop, print out the new & old values:
- if (m_should_stop)
+ else
{
- 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();
+ 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;
}
- 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:
@@ -789,13 +830,19 @@ public:
virtual bool
ShouldStopSynchronous (Event *event_ptr)
{
- return m_thread.GetProcess()->GetUnixSignals().GetShouldStop (m_value);
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
+ return thread_sp->GetProcess()->GetUnixSignals().GetShouldStop (m_value);
+ return false;
}
virtual bool
ShouldStop (Event *event_ptr)
{
- return m_thread.GetProcess()->GetUnixSignals().GetShouldStop (m_value);
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
+ return thread_sp->GetProcess()->GetUnixSignals().GetShouldStop (m_value);
+ return false;
}
@@ -803,24 +850,33 @@ public:
virtual bool
ShouldNotify (Event *event_ptr)
{
- bool should_notify = m_thread.GetProcess()->GetUnixSignals().GetShouldNotify (m_value);
- if (should_notify)
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
{
- StreamString strm;
- strm.Printf ("thread %d received signal: %s",
- m_thread.GetIndexID(),
- m_thread.GetProcess()->GetUnixSignals().GetSignalAsCString (m_value));
- Process::ProcessEventData::AddRestartedReason(event_ptr, strm.GetData());
+ 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 should_notify;
+ return true;
}
virtual void
WillResume (lldb::StateType resume_state)
{
- if (m_thread.GetProcess()->GetUnixSignals().GetShouldSuppress(m_value) == false)
- m_thread.SetResumeSignal(m_value);
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
+ {
+ if (thread_sp->GetProcess()->GetUnixSignals().GetShouldSuppress(m_value) == false)
+ thread_sp->SetResumeSignal(m_value);
+ }
}
virtual const char *
@@ -828,13 +884,17 @@ public:
{
if (m_description.empty())
{
- StreamString strm;
- const char *signal_name = m_thread.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());
+ 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();
}
@@ -1004,7 +1064,9 @@ protected:
if (m_performed_action)
return;
m_performed_action = true;
- m_thread.GetProcess()->DidExec();
+ ThreadSP thread_sp (m_thread_wp.lock());
+ if (thread_sp)
+ thread_sp->GetProcess()->DidExec();
}
bool m_performed_action;
More information about the lldb-commits
mailing list