summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/include/lldb/API/SBProcess.h3
-rw-r--r--lldb/include/lldb/Target/Process.h13
-rw-r--r--lldb/source/API/SBProcess.cpp10
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp101
-rw-r--r--lldb/source/Interpreter/CommandObject.cpp1
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp10
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h2
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp9
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h2
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp45
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp16
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h2
-rw-r--r--lldb/source/Target/Process.cpp32
14 files changed, 221 insertions, 30 deletions
diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h
index 73ef89d207d..288d7d0290d 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -205,6 +205,9 @@ public:
Detach ();
lldb::SBError
+ Detach (bool keep_stopped);
+
+ lldb::SBError
Signal (int signal);
void
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 82e668fe732..090b7593444 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -91,6 +91,12 @@ public:
void
SetStopOnSharedLibraryEvents (bool stop);
+
+ bool
+ GetDetachKeepsStopped () const;
+
+ void
+ SetDetachKeepsStopped (bool keep_stopped);
};
typedef std::shared_ptr<ProcessProperties> ProcessPropertiesSP;
@@ -1943,11 +1949,14 @@ public:
/// This function is not meant to be overridden by Process
/// subclasses.
///
+ /// @param[in] keep_stopped
+ /// If true, don't resume the process on detach.
+ ///
/// @return
/// Returns an error object.
//------------------------------------------------------------------
Error
- Detach ();
+ Detach (bool keep_stopped);
//------------------------------------------------------------------
/// Kills the process and shuts down all threads that were spawned
@@ -2334,7 +2343,7 @@ public:
/// false otherwise.
//------------------------------------------------------------------
virtual Error
- DoDetach ()
+ DoDetach (bool keep_stopped)
{
Error error;
error.SetErrorStringWithFormat("error: %s does not support detaching from processes", GetShortPluginName());
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index ba45ce567d1..f04fed22843 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -786,12 +786,20 @@ SBProcess::Kill ()
SBError
SBProcess::Detach ()
{
+ // FIXME: This should come from a process default.
+ bool keep_stopped = false;
+ Detach (keep_stopped);
+}
+
+SBError
+SBProcess::Detach (bool keep_stopped)
+{
SBError sb_error;
ProcessSP process_sp(GetSP());
if (process_sp)
{
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- sb_error.SetError (process_sp->Detach());
+ sb_error.SetError (process_sp->Detach(keep_stopped));
}
else
sb_error.SetErrorString ("SBProcess is invalid");
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 2221514d902..7ad5f7be935 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -75,7 +75,8 @@ protected:
{
if (process->GetShouldDetach())
{
- Error detach_error (process->Detach());
+ bool keep_stopped = false;
+ Error detach_error (process->Detach(keep_stopped));
if (detach_error.Success())
{
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -903,6 +904,68 @@ CommandObjectProcessContinue::CommandOptions::g_option_table[] =
class CommandObjectProcessDetach : public CommandObjectParsed
{
public:
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter)
+ {
+ OptionParsingStarting ();
+ }
+
+ ~CommandOptions ()
+ {
+ }
+
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 's':
+ bool tmp_result;
+ bool success;
+ tmp_result = Args::StringToBoolean(option_arg, false, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg);
+ else
+ {
+ if (tmp_result)
+ m_keep_stopped = eLazyBoolYes;
+ else
+ m_keep_stopped = eLazyBoolNo;
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_keep_stopped = eLazyBoolCalculate;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ LazyBool m_keep_stopped;
+ };
CommandObjectProcessDetach (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
@@ -911,7 +974,8 @@ public:
"process detach",
eFlagRequiresProcess |
eFlagTryTargetAPILock |
- eFlagProcessMustBeLaunched)
+ eFlagProcessMustBeLaunched),
+ m_options(interpreter)
{
}
@@ -919,13 +983,35 @@ public:
{
}
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+
protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
Process *process = m_exe_ctx.GetProcessPtr();
result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
- Error error (process->Detach());
+ // FIXME: This will be a Command Option:
+ bool keep_stopped;
+ if (m_options.m_keep_stopped == eLazyBoolCalculate)
+ {
+ // Check the process default:
+ if (process->GetDetachKeepsStopped())
+ keep_stopped = true;
+ else
+ keep_stopped = false;
+ }
+ else if (m_options.m_keep_stopped == eLazyBoolYes)
+ keep_stopped = true;
+ else
+ keep_stopped = false;
+
+ Error error (process->Detach(keep_stopped));
if (error.Success())
{
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -938,6 +1024,15 @@ protected:
}
return result.Succeeded();
}
+
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectProcessDetach::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "keep-stopped", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
+{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index d2b2ce54875..68756050c6f 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -295,7 +295,6 @@ CommandObject::CheckRequirements (CommandReturnObject &result)
else
{
StateType state = process->GetState();
-
switch (state)
{
case eStateInvalid:
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 9e4cc568af5..f9b1055644b 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -507,12 +507,12 @@ ProcessKDP::DoHalt (bool &caused_stop)
}
Error
-ProcessKDP::DoDetach()
+ProcessKDP::DoDetach(bool keep_stopped)
{
Error error;
Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
if (log)
- log->Printf ("ProcessKDP::DoDetach()");
+ log->Printf ("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
if (m_comm.IsRunning())
{
@@ -525,7 +525,8 @@ ProcessKDP::DoDetach()
m_thread_list.DiscardThreadPlans();
- if (m_comm.IsConnected())
+ // If we are going to keep the target stopped, then don't send the disconnect message.
+ if (!keep_stopped && m_comm.IsConnected())
{
m_comm.SendRequestDisconnect();
@@ -554,7 +555,8 @@ Error
ProcessKDP::DoDestroy ()
{
// For KDP there really is no difference between destroy and detach
- return DoDetach();
+ bool keep_stopped = false;
+ return DoDetach(keep_stopped);
}
//------------------------------------------------------------------
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
index fba221ea5ed..9de262322ae 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
@@ -135,7 +135,7 @@ public:
DoHalt (bool &caused_stop);
virtual lldb_private::Error
- DoDetach ();
+ DoDetach (bool keep_stopped);
virtual lldb_private::Error
DoSignal (int signal);
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index 137fa46eddc..35c365f75c0 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -283,9 +283,16 @@ ProcessPOSIX::DoHalt(bool &caused_stop)
}
Error
-ProcessPOSIX::DoDetach()
+ProcessPOSIX::DoDetach(bool keep_stopped)
{
Error error;
+ if (keep_stopped)
+ {
+ // FIXME: If you want to implement keep_stopped on Linux,
+ // this would be the place to do it.
+ error.SetErrorString("Detaching with keep_stopped true is not currently supported on Linux.");
+ return error;
+ }
error = m_monitor->Detach();
if (error.Success())
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
index b16da3aca74..86c4ef33b3d 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -65,7 +65,7 @@ public:
DoHalt(bool &caused_stop);
virtual lldb_private::Error
- DoDetach();
+ DoDetach(bool keep_stopped);
virtual lldb_private::Error
DoSignal(int signal);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 9351b93761b..6657c2ca27b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -52,6 +52,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_supports_alloc_dealloc_memory (eLazyBoolCalculate),
m_supports_memory_region_info (eLazyBoolCalculate),
m_supports_watchpoint_support_info (eLazyBoolCalculate),
+ m_supports_detach_stay_stopped (eLazyBoolCalculate),
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
@@ -1396,10 +1397,48 @@ GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
return false;
}
-bool
-GDBRemoteCommunicationClient::Detach ()
+Error
+GDBRemoteCommunicationClient::Detach (bool keep_stopped)
{
- return SendPacket ("D", 1) > 0;
+ Error error;
+
+ if (keep_stopped)
+ {
+ if (m_supports_detach_stay_stopped == eLazyBoolCalculate)
+ {
+ char packet[64];
+ const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
+ assert (packet_len < sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ {
+ m_supports_detach_stay_stopped = eLazyBoolYes;
+ }
+ else
+ {
+ m_supports_detach_stay_stopped = eLazyBoolNo;
+ }
+ }
+
+ if (m_supports_detach_stay_stopped == eLazyBoolNo)
+ {
+ error.SetErrorString("Stays stopped not supported by this target.");
+ return error;
+ }
+ else
+ {
+ size_t num_sent = SendPacket ("D1", 2);
+ if (num_sent == 0)
+ error.SetErrorString ("Sending extended disconnect packet failed.");
+ }
+ }
+ else
+ {
+ size_t num_sent = SendPacket ("D", 1);
+ if (num_sent == 0)
+ error.SetErrorString ("Sending disconnect packet failed.");
+ }
+ return error;
}
Error
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 25b697de8ef..4075eebddec 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -199,8 +199,8 @@ public:
bool
DeallocateMemory (lldb::addr_t addr);
- bool
- Detach ();
+ lldb_private::Error
+ Detach (bool keep_stopped);
lldb_private::Error
GetMemoryRegionInfo (lldb::addr_t addr,
@@ -381,6 +381,7 @@ protected:
lldb_private::LazyBool m_supports_alloc_dealloc_memory;
lldb_private::LazyBool m_supports_memory_region_info;
lldb_private::LazyBool m_supports_watchpoint_support_info;
+ lldb_private::LazyBool m_supports_detach_stay_stopped;
lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 35e455d5f24..aa27ae8257e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1703,25 +1703,29 @@ ProcessGDBRemote::DoHalt (bool &caused_stop)
}
Error
-ProcessGDBRemote::DoDetach()
+ProcessGDBRemote::DoDetach(bool keep_stopped)
{
Error error;
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
- log->Printf ("ProcessGDBRemote::DoDetach()");
-
+ log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
+
DisableAllBreakpointSites ();
m_thread_list.DiscardThreadPlans();
- bool success = m_gdb_comm.Detach ();
+ error = m_gdb_comm.Detach (keep_stopped);
if (log)
{
- if (success)
+ if (error.Success())
log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
else
- log->PutCString ("ProcessGDBRemote::DoDetach() detach packet send failed");
+ log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>");
}
+
+ if (!error.Success())
+ return error;
+
// Sleep for one second to let the process get all detached...
StopAsyncThread ();
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index dc4ec561b03..5cbb13f4914 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -141,7 +141,7 @@ public:
DoHalt (bool &caused_stop);
virtual lldb_private::Error
- DoDetach ();
+ DoDetach (bool keep_stopped);
virtual bool
DetachRequiresHalt() { return true; }
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index f60adca741e..e0ea32a021e 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -101,6 +101,7 @@ g_properties[] =
{ "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, 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." },
{ "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, stop when a shared library is loaded or unloaded." },
+ { "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, detach will attempt to keep the process stopped." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
@@ -110,7 +111,8 @@ enum {
ePropertyIgnoreBreakpointsInExpressions,
ePropertyUnwindOnErrorInExpressions,
ePropertyPythonOSPluginPath,
- ePropertyStopOnSharedLibraryEvents
+ ePropertyStopOnSharedLibraryEvents,
+ ePropertyDetachKeepsStopped
};
ProcessProperties::ProcessProperties (bool is_global) :
@@ -213,6 +215,20 @@ ProcessProperties::SetStopOnSharedLibraryEvents (bool stop)
m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
}
+bool
+ProcessProperties::GetDetachKeepsStopped () const
+{
+ const uint32_t idx = ePropertyDetachKeepsStopped;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void
+ProcessProperties::SetDetachKeepsStopped (bool stop)
+{
+ const uint32_t idx = ePropertyDetachKeepsStopped;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
+}
+
void
ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
{
@@ -1096,7 +1112,11 @@ Process::Finalize()
case eStateCrashed:
case eStateSuspended:
if (GetShouldDetach())
- Detach();
+ {
+ // FIXME: This will have to be a process setting:
+ bool keep_stopped = false;
+ Detach(keep_stopped);
+ }
else
Destroy();
break;
@@ -3431,7 +3451,7 @@ Process::HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp)
}
Error
-Process::Detach ()
+Process::Detach (bool keep_stopped)
{
EventSP exit_event_sp;
Error error;
@@ -3458,12 +3478,16 @@ Process::Detach ()
}
}
- error = DoDetach();
+ error = DoDetach(keep_stopped);
if (error.Success())
{
DidDetach();
StopPrivateStateThread();
}
+ else
+ {
+ return error;
+ }
}
m_destroy_in_process = false;
OpenPOWER on IntegriCloud