summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process
diff options
context:
space:
mode:
authorTodd Fiala <todd.fiala@gmail.com>2014-08-28 15:46:54 +0000
committerTodd Fiala <todd.fiala@gmail.com>2014-08-28 15:46:54 +0000
commita9882cee50d3ba5716ca39ba831b43ea82c34183 (patch)
tree8b8d40a7af353787acc35496d9f795feaae11ef0 /lldb/source/Plugins/Process
parenta8833f0c28c86c86d1d059484fe0f44d371eaa47 (diff)
downloadbcm5719-llvm-a9882cee50d3ba5716ca39ba831b43ea82c34183.tar.gz
bcm5719-llvm-a9882cee50d3ba5716ca39ba831b43ea82c34183.zip
llgs: add proper exec support for Linux.
This change: * properly captures execs in NativeProcessLinux. * clears out all non-main-thread thread metadata in NativeProcessLinux on exec. * adds a DidExec() method to the NativeProcessProtocol delegate. * clears out the auxv data cache when we exec (on Linux). This is a small part of the llgs for local Linux debugging work going on here: https://github.com/tfiala/lldb/tree/dev-llgs-local I'm breaking it into small patches. llvm-svn: 216670
Diffstat (limited to 'lldb/source/Plugins/Process')
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp75
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp28
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeThreadLinux.h3
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp23
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h6
5 files changed, 125 insertions, 10 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index f004a8e8539..22f355a7c89 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -1953,19 +1953,31 @@ NativeProcessLinux::MonitorCallback(void *callback_baton,
if (ptrace_err == EINVAL)
{
// This is the first part of the Linux ptrace group-stop mechanism.
+ // (The other thing it can conceivably be is a call on a pid that no
+ // longer exists for some reason).
// The tracer (i.e. NativeProcessLinux) is expected to inject the signal
// into the tracee (i.e. inferior) at this point.
if (log)
- log->Printf ("NativeProcessLinux::%s() resuming from group-stop", __FUNCTION__);
+ log->Printf ("NativeProcessLinux::%s resuming from group-stop", __FUNCTION__);
// The inferior process is in 'group-stop', so deliver the stopping signal.
const bool signal_delivered = process->Resume (pid, info.si_signo);
if (log)
- log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " group-stop signal delivery of signal 0x%x (%s) - %s", __FUNCTION__, pid, info.si_signo, GetUnixSignals ().GetSignalAsCString (info.si_signo), signal_delivered ? "success" : "failed");
+ log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " group-stop signal delivery of signal 0x%x (%s) - %s", __FUNCTION__, pid, info.si_signo, GetUnixSignals ().GetSignalAsCString (info.si_signo), signal_delivered ? "success" : "failed");
- assert(signal_delivered && "SIGSTOP delivery failed while in 'group-stop' state");
+ if (signal_delivered)
+ {
+ // All is well.
+ stop_monitoring = false;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " something looks horribly wrong - like the process we're monitoring died. Stop monitoring it.", __FUNCTION__, pid);
- stop_monitoring = false;
+ // Stop monitoring now.
+ return true;
+ }
}
else
{
@@ -2079,10 +2091,63 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid)
}
case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)):
+ {
+ NativeThreadProtocolSP main_thread_sp;
+
if (log)
log->Printf ("NativeProcessLinux::%s() received exec event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP);
- // FIXME stop all threads, mark thread stop reason as ThreadStopInfo.reason = eStopReasonExec;
+
+ // Remove all but the main thread here.
+ // FIXME check if we really need to do this - how does ptrace behave under exec when multiple threads were present
+ // before the exec? If we get all the detach signals right, we don't need to do this. However, it makes it clearer
+ // what we should really be tracking.
+ {
+ Mutex::Locker locker (m_threads_mutex);
+
+ if (log)
+ log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__);
+
+ for (auto thread_sp : m_threads)
+ {
+ const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID ();
+ if (is_main_thread)
+ {
+ main_thread_sp = thread_sp;
+ if (log)
+ log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64 ", keeping", __FUNCTION__, main_thread_sp->GetID ());
+ }
+ else
+ {
+ if (log)
+ log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 " due to exec", __FUNCTION__, thread_sp->GetID ());
+ }
+ }
+
+ m_threads.clear ();
+
+ if (main_thread_sp)
+ {
+ m_threads.push_back (main_thread_sp);
+ SetCurrentThreadID (main_thread_sp->GetID ());
+ reinterpret_cast<NativeThreadLinux*>(main_thread_sp.get())->SetStoppedByExec ();
+ }
+ else
+ {
+ SetCurrentThreadID (LLDB_INVALID_THREAD_ID);
+ if (log)
+ log->Printf ("NativeProcessLinux::%s pid %" PRIu64 "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ());
+ }
+ }
+
+ // Let our delegate know we have just exec'd.
+ NotifyDidExec ();
+
+ // If we have a main thread, indicate we are stopped.
+ assert (main_thread_sp && "exec called during ptraced process but no main thread metadata tracked");
+ SetState (StateType::eStateStopped);
+
break;
+ }
case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)):
{
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index ef5b63a3f94..eeef780d172 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -34,13 +34,16 @@ namespace
switch (stop_info.reason)
{
case eStopReasonSignal:
- log.Printf ("%s: %s: signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
+ log.Printf ("%s: %s signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
return;
case eStopReasonException:
- log.Printf ("%s: %s: exception type 0x%" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
+ log.Printf ("%s: %s exception type 0x%" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
+ return;
+ case eStopReasonExec:
+ log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
return;
default:
- log.Printf ("%s: %s: invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
+ log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
}
}
}
@@ -83,10 +86,10 @@ NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info)
case eStateSuspended:
case eStateUnloaded:
if (log)
- LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread: ");
+ LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
stop_info = m_stop_info;
if (log)
- LogThreadStopInfo (*log, stop_info, "returned stop_info: ");
+ LogThreadStopInfo (*log, stop_info, "returned stop_info:");
return true;
case eStateInvalid:
@@ -246,6 +249,21 @@ NativeThreadLinux::SetStoppedBySignal (uint32_t signo)
}
void
+NativeThreadLinux::SetStoppedByExec ()
+{
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
+
+ const StateType new_state = StateType::eStateStopped;
+ MaybeLogStateChange (new_state);
+ m_state = new_state;
+
+ m_stop_info.reason = StopReason::eStopReasonExec;
+ m_stop_info.details.signal.signo = SIGSTOP;
+}
+
+void
NativeThreadLinux::SetStoppedByBreakpoint ()
{
const StateType new_state = StateType::eStateStopped;
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
index 1a9fc4e868c..bed530dbe9f 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
@@ -65,6 +65,9 @@ namespace lldb_private
SetStoppedBySignal (uint32_t signo);
void
+ SetStoppedByExec ();
+
+ void
SetStoppedByBreakpoint ();
bool
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 4d38a07302c..ffcdd169eb9 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -1094,6 +1094,12 @@ GDBRemoteCommunicationServer::ProcessStateChanged (lldb_private::NativeProcessPr
m_inferior_prev_state = state;
}
+void
+GDBRemoteCommunicationServer::DidExec (NativeProcessProtocol *process)
+{
+ ClearProcessSpecificData ();
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendONotification (const char *buffer, uint32_t len)
{
@@ -4289,3 +4295,20 @@ GDBRemoteCommunicationServer::GetNextSavedRegistersID ()
return m_next_saved_registers_id++;
}
+void
+GDBRemoteCommunicationServer::ClearProcessSpecificData ()
+{
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s()", __FUNCTION__);
+
+ // Clear any auxv cached data.
+ // *BSD impls should be able to do this too.
+#if defined(__linux__)
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServer::%s clearing auxv buffer (previously %s)",
+ __FUNCTION__,
+ m_active_auxv_buffer_sp ? "was set" : "was not set");
+ m_active_auxv_buffer_sp.reset ();
+#endif
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 412b591e6ec..13c037c0287 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -218,6 +218,9 @@ public:
void
ProcessStateChanged (lldb_private::NativeProcessProtocol *process, lldb::StateType state) override;
+ void
+ DidExec (lldb_private::NativeProcessProtocol *process) override;
+
protected:
lldb::PlatformSP m_platform_sp;
lldb::thread_t m_async_thread;
@@ -534,6 +537,9 @@ private:
void
MaybeCloseInferiorTerminalConnection ();
+ void
+ ClearProcessSpecificData ();
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
OpenPOWER on IntegriCloud