forked from OSchip/llvm-project
Added an option to turn OFF the "detach on error" behavior that was added
to debugserver when launching processes. <rdar://problem/16216199> llvm-svn: 211658
This commit is contained in:
parent
ab8d0a0dd5
commit
106d02866d
|
@ -145,6 +145,12 @@ public:
|
|||
const char *
|
||||
GetLaunchEventData () const;
|
||||
|
||||
bool
|
||||
GetDetachOnError() const;
|
||||
|
||||
void
|
||||
SetDetachOnError(bool enable);
|
||||
|
||||
protected:
|
||||
friend class SBTarget;
|
||||
|
||||
|
|
|
@ -866,6 +866,21 @@ public:
|
|||
return m_event_data.c_str();
|
||||
}
|
||||
|
||||
void
|
||||
SetDetachOnError (bool enable)
|
||||
{
|
||||
if (enable)
|
||||
m_flags.Set(lldb::eLaunchFlagDetachOnError);
|
||||
else
|
||||
m_flags.Clear(lldb::eLaunchFlagDetachOnError);
|
||||
}
|
||||
|
||||
bool
|
||||
GetDetachOnError () const
|
||||
{
|
||||
return m_flags.Test(lldb::eLaunchFlagDetachOnError);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string m_working_dir;
|
||||
std::string m_plugin_name;
|
||||
|
@ -882,9 +897,9 @@ protected:
|
|||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// ProcessLaunchInfo
|
||||
// ProcessAttachInfo
|
||||
//
|
||||
// Describes any information that is required to launch a process.
|
||||
// Describes any information that is required to attach to a process.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class ProcessAttachInfo : public ProcessInstanceInfo
|
||||
|
@ -896,7 +911,8 @@ public:
|
|||
m_resume_count (0),
|
||||
m_wait_for_launch (false),
|
||||
m_ignore_existing (true),
|
||||
m_continue_once_attached (false)
|
||||
m_continue_once_attached (false),
|
||||
m_detach_on_error (true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -906,12 +922,14 @@ public:
|
|||
m_resume_count (0),
|
||||
m_wait_for_launch (false),
|
||||
m_ignore_existing (true),
|
||||
m_continue_once_attached (false)
|
||||
m_continue_once_attached (false),
|
||||
m_detach_on_error(true)
|
||||
{
|
||||
ProcessInfo::operator= (launch_info);
|
||||
SetProcessPluginName (launch_info.GetProcessPluginName());
|
||||
SetResumeCount (launch_info.GetResumeCount());
|
||||
SetHijackListener(launch_info.GetHijackListener());
|
||||
m_detach_on_error = launch_info.GetDetachOnError();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1014,7 +1032,18 @@ public:
|
|||
m_hijack_listener_sp = listener_sp;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GetDetachOnError () const
|
||||
{
|
||||
return m_detach_on_error;
|
||||
}
|
||||
|
||||
void
|
||||
SetDetachOnError (bool enable)
|
||||
{
|
||||
m_detach_on_error = enable;
|
||||
}
|
||||
|
||||
protected:
|
||||
lldb::ListenerSP m_hijack_listener_sp;
|
||||
std::string m_plugin_name;
|
||||
|
@ -1022,6 +1051,7 @@ protected:
|
|||
bool m_wait_for_launch;
|
||||
bool m_ignore_existing;
|
||||
bool m_continue_once_attached; // Supports the use-case scenario of immediately continuing the process once attached.
|
||||
bool m_detach_on_error; // If we are debugging remotely, instruct the stub to detach rather than killing the target on error.
|
||||
};
|
||||
|
||||
class ProcessLaunchCommandOptions : public Options
|
||||
|
|
|
@ -81,6 +81,12 @@ public:
|
|||
void
|
||||
SetDisableASLR (bool b);
|
||||
|
||||
bool
|
||||
GetDetachOnError () const;
|
||||
|
||||
void
|
||||
SetDetachOnError (bool b);
|
||||
|
||||
bool
|
||||
GetDisableSTDIO () const;
|
||||
|
||||
|
|
|
@ -39,16 +39,18 @@ namespace lldb {
|
|||
typedef enum LaunchFlags
|
||||
{
|
||||
eLaunchFlagNone = 0u,
|
||||
eLaunchFlagExec = (1u << 0), ///< Exec when launching and turn the calling process into a new process
|
||||
eLaunchFlagDebug = (1u << 1), ///< Stop as soon as the process launches to allow the process to be debugged
|
||||
eLaunchFlagStopAtEntry = (1u << 2), ///< Stop at the program entry point instead of auto-continuing when launching or attaching at entry point
|
||||
eLaunchFlagDisableASLR = (1u << 3), ///< Disable Address Space Layout Randomization
|
||||
eLaunchFlagDisableSTDIO = (1u << 4), ///< Disable stdio for inferior process (e.g. for a GUI app)
|
||||
eLaunchFlagLaunchInTTY = (1u << 5), ///< Launch the process in a new TTY if supported by the host
|
||||
eLaunchFlagLaunchInShell= (1u << 6), ///< Launch the process inside a shell to get shell expansion
|
||||
eLaunchFlagExec = (1u << 0), ///< Exec when launching and turn the calling process into a new process
|
||||
eLaunchFlagDebug = (1u << 1), ///< Stop as soon as the process launches to allow the process to be debugged
|
||||
eLaunchFlagStopAtEntry = (1u << 2), ///< Stop at the program entry point instead of auto-continuing when launching or attaching at entry point
|
||||
eLaunchFlagDisableASLR = (1u << 3), ///< Disable Address Space Layout Randomization
|
||||
eLaunchFlagDisableSTDIO = (1u << 4), ///< Disable stdio for inferior process (e.g. for a GUI app)
|
||||
eLaunchFlagLaunchInTTY = (1u << 5), ///< Launch the process in a new TTY if supported by the host
|
||||
eLaunchFlagLaunchInShell= (1u << 6), ///< Launch the process inside a shell to get shell expansion
|
||||
eLaunchFlagLaunchInSeparateProcessGroup = (1u << 7), ///< Launch the process in a separate process group
|
||||
eLaunchFlagsDontSetExitStatus = (1u << 8) ///< If you are going to hand the process off (e.g. to debugserver)
|
||||
///< set this flag so lldb & the handee don't race to set its exit status.
|
||||
eLaunchFlagDontSetExitStatus = (1u << 8), ///< If you are going to hand the process off (e.g. to debugserver)
|
||||
///< set this flag so lldb & the handee don't race to set its exit status.
|
||||
eLaunchFlagDetachOnError = (1u << 9) ///< If set, then the client stub should detach rather than killing the debugee
|
||||
///< if it loses connection with lldb.
|
||||
} LaunchFlags;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -107,6 +107,12 @@ public:
|
|||
const char *
|
||||
GetLaunchEventData () const;
|
||||
|
||||
bool
|
||||
GetDetachOnError() const;
|
||||
|
||||
void
|
||||
SetDetachOnError(bool enable);
|
||||
|
||||
};
|
||||
|
||||
class SBAttachInfo
|
||||
|
|
|
@ -292,6 +292,18 @@ SBLaunchInfo::GetLaunchEventData () const
|
|||
return m_opaque_sp->GetLaunchEventData ();
|
||||
}
|
||||
|
||||
void
|
||||
SBLaunchInfo::SetDetachOnError (bool enable)
|
||||
{
|
||||
m_opaque_sp->SetDetachOnError (enable);
|
||||
}
|
||||
|
||||
bool
|
||||
SBLaunchInfo::GetDetachOnError () const
|
||||
{
|
||||
return m_opaque_sp->GetDetachOnError ();
|
||||
}
|
||||
|
||||
SBAttachInfo::SBAttachInfo () :
|
||||
m_opaque_sp (new ProcessAttachInfo())
|
||||
{
|
||||
|
|
|
@ -208,6 +208,9 @@ protected:
|
|||
if (target->GetDisableASLR())
|
||||
m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
|
||||
|
||||
if (target->GetDetachOnError())
|
||||
m_options.launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
|
||||
|
||||
if (target->GetDisableSTDIO())
|
||||
m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
|
||||
|
||||
|
|
|
@ -1669,7 +1669,7 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
|
|||
const bool monitor_signals = false;
|
||||
Host::MonitorChildProcessCallback callback = nullptr;
|
||||
|
||||
if (!launch_info.GetFlags().Test(lldb::eLaunchFlagsDontSetExitStatus))
|
||||
if (!launch_info.GetFlags().Test(lldb::eLaunchFlagDontSetExitStatus))
|
||||
callback = Process::SetProcessExitStatus;
|
||||
|
||||
StartMonitoringChildProcess (callback,
|
||||
|
|
|
@ -788,7 +788,7 @@ PlatformDarwin::DebugProcess (ProcessLaunchInfo &launch_info,
|
|||
// We are going to hand this process off to debugserver which will be in charge of setting the exit status.
|
||||
// We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a
|
||||
// race between debugserver & us for who will find out about the debugged process's death.
|
||||
launch_info.GetFlags().Set(eLaunchFlagsDontSetExitStatus);
|
||||
launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus);
|
||||
process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -353,6 +353,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
|
|||
m_gdb_client.SetSTDOUT ("/dev/null");
|
||||
m_gdb_client.SetSTDERR ("/dev/null");
|
||||
m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR));
|
||||
m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError));
|
||||
|
||||
const char *working_dir = launch_info.GetWorkingDirectory();
|
||||
if (working_dir && working_dir[0])
|
||||
|
|
|
@ -2256,6 +2256,25 @@ GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
GDBRemoteCommunicationClient::SetDetachOnError (bool enable)
|
||||
{
|
||||
char packet[32];
|
||||
const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDetachOnError:%i", enable ? 1 : 0);
|
||||
assert (packet_len < (int)sizeof(packet));
|
||||
StringExtractorGDBRemote response;
|
||||
if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
|
||||
{
|
||||
if (response.IsOKResponse())
|
||||
return 0;
|
||||
uint8_t error = response.GetError();
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info)
|
||||
{
|
||||
|
|
|
@ -205,13 +205,25 @@ public:
|
|||
/// be launched with the 'A' packet.
|
||||
///
|
||||
/// @param[in] enable
|
||||
/// A boolean value indicating wether to disable ASLR or not.
|
||||
/// A boolean value indicating whether to disable ASLR or not.
|
||||
///
|
||||
/// @return
|
||||
/// Zero if the for success, or an error code for failure.
|
||||
//------------------------------------------------------------------
|
||||
int
|
||||
SetDisableASLR (bool enable);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Sets the DetachOnError flag to \a enable for the process controlled by the stub.
|
||||
///
|
||||
/// @param[in] enable
|
||||
/// A boolean value indicating whether to detach on error or not.
|
||||
///
|
||||
/// @return
|
||||
/// Zero if the for success, or an error code for failure.
|
||||
//------------------------------------------------------------------
|
||||
int
|
||||
SetDetachOnError (bool enable);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Sets the working directory to \a path for a process that will
|
||||
|
|
|
@ -202,6 +202,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
|
|||
packet_result = Handle_QSetDisableASLR (packet);
|
||||
break;
|
||||
|
||||
case StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError:
|
||||
packet_result = Handle_QSetDetachOnError (packet);
|
||||
break;
|
||||
|
||||
case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
|
||||
packet_result = Handle_QSetSTDIN (packet);
|
||||
break;
|
||||
|
@ -1139,6 +1143,17 @@ GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &
|
|||
return SendOKResponse ();
|
||||
}
|
||||
|
||||
GDBRemoteCommunication::PacketResult
|
||||
GDBRemoteCommunicationServer::Handle_QSetDetachOnError (StringExtractorGDBRemote &packet)
|
||||
{
|
||||
packet.SetFilePos(::strlen ("QSetDetachOnError:"));
|
||||
if (packet.GetU32(0))
|
||||
m_process_launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
|
||||
else
|
||||
m_process_launch_info.GetFlags().Clear (eLaunchFlagDetachOnError);
|
||||
return SendOKResponse ();
|
||||
}
|
||||
|
||||
GDBRemoteCommunication::PacketResult
|
||||
GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
|
||||
{
|
||||
|
|
|
@ -264,6 +264,9 @@ protected:
|
|||
PacketResult
|
||||
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_QSetDetachOnError (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
|
||||
|
||||
|
|
|
@ -799,6 +799,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
|
|||
m_gdb_comm.SetSTDERR (stderr_path);
|
||||
|
||||
m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
|
||||
m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);
|
||||
|
||||
m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName());
|
||||
|
||||
|
@ -1071,6 +1072,8 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
|
|||
|
||||
if (error.Success())
|
||||
{
|
||||
m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
|
||||
|
||||
char packet[64];
|
||||
const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
|
||||
SetID (attach_pid);
|
||||
|
@ -1108,6 +1111,8 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro
|
|||
{
|
||||
StreamString packet;
|
||||
|
||||
m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
|
||||
|
||||
if (attach_info.GetWaitForLaunch())
|
||||
{
|
||||
if (!m_gdb_comm.GetVAttachOrWaitSupported())
|
||||
|
|
|
@ -2642,6 +2642,7 @@ g_properties[] =
|
|||
{ "input-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for reading its standard input." },
|
||||
{ "output-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for writing its standard output." },
|
||||
{ "error-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for writing its standard error." },
|
||||
{ "detach-on-error" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "debugserver will detach (rather than killing) a process if it loses connection with lldb." },
|
||||
{ "disable-aslr" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Disable Address Space Layout Randomization (ASLR)" },
|
||||
{ "disable-stdio" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "Disable stdin/stdout for process (e.g. for a GUI application)" },
|
||||
{ "inline-breakpoint-strategy" , OptionValue::eTypeEnum , false, eInlineBreakpointsHeaders , NULL, g_inline_breakpoint_enums, "The strategy to use when settings breakpoints by file and line. "
|
||||
|
@ -2688,6 +2689,7 @@ enum
|
|||
ePropertyInputPath,
|
||||
ePropertyOutputPath,
|
||||
ePropertyErrorPath,
|
||||
ePropertyDetachOnError,
|
||||
ePropertyDisableASLR,
|
||||
ePropertyDisableSTDIO,
|
||||
ePropertyInlineStrategy,
|
||||
|
@ -2870,6 +2872,20 @@ TargetProperties::SetDisableASLR (bool b)
|
|||
m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
|
||||
}
|
||||
|
||||
bool
|
||||
TargetProperties::GetDetachOnError () const
|
||||
{
|
||||
const uint32_t idx = ePropertyDetachOnError;
|
||||
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
|
||||
}
|
||||
|
||||
void
|
||||
TargetProperties::SetDetachOnError (bool b)
|
||||
{
|
||||
const uint32_t idx = ePropertyDetachOnError;
|
||||
m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
|
||||
}
|
||||
|
||||
bool
|
||||
TargetProperties::GetDisableSTDIO () const
|
||||
{
|
||||
|
|
|
@ -92,6 +92,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
|
|||
if (PACKET_MATCHES ("QStartNoAckMode")) return eServerPacketType_QStartNoAckMode;
|
||||
if (PACKET_STARTS_WITH ("QSaveRegisterState")) return eServerPacketType_QSaveRegisterState;
|
||||
if (PACKET_STARTS_WITH ("QSetDisableASLR:")) return eServerPacketType_QSetDisableASLR;
|
||||
if (PACKET_STARTS_WITH ("QSetDetachOnError:")) return eServerPacketType_QSetDetachOnError;
|
||||
if (PACKET_STARTS_WITH ("QSetSTDIN:")) return eServerPacketType_QSetSTDIN;
|
||||
if (PACKET_STARTS_WITH ("QSetSTDOUT:")) return eServerPacketType_QSetSTDOUT;
|
||||
if (PACKET_STARTS_WITH ("QSetSTDERR:")) return eServerPacketType_QSetSTDERR;
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
eServerPacketType_QEnvironment,
|
||||
eServerPacketType_QLaunchArch,
|
||||
eServerPacketType_QSetDisableASLR,
|
||||
eServerPacketType_QSetDetachOnError,
|
||||
eServerPacketType_QSetSTDIN,
|
||||
eServerPacketType_QSetSTDOUT,
|
||||
eServerPacketType_QSetSTDERR,
|
||||
|
|
|
@ -203,6 +203,7 @@ RNBRemote::CreatePacketTable ()
|
|||
t.push_back (Packet (set_enable_profiling, &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL, "QSetEnableAsyncProfiling", "Enable or disable the profiling of current target."));
|
||||
t.push_back (Packet (watchpoint_support_info, &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL, "qWatchpointSupportInfo", "Return the number of supported hardware watchpoints"));
|
||||
t.push_back (Packet (set_process_event, &RNBRemote::HandlePacket_QSetProcessEvent, NULL, "QSetProcessEvent:", "Set a process event, to be passed to the process, can be set before the process is started, or after."));
|
||||
t.push_back (Packet (set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError, NULL, "QSetDetachOnError:", "Set whether debugserver will detach (1) or kill (0) from the process it is controlling if it loses connection to lldb."));
|
||||
t.push_back (Packet (speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:", "Test the maximum speed at which packet can be sent/received."));
|
||||
}
|
||||
|
||||
|
@ -2017,6 +2018,24 @@ RNBRemote::HandlePacket_QSyncThreadState (const char *p)
|
|||
return SendPacket ("E61");
|
||||
}
|
||||
|
||||
rnb_err_t
|
||||
RNBRemote::HandlePacket_QSetDetachOnError (const char *p)
|
||||
{
|
||||
p += sizeof ("QSetDetachOnError:") - 1;
|
||||
bool should_detach = true;
|
||||
switch (*p)
|
||||
{
|
||||
case '0': should_detach = false; break;
|
||||
case '1': should_detach = true; break;
|
||||
default:
|
||||
return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid value for QSetDetachOnError - should be 0 or 1");
|
||||
break;
|
||||
}
|
||||
|
||||
m_ctx.SetDetachOnError(should_detach);
|
||||
return SendPacket ("OK");
|
||||
}
|
||||
|
||||
rnb_err_t
|
||||
RNBRemote::HandlePacket_QListThreadsInStopReply (const char *p)
|
||||
{
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
save_register_state, // '_g'
|
||||
restore_register_state, // '_G'
|
||||
speed_test, // 'qSpeedTest:'
|
||||
set_detach_on_error, // 'QSetDetachOnError:'
|
||||
unknown_type
|
||||
} PacketEnum;
|
||||
|
||||
|
@ -234,6 +235,7 @@ public:
|
|||
rnb_err_t HandlePacket_WatchpointSupportInfo (const char *p);
|
||||
rnb_err_t HandlePacket_qSpeedTest (const char *p);
|
||||
rnb_err_t HandlePacket_stop_process (const char *p);
|
||||
rnb_err_t HandlePacket_QSetDetachOnError (const char *p);
|
||||
|
||||
rnb_err_t SendStopReplyPacketForThread (nub_thread_t tid);
|
||||
rnb_err_t SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer);
|
||||
|
|
Loading…
Reference in New Issue