[Lldb-commits] [lldb] r216670 - llgs: add proper exec support for Linux.

Todd Fiala todd.fiala at gmail.com
Thu Aug 28 08:46:54 PDT 2014


Author: tfiala
Date: Thu Aug 28 10:46:54 2014
New Revision: 216670

URL: http://llvm.org/viewvc/llvm-project?rev=216670&view=rev
Log:
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.

Modified:
    lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
    lldb/trunk/source/Host/common/NativeProcessProtocol.h
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h

Modified: lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.cpp?rev=216670&r1=216669&r2=216670&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeProcessProtocol.cpp (original)
+++ lldb/trunk/source/Host/common/NativeProcessProtocol.cpp Thu Aug 28 10:46:54 2014
@@ -325,6 +325,21 @@ NativeProcessProtocol::SynchronouslyNoti
     }
 }
 
+void
+NativeProcessProtocol::NotifyDidExec ()
+{
+    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+    if (log)
+        log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__);
+
+    {
+        Mutex::Locker locker (m_delegates_mutex);
+        for (auto native_delegate: m_delegates)
+            native_delegate->DidExec (this);
+    }
+}
+
+
 Error
 NativeProcessProtocol::SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint)
 {

Modified: lldb/trunk/source/Host/common/NativeProcessProtocol.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.h?rev=216670&r1=216669&r2=216670&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeProcessProtocol.h (original)
+++ lldb/trunk/source/Host/common/NativeProcessProtocol.h Thu Aug 28 10:46:54 2014
@@ -230,6 +230,9 @@ namespace lldb_private
 
             virtual void
             ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) = 0;
+
+            virtual void
+            DidExec (NativeProcessProtocol *process) = 0;
         };
 
         //------------------------------------------------------------------
@@ -311,6 +314,15 @@ namespace lldb_private
         virtual Error
         GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) = 0;
 
+        // -----------------------------------------------------------
+        /// Notify the delegate that an exec occurred.
+        ///
+        /// Provide a mechanism for a delegate to clear out any exec-
+        /// sensitive data.
+        // -----------------------------------------------------------
+        void
+        NotifyDidExec ();
+
     private:
 
         void

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=216670&r1=216669&r2=216670&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Thu Aug 28 10:46:54 2014
@@ -1953,19 +1953,31 @@ NativeProcessLinux::MonitorCallback(void
         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
     }
 
     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)):
     {

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp?rev=216670&r1=216669&r2=216670&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp Thu Aug 28 10:46:54 2014
@@ -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 (Thread
     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 (u
 }
 
 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;

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h?rev=216670&r1=216669&r2=216670&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.h Thu Aug 28 10:46:54 2014
@@ -65,6 +65,9 @@ namespace lldb_private
         SetStoppedBySignal (uint32_t signo);
 
         void
+        SetStoppedByExec ();
+
+        void
         SetStoppedByBreakpoint ();
 
         bool

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp?rev=216670&r1=216669&r2=216670&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp Thu Aug 28 10:46:54 2014
@@ -1094,6 +1094,12 @@ GDBRemoteCommunicationServer::ProcessSta
     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::GetNextSav
     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
+}

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h?rev=216670&r1=216669&r2=216670&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h Thu Aug 28 10:46:54 2014
@@ -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
     //------------------------------------------------------------------





More information about the lldb-commits mailing list