summaryrefslogtreecommitdiffstats
path: root/lldb/source/Target/Process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Target/Process.cpp')
-rw-r--r--lldb/source/Target/Process.cpp110
1 files changed, 89 insertions, 21 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index e95fbf89755..18493de1e63 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -97,6 +97,8 @@ g_properties[] =
{ "disable-memory-cache" , OptionValue::eTypeBoolean, false, DISABLE_MEM_CACHE_DEFAULT, NULL, NULL, "Disable reading and caching of memory in fixed-size units." },
{ "extra-startup-command", OptionValue::eTypeArray , false, OptionValue::eTypeString, NULL, NULL, "A list containing extra commands understood by the particular process plugin used. "
"For instance, to turn on debugserver logging set this to \"QSetLogging:bitmask=LOG_DEFAULT;\"" },
+ { "ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, breakpoints will be ignored during expression evaluation." },
+ { "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, errors in expression evaluation will unwind the stack back to the state before the call." },
{ "python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, NULL, NULL, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
@@ -104,6 +106,8 @@ g_properties[] =
enum {
ePropertyDisableMemCache,
ePropertyExtraStartCommand,
+ ePropertyIgnoreBreakpointsInExpressions,
+ ePropertyUnwindOnErrorInExpressions,
ePropertyPythonOSPluginPath
};
@@ -164,6 +168,35 @@ ProcessProperties::SetPythonOSPluginPath (const FileSpec &file)
m_collection_sp->SetPropertyAtIndexAsFileSpec(NULL, idx, file);
}
+
+bool
+ProcessProperties::GetIgnoreBreakpointsInExpressions () const
+{
+ const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void
+ProcessProperties::SetIgnoreBreakpointsInExpressions (bool ignore)
+{
+ const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore);
+}
+
+bool
+ProcessProperties::GetUnwindOnErrorInExpressions () const
+{
+ const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void
+ProcessProperties::SetUnwindOnErrorInExpressions (bool ignore)
+{
+ const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore);
+}
+
void
ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
{
@@ -1668,7 +1701,8 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
{
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
- bool unwind_on_error = true;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
StreamString expr;
expr.Printf("dlopen (\"%s\", 2)", path);
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
@@ -1678,6 +1712,7 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
lldb::eLanguageTypeUnknown,
ClangUserExpression::eResultTypeAny,
unwind_on_error,
+ ignore_breakpoints,
expr.GetData(),
prefix,
result_valobj_sp,
@@ -1743,7 +1778,8 @@ Process::UnloadImage (uint32_t image_token)
{
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
- bool unwind_on_error = true;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
StreamString expr;
expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
@@ -1753,6 +1789,7 @@ Process::UnloadImage (uint32_t image_token)
lldb::eLanguageTypeUnknown,
ClangUserExpression::eResultTypeAny,
unwind_on_error,
+ ignore_breakpoints,
expr.GetData(),
prefix,
result_valobj_sp,
@@ -4293,7 +4330,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
bool stop_others,
bool run_others,
- bool discard_on_error,
+ bool unwind_on_error,
+ bool ignore_breakpoints,
uint32_t timeout_usec,
Stream &errors)
{
@@ -4419,8 +4457,10 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
bool first_timeout = true;
bool do_resume = true;
+ bool handle_running_event = true;
const uint64_t default_one_thread_timeout_usec = 250000;
uint64_t computed_timeout = 0;
+ bool stopped_by_breakpoint = false;
// This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
// So don't call return anywhere within it.
@@ -4431,16 +4471,19 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// The only exception is if we get two running events with no intervening
// stop, which can happen, we will just wait for then next stop event.
- if (do_resume)
+ if (do_resume || handle_running_event)
{
// Do the initial resume and wait for the running event before going further.
- Error resume_error = PrivateResume ();
- if (!resume_error.Success())
+ if (do_resume)
{
- errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
- return_value = eExecutionSetupError;
- break;
+ Error resume_error = PrivateResume ();
+ if (!resume_error.Success())
+ {
+ errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
+ return_value = eExecutionSetupError;
+ break;
+ }
}
real_timeout = TimeValue::Now();
@@ -4526,6 +4569,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->PutCString ("Process::RunThreadPlan(): handled an extra running event.");
do_resume = true;
+ handle_running_event = true;
}
// Now wait for the process to stop again:
@@ -4601,10 +4645,24 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
else
{
- if (log)
- log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
-
- return_value = eExecutionInterrupted;
+ // Something restarted the target, so just wait for it to stop for real.
+ if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
+ {
+ if (log)
+ log->PutCString ("Process::RunThreadPlan(): Somebody stopped and then restarted, we'll continue waiting.");
+ keep_going = true;
+ do_resume = false;
+ handle_running_event = true;
+ }
+ else
+ {
+ if (log)
+ log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
+ if (stop_reason == eStopReasonBreakpoint)
+ return_value = eExecutionHitBreakpoint;
+ else
+ return_value = eExecutionInterrupted;
+ }
}
}
}
@@ -4619,6 +4677,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
case lldb::eStateRunning:
do_resume = false;
keep_going = true;
+ handle_running_event = false;
break;
default:
@@ -4815,7 +4874,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
}
-
} // END WAIT LOOP
// If we had to start up a temporary private state thread to run this thread plan, shut it down now.
@@ -4832,15 +4890,22 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
- // Restore the thread state if we are going to discard the plan execution.
+ // Restore the thread state if we are going to discard the plan execution. There are three cases where this
+ // could happen:
+ // 1) The execution successfully completed
+ // 2) We hit a breakpoint, and ignore_breakpoints was true
+ // 3) We got some other error, and discard_on_error was true
+ bool should_unwind = (return_value == eExecutionInterrupted && unwind_on_error)
+ || (return_value == eExecutionHitBreakpoint && ignore_breakpoints);
- if (return_value == eExecutionCompleted || discard_on_error)
+ if (return_value == eExecutionCompleted
+ || should_unwind)
{
thread_plan_sp->RestoreThreadState();
}
// Now do some processing on the results of the run:
- if (return_value == eExecutionInterrupted)
+ if (return_value == eExecutionInterrupted || return_value == eExecutionHitBreakpoint)
{
if (log)
{
@@ -4933,7 +4998,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
}
- if (discard_on_error && thread_plan_sp)
+ if (should_unwind && thread_plan_sp)
{
if (log)
log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
@@ -4951,7 +5016,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->PutCString("Process::RunThreadPlan(): execution set up error.");
- if (discard_on_error && thread_plan_sp)
+ if (unwind_on_error && thread_plan_sp)
{
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
thread_plan_sp->SetPrivate (orig_plan_private);
@@ -4975,10 +5040,10 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
- if (discard_on_error && thread_plan_sp)
+ if (unwind_on_error && thread_plan_sp)
{
if (log)
- log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause discard_on_error is set.");
+ log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set.");
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
thread_plan_sp->SetPrivate (orig_plan_private);
}
@@ -5037,6 +5102,9 @@ Process::ExecutionResultAsCString (ExecutionResults result)
case eExecutionInterrupted:
result_name = "eExecutionInterrupted";
break;
+ case eExecutionHitBreakpoint:
+ result_name = "eExecutionHitBreakpoint";
+ break;
case eExecutionSetupError:
result_name = "eExecutionSetupError";
break;
OpenPOWER on IntegriCloud