forked from OSchip/llvm-project
Still trying to get detach to work with debugserver. Got a bit closer,
but something is still killing our inferior. Fixed an issue with darwin-debug where it wasn't passing all needed arguments to the inferior. Fixed a race condition with the attach to named process code. llvm-svn: 116697
This commit is contained in:
parent
5cd41c4b13
commit
58d1c9a44f
|
@ -421,7 +421,7 @@
|
|||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 26579F67126A25920007C5CB /* darwin-debug */;
|
||||
remoteGlobalIDString = 26579F67126A25920007C5CB;
|
||||
remoteInfo = "darwin-debug";
|
||||
};
|
||||
266803611160110D008E1FE4 /* PBXContainerItemProxy */ = {
|
||||
|
|
|
@ -1139,13 +1139,25 @@ ProcessGDBRemote::WillDetach ()
|
|||
{
|
||||
bool timed_out = false;
|
||||
Mutex::Locker locker;
|
||||
PausePrivateStateThread();
|
||||
m_thread_list.DiscardThreadPlans();
|
||||
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
|
||||
if (!m_gdb_comm.SendInterrupt (locker, 2, &timed_out))
|
||||
{
|
||||
if (timed_out)
|
||||
error.SetErrorString("timed out sending interrupt packet");
|
||||
else
|
||||
error.SetErrorString("unknown error sending interrupt packet");
|
||||
ResumePrivateStateThread();
|
||||
}
|
||||
TimeValue timeout_time;
|
||||
timeout_time = TimeValue::Now();
|
||||
timeout_time.OffsetWithSeconds(2);
|
||||
|
||||
EventSP event_sp;
|
||||
StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
|
||||
if (state != eStateStopped)
|
||||
error.SetErrorString("unable to stop target");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -1160,30 +1172,26 @@ ProcessGDBRemote::DoDetach()
|
|||
|
||||
DisableAllBreakpointSites ();
|
||||
|
||||
StringExtractorGDBRemote response;
|
||||
size_t response_size = m_gdb_comm.SendPacketAndWaitForResponse("D", response, 2, false);
|
||||
if (response_size)
|
||||
{
|
||||
if (response.IsOKPacket())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::DoDetach() detach was successful");
|
||||
m_thread_list.DiscardThreadPlans();
|
||||
|
||||
}
|
||||
else if (log)
|
||||
{
|
||||
log->Printf ("ProcessGDBRemote::DoDestroy() detach failed: %s", response.GetStringRef().c_str());
|
||||
}
|
||||
}
|
||||
else if (log)
|
||||
size_t response_size = m_gdb_comm.SendPacket ("D", 1);
|
||||
if (log)
|
||||
{
|
||||
log->PutCString ("ProcessGDBRemote::DoDestroy() detach failed for unknown reasons");
|
||||
if (response_size)
|
||||
log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
|
||||
else
|
||||
log->PutCString ("ProcessGDBRemote::DoDetach() detach packet send failed");
|
||||
}
|
||||
// Sleep for one second to let the process get all detached...
|
||||
StopAsyncThread ();
|
||||
|
||||
m_gdb_comm.StopReadThread();
|
||||
KillDebugserverProcess ();
|
||||
m_gdb_comm.Disconnect(); // Disconnect from the debug server.
|
||||
SetPublicState (eStateDetached);
|
||||
|
||||
SetPrivateState (eStateDetached);
|
||||
ResumePrivateStateThread();
|
||||
|
||||
//KillDebugserverProcess ();
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1922,7 +1930,13 @@ ProcessGDBRemote::MonitorDebugserverProcess
|
|||
usleep (500000);
|
||||
// If our process hasn't yet exited, debugserver might have died.
|
||||
// If the process did exit, the we are reaping it.
|
||||
if (process->GetState() != eStateExited)
|
||||
const StateType state = process->GetState();
|
||||
|
||||
if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID &&
|
||||
state != eStateInvalid &&
|
||||
state != eStateUnloaded &&
|
||||
state != eStateExited &&
|
||||
state != eStateDetached)
|
||||
{
|
||||
char error_str[1024];
|
||||
if (signo)
|
||||
|
@ -1940,15 +1954,12 @@ ProcessGDBRemote::MonitorDebugserverProcess
|
|||
|
||||
process->SetExitStatus (-1, error_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Debugserver has exited we need to let our ProcessGDBRemote
|
||||
// know that it no longer has a debugserver instance
|
||||
process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
|
||||
// We are returning true to this function below, so we can
|
||||
// forget about the monitor handle.
|
||||
process->m_debugserver_thread = LLDB_INVALID_HOST_THREAD;
|
||||
}
|
||||
// Debugserver has exited we need to let our ProcessGDBRemote
|
||||
// know that it no longer has a debugserver instance
|
||||
process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
|
||||
// We are returning true to this function below, so we can
|
||||
// forget about the monitor handle.
|
||||
process->m_debugserver_thread = LLDB_INVALID_HOST_THREAD;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1222,7 +1222,6 @@ Process::Attach (const char *process_name, bool wait_for_launch)
|
|||
if (error.Success())
|
||||
{
|
||||
SetPublicState (eStateAttaching);
|
||||
StartPrivateStateThread();
|
||||
error = DoAttachToProcessWithName (process_name, wait_for_launch);
|
||||
if (error.Fail())
|
||||
{
|
||||
|
@ -1635,7 +1634,9 @@ Process::RunPrivateStateThread ()
|
|||
HandlePrivateEvent (event_sp);
|
||||
}
|
||||
|
||||
if (internal_state == eStateInvalid || internal_state == eStateExited)
|
||||
if (internal_state == eStateInvalid ||
|
||||
internal_state == eStateExited ||
|
||||
internal_state == eStateDetached )
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,10 +87,12 @@ exit_with_errno (int err, const char *prefix)
|
|||
}
|
||||
|
||||
pid_t
|
||||
posix_spawn_for_debug (const char *path, char *const *argv, char *const *envp, cpu_type_t cpu_type, int disable_aslr)
|
||||
posix_spawn_for_debug (char *const *argv, char *const *envp, cpu_type_t cpu_type, int disable_aslr)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
|
||||
const char *path = argv[0];
|
||||
|
||||
posix_spawnattr_t attr;
|
||||
|
||||
exit_with_errno (::posix_spawnattr_init (&attr), "::posix_spawnattr_init (&attr) error: ");
|
||||
|
@ -203,13 +205,7 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
|
|||
printf ("argv[%u] = '%s'\n", i, argv[i]);
|
||||
#endif
|
||||
|
||||
const char *exe_path = argv[0];
|
||||
|
||||
// Skip this inferior program name...
|
||||
++argv;
|
||||
|
||||
posix_spawn_for_debug (exe_path,
|
||||
argv,
|
||||
posix_spawn_for_debug (argv,
|
||||
pass_env ? envp : NULL,
|
||||
cpu_type,
|
||||
disable_aslr);
|
||||
|
|
|
@ -101,7 +101,7 @@ MachProcess::MachProcess() :
|
|||
m_stdio_thread (0),
|
||||
m_stdio_mutex (PTHREAD_MUTEX_RECURSIVE),
|
||||
m_stdout_data (),
|
||||
m_threadList (),
|
||||
m_thread_list (),
|
||||
m_exception_messages (),
|
||||
m_exception_messages_mutex (PTHREAD_MUTEX_RECURSIVE),
|
||||
m_state (eStateUnloaded),
|
||||
|
@ -147,62 +147,62 @@ MachProcess::GetState()
|
|||
const char *
|
||||
MachProcess::ThreadGetName(nub_thread_t tid)
|
||||
{
|
||||
return m_threadList.GetName(tid);
|
||||
return m_thread_list.GetName(tid);
|
||||
}
|
||||
|
||||
nub_state_t
|
||||
MachProcess::ThreadGetState(nub_thread_t tid)
|
||||
{
|
||||
return m_threadList.GetState(tid);
|
||||
return m_thread_list.GetState(tid);
|
||||
}
|
||||
|
||||
|
||||
nub_size_t
|
||||
MachProcess::GetNumThreads () const
|
||||
{
|
||||
return m_threadList.NumThreads();
|
||||
return m_thread_list.NumThreads();
|
||||
}
|
||||
|
||||
nub_thread_t
|
||||
MachProcess::GetThreadAtIndex (nub_size_t thread_idx) const
|
||||
{
|
||||
return m_threadList.ThreadIDAtIndex(thread_idx);
|
||||
return m_thread_list.ThreadIDAtIndex(thread_idx);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MachProcess::GetThreadIndexFromThreadID (nub_thread_t tid)
|
||||
{
|
||||
return m_threadList.GetThreadIndexByID(tid);
|
||||
return m_thread_list.GetThreadIndexByID(tid);
|
||||
}
|
||||
|
||||
nub_thread_t
|
||||
MachProcess::GetCurrentThread ()
|
||||
{
|
||||
return m_threadList.CurrentThreadID();
|
||||
return m_thread_list.CurrentThreadID();
|
||||
}
|
||||
|
||||
nub_thread_t
|
||||
MachProcess::SetCurrentThread(nub_thread_t tid)
|
||||
{
|
||||
return m_threadList.SetCurrentThread(tid);
|
||||
return m_thread_list.SetCurrentThread(tid);
|
||||
}
|
||||
|
||||
bool
|
||||
MachProcess::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const
|
||||
{
|
||||
return m_threadList.GetThreadStoppedReason(tid, stop_info);
|
||||
return m_thread_list.GetThreadStoppedReason(tid, stop_info);
|
||||
}
|
||||
|
||||
void
|
||||
MachProcess::DumpThreadStoppedReason(nub_thread_t tid) const
|
||||
{
|
||||
return m_threadList.DumpThreadStoppedReason(tid);
|
||||
return m_thread_list.DumpThreadStoppedReason(tid);
|
||||
}
|
||||
|
||||
const char *
|
||||
MachProcess::GetThreadInfo(nub_thread_t tid) const
|
||||
{
|
||||
return m_threadList.GetThreadInfo(tid);
|
||||
return m_thread_list.GetThreadInfo(tid);
|
||||
}
|
||||
|
||||
const DNBRegisterSetInfo *
|
||||
|
@ -214,13 +214,13 @@ MachProcess::GetRegisterSetInfo(nub_thread_t tid, nub_size_t *num_reg_sets ) con
|
|||
bool
|
||||
MachProcess::GetRegisterValue ( nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value ) const
|
||||
{
|
||||
return m_threadList.GetRegisterValue(tid, set, reg, value);
|
||||
return m_thread_list.GetRegisterValue(tid, set, reg, value);
|
||||
}
|
||||
|
||||
bool
|
||||
MachProcess::SetRegisterValue ( nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value ) const
|
||||
{
|
||||
return m_threadList.SetRegisterValue(tid, set, reg, value);
|
||||
return m_thread_list.SetRegisterValue(tid, set, reg, value);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -273,7 +273,7 @@ MachProcess::Clear()
|
|||
SetState(eStateUnloaded);
|
||||
m_flags = eMachProcessFlagsNone;
|
||||
m_stop_count = 0;
|
||||
m_threadList.Clear();
|
||||
m_thread_list.Clear();
|
||||
{
|
||||
PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
|
||||
m_exception_messages.clear();
|
||||
|
@ -373,7 +373,13 @@ MachProcess::DoSIGSTOP (bool clear_bps_and_wps)
|
|||
clear_bps_and_wps = false;
|
||||
}
|
||||
|
||||
// Resume our process
|
||||
// If we already have a thread stopped due to a SIGSTOP, we don't have
|
||||
// to do anything...
|
||||
if (m_thread_list.GetThreadIndexForThreadStoppedWithSignal (SIGSTOP) != UINT32_MAX)
|
||||
return GetState();
|
||||
|
||||
// No threads were stopped with a SIGSTOP, we need to run and halt the
|
||||
// process with a signal
|
||||
DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s -- resuming process", DNBStateAsString (state));
|
||||
PrivateResume (DNBThreadResumeActions (eStateRunning, 0));
|
||||
|
||||
|
@ -406,11 +412,15 @@ MachProcess::Detach()
|
|||
nub_state_t state = DoSIGSTOP(true);
|
||||
DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s", DNBStateAsString(state));
|
||||
|
||||
{
|
||||
DNBThreadResumeActions thread_actions (eStateRunning, 0);
|
||||
PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex);
|
||||
|
||||
// Don't reply to our SIGSTOP exception, just make sure no threads
|
||||
// are still suspended.
|
||||
PrivateResume (DNBThreadResumeActions (eStateRunning, 0));
|
||||
ReplyToAllExceptions (thread_actions);
|
||||
|
||||
}
|
||||
|
||||
m_task.ShutDownExcecptionThread();
|
||||
|
||||
// Detach from our process
|
||||
errno = 0;
|
||||
|
@ -423,13 +433,14 @@ MachProcess::Detach()
|
|||
// Resume our task
|
||||
m_task.Resume();
|
||||
|
||||
SetState(eStateDetached);
|
||||
|
||||
// NULL our task out as we have already retored all exception ports
|
||||
m_task.Clear();
|
||||
|
||||
// Clear out any notion of the process we once were
|
||||
Clear();
|
||||
|
||||
SetState(eStateDetached);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -604,7 +615,7 @@ MachProcess::PrivateResume (const DNBThreadResumeActions& thread_actions)
|
|||
// Let the thread prepare to resume and see if any threads want us to
|
||||
// step over a breakpoint instruction (ProcessWillResume will modify
|
||||
// the value of stepOverBreakInstruction).
|
||||
m_threadList.ProcessWillResume (this, thread_actions);
|
||||
m_thread_list.ProcessWillResume (this, thread_actions);
|
||||
|
||||
// Set our state accordingly
|
||||
if (thread_actions.NumActionsWithState(eStateStepping))
|
||||
|
@ -718,7 +729,7 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove)
|
|||
|
||||
if (bp->IsHardware())
|
||||
{
|
||||
bool hw_disable_result = m_threadList.DisableHardwareBreakpoint (bp);
|
||||
bool hw_disable_result = m_thread_list.DisableHardwareBreakpoint (bp);
|
||||
|
||||
if (hw_disable_result == true)
|
||||
{
|
||||
|
@ -726,7 +737,7 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove)
|
|||
// Let the thread list know that a breakpoint has been modified
|
||||
if (remove)
|
||||
{
|
||||
m_threadList.NotifyBreakpointChanged(bp);
|
||||
m_thread_list.NotifyBreakpointChanged(bp);
|
||||
m_breakpoints.Remove(breakID);
|
||||
}
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx (hardware) => success", breakID, remove, (uint64_t)addr);
|
||||
|
@ -794,7 +805,7 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove)
|
|||
// Let the thread list know that a breakpoint has been modified
|
||||
if (remove)
|
||||
{
|
||||
m_threadList.NotifyBreakpointChanged(bp);
|
||||
m_thread_list.NotifyBreakpointChanged(bp);
|
||||
m_breakpoints.Remove(breakID);
|
||||
}
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx => success", breakID, remove, (uint64_t)addr);
|
||||
|
@ -839,7 +850,7 @@ MachProcess::DisableWatchpoint(nub_watch_t watchID, bool remove)
|
|||
|
||||
if (wp->IsHardware())
|
||||
{
|
||||
bool hw_disable_result = m_threadList.DisableHardwareWatchpoint (wp);
|
||||
bool hw_disable_result = m_thread_list.DisableHardwareWatchpoint (wp);
|
||||
|
||||
if (hw_disable_result == true)
|
||||
{
|
||||
|
@ -916,7 +927,7 @@ MachProcess::EnableBreakpoint(nub_break_t breakID)
|
|||
{
|
||||
if (bp->HardwarePreferred())
|
||||
{
|
||||
bp->SetHardwareIndex(m_threadList.EnableHardwareBreakpoint(bp));
|
||||
bp->SetHardwareIndex(m_thread_list.EnableHardwareBreakpoint(bp));
|
||||
if (bp->IsHardware())
|
||||
{
|
||||
bp->SetEnabled(true);
|
||||
|
@ -942,7 +953,7 @@ MachProcess::EnableBreakpoint(nub_break_t breakID)
|
|||
{
|
||||
bp->SetEnabled(true);
|
||||
// Let the thread list know that a breakpoint has been modified
|
||||
m_threadList.NotifyBreakpointChanged(bp);
|
||||
m_thread_list.NotifyBreakpointChanged(bp);
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( breakID = %d ) addr = 0x%8.8llx: SUCCESS.", breakID, (uint64_t)addr);
|
||||
return true;
|
||||
}
|
||||
|
@ -991,7 +1002,7 @@ MachProcess::EnableWatchpoint(nub_watch_t watchID)
|
|||
else
|
||||
{
|
||||
// Currently only try and set hardware watchpoints.
|
||||
wp->SetHardwareIndex(m_threadList.EnableHardwareWatchpoint(wp));
|
||||
wp->SetHardwareIndex(m_thread_list.EnableHardwareWatchpoint(wp));
|
||||
if (wp->IsHardware())
|
||||
{
|
||||
wp->SetEnabled(true);
|
||||
|
@ -1031,7 +1042,7 @@ MachProcess::ExceptionMessageBundleComplete()
|
|||
{
|
||||
// Let all threads recover from stopping and do any clean up based
|
||||
// on the previous thread state (if any).
|
||||
m_threadList.ProcessDidStop(this);
|
||||
m_thread_list.ProcessDidStop(this);
|
||||
|
||||
// Let each thread know of any exceptions
|
||||
task_t task = m_task.TaskPort();
|
||||
|
@ -1041,16 +1052,16 @@ MachProcess::ExceptionMessageBundleComplete()
|
|||
// Let the thread list figure use the MachProcess to forward all exceptions
|
||||
// on down to each thread.
|
||||
if (m_exception_messages[i].state.task_port == task)
|
||||
m_threadList.NotifyException(m_exception_messages[i].state);
|
||||
m_thread_list.NotifyException(m_exception_messages[i].state);
|
||||
if (DNBLogCheckLogBit(LOG_EXCEPTIONS))
|
||||
m_exception_messages[i].Dump();
|
||||
}
|
||||
|
||||
if (DNBLogCheckLogBit(LOG_THREAD))
|
||||
m_threadList.Dump();
|
||||
m_thread_list.Dump();
|
||||
|
||||
bool step_more = false;
|
||||
if (m_threadList.ShouldStop(step_more))
|
||||
if (m_thread_list.ShouldStop(step_more))
|
||||
{
|
||||
// Wait for the eEventProcessRunningStateChanged event to be reset
|
||||
// before changing state to stopped to avoid race condition with
|
||||
|
|
|
@ -141,7 +141,7 @@ public:
|
|||
uint32_t GetThreadIndexFromThreadID (nub_thread_t tid);
|
||||
nub_thread_t GetCurrentThread ();
|
||||
nub_thread_t SetCurrentThread (nub_thread_t tid);
|
||||
MachThreadList & GetThreadList() { return m_threadList; }
|
||||
MachThreadList & GetThreadList() { return m_thread_list; }
|
||||
bool GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const;
|
||||
void DumpThreadStoppedReason(nub_thread_t tid) const;
|
||||
const char * GetThreadInfo (nub_thread_t tid) const;
|
||||
|
@ -243,7 +243,7 @@ private:
|
|||
m_exception_messages; // A collection of exception messages caught when listening to the exception port
|
||||
PThreadMutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages
|
||||
|
||||
MachThreadList m_threadList; // A list of threads that is maintained/updated after each stop
|
||||
MachThreadList m_thread_list; // A list of threads that is maintained/updated after each stop
|
||||
nub_state_t m_state; // The state of our process
|
||||
PThreadMutex m_state_mutex; // Multithreaded protection for m_state
|
||||
PThreadEvent m_events; // Process related events in the child processes lifetime can be waited upon
|
||||
|
|
|
@ -429,4 +429,17 @@ MachThreadList::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MachThreadList::GetThreadIndexForThreadStoppedWithSignal (const int signo) const
|
||||
{
|
||||
uint32_t should_stop = false;
|
||||
const uint32_t num_threads = m_threads.size();
|
||||
uint32_t idx = 0;
|
||||
for (idx = 0; !should_stop && idx < num_threads; ++idx)
|
||||
{
|
||||
if (m_threads[idx]->GetStopException().SoftSignal () == signo)
|
||||
return idx;
|
||||
}
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
bool DisableHardwareBreakpoint (const DNBBreakpoint *bp) const;
|
||||
uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *wp) const;
|
||||
bool DisableHardwareWatchpoint (const DNBBreakpoint *wp) const;
|
||||
uint32_t GetThreadIndexForThreadStoppedWithSignal (const int signo) const;
|
||||
|
||||
protected:
|
||||
typedef std::vector<MachThreadSP> collection;
|
||||
|
|
|
@ -167,6 +167,7 @@ RNBContext::ThreadFunctionProcessStatus(void *arg)
|
|||
|
||||
case eStateInvalid:
|
||||
case eStateExited:
|
||||
case eStateDetached:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -3064,7 +3064,8 @@ RNBRemote::HandlePacket_C (const char *p)
|
|||
rnb_err_t
|
||||
RNBRemote::HandlePacket_D (const char *p)
|
||||
{
|
||||
SendPacket ("OK");
|
||||
// We are not supposed to send a response for deatch.
|
||||
//SendPacket ("OK");
|
||||
if (m_ctx.HasValidProcessID())
|
||||
DNBProcessDetach(m_ctx.ProcessID());
|
||||
return rnb_success;
|
||||
|
|
Loading…
Reference in New Issue