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 //------------------------------------------------------------------ _______________________________________________ lldb-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
