mirror of
https://github.com/intel/llvm.git
synced 2026-01-17 06:40:01 +08:00
Recommitting r180831 with trivial fix - remember to return errors if you compute.
llvm-svn: 180898
This commit is contained in:
@@ -204,6 +204,9 @@ public:
|
||||
lldb::SBError
|
||||
Detach ();
|
||||
|
||||
lldb::SBError
|
||||
Detach (bool keep_stopped);
|
||||
|
||||
lldb::SBError
|
||||
Signal (int signal);
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -785,13 +785,21 @@ SBProcess::Kill ()
|
||||
|
||||
SBError
|
||||
SBProcess::Detach ()
|
||||
{
|
||||
// FIXME: This should come from a process default.
|
||||
bool keep_stopped = false;
|
||||
return 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");
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@@ -295,7 +295,6 @@ CommandObject::CheckRequirements (CommandReturnObject &result)
|
||||
else
|
||||
{
|
||||
StateType state = process->GetState();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case eStateInvalid:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1696,25 +1696,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 ();
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
DoHalt (bool &caused_stop);
|
||||
|
||||
virtual lldb_private::Error
|
||||
DoDetach ();
|
||||
DoDetach (bool keep_stopped);
|
||||
|
||||
virtual bool
|
||||
DetachRequiresHalt() { return true; }
|
||||
|
||||
@@ -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;
|
||||
@@ -3437,7 +3457,7 @@ Process::HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp)
|
||||
}
|
||||
|
||||
Error
|
||||
Process::Detach ()
|
||||
Process::Detach (bool keep_stopped)
|
||||
{
|
||||
EventSP exit_event_sp;
|
||||
Error error;
|
||||
@@ -3464,12 +3484,16 @@ Process::Detach ()
|
||||
}
|
||||
}
|
||||
|
||||
error = DoDetach();
|
||||
error = DoDetach(keep_stopped);
|
||||
if (error.Success())
|
||||
{
|
||||
DidDetach();
|
||||
StopPrivateStateThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
return error;
|
||||
}
|
||||
}
|
||||
m_destroy_in_process = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user