diff options
Diffstat (limited to 'lldb')
-rw-r--r-- | lldb/include/lldb/API/SBProcess.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/Target/Process.h | 13 | ||||
-rw-r--r-- | lldb/source/API/SBProcess.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectProcess.cpp | 101 | ||||
-rw-r--r-- | lldb/source/Interpreter/CommandObject.cpp | 1 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h | 2 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp | 9 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h | 2 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp | 45 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h | 5 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 16 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h | 2 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 32 |
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; |