diff --git a/lldb/bindings/interface/SBThread.i b/lldb/bindings/interface/SBThread.i index 463584d2cab16..d847d38f0d66e 100644 --- a/lldb/bindings/interface/SBThread.i +++ b/lldb/bindings/interface/SBThread.i @@ -104,6 +104,9 @@ public: eStopReasonSignal 1 unix signal number eStopReasonException N exception data eStopReasonExec 0 + eStopReasonFork 1 pid of the child process + eStopReasonVFork 1 pid of the child process + eStopReasonVForkDone 0 eStopReasonPlanComplete 0") GetStopReasonDataAtIndex; uint64_t GetStopReasonDataAtIndex(uint32_t idx); diff --git a/lldb/bindings/interface/SBThreadPlan.i b/lldb/bindings/interface/SBThreadPlan.i index 94ae1a42dd3b2..9e10535253548 100644 --- a/lldb/bindings/interface/SBThreadPlan.i +++ b/lldb/bindings/interface/SBThreadPlan.i @@ -73,6 +73,9 @@ public: eStopReasonSignal 1 unix signal number eStopReasonException N exception data eStopReasonExec 0 + eStopReasonFork 1 pid of the child process + eStopReasonVFork 1 pid of the child process + eStopReasonVForkDone 0 eStopReasonPlanComplete 0") GetStopReasonDataAtIndex; uint64_t GetStopReasonDataAtIndex(uint32_t idx); diff --git a/lldb/docs/python_api_enums.rst b/lldb/docs/python_api_enums.rst index a05647f61ca8c..70bce246fc687 100644 --- a/lldb/docs/python_api_enums.rst +++ b/lldb/docs/python_api_enums.rst @@ -342,6 +342,9 @@ StopReason .. py:data:: eStopReasonSignal .. py:data:: eStopReasonException .. py:data:: eStopReasonExec +.. py:data:: eStopReasonFork +.. py:data:: eStopReasonVFork +.. py:data:: eStopReasonVForkDone .. py:data:: eStopReasonPlanComplete .. py:data:: eStopReasonThreadExiting .. py:data:: eStopReasonInstrumentation diff --git a/lldb/examples/python/performance.py b/lldb/examples/python/performance.py index f90857808fc0c..57e9d1e0a24c3 100755 --- a/lldb/examples/python/performance.py +++ b/lldb/examples/python/performance.py @@ -255,6 +255,15 @@ def WaitForNextProcessEvent(self): select_thread = True if self.verbose: print("signal %d" % (thread.GetStopReasonDataAtIndex(0))) + elif stop_reason == lldb.eStopReasonFork: + if self.verbose: + print("fork pid = %d" % (thread.GetStopReasonDataAtIndex(0))) + elif stop_reason == lldb.eStopReasonVFork: + if self.verbose: + print("vfork pid = %d" % (thread.GetStopReasonDataAtIndex(0))) + elif stop_reason == lldb.eStopReasonVForkDone: + if self.verbose: + print("vfork done") if select_thread and not selected_thread: self.thread = thread diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h index 894120c6d9861..095a679948227 100644 --- a/lldb/include/lldb/API/SBThread.h +++ b/lldb/include/lldb/API/SBThread.h @@ -66,6 +66,9 @@ class LLDB_API SBThread { /// eStopReasonSignal 1 unix signal number /// eStopReasonException N exception data /// eStopReasonExec 0 + /// eStopReasonFork 1 pid of the child process + /// eStopReasonVFork 1 pid of the child process + /// eStopReasonVForkDone 0 /// eStopReasonPlanComplete 0 uint64_t GetStopReasonDataAtIndex(uint32_t idx); diff --git a/lldb/include/lldb/API/SBThreadPlan.h b/lldb/include/lldb/API/SBThreadPlan.h index 269cbc64a8efd..831452dc0a98d 100644 --- a/lldb/include/lldb/API/SBThreadPlan.h +++ b/lldb/include/lldb/API/SBThreadPlan.h @@ -58,6 +58,9 @@ class LLDB_API SBThreadPlan { /// eStopReasonSignal 1 unix signal number /// eStopReasonException N exception data /// eStopReasonExec 0 + /// eStopReasonFork 1 pid of the child process + /// eStopReasonVFork 1 pid of the child process + /// eStopReasonVForkDone 0 /// eStopReasonPlanComplete 0 uint64_t GetStopReasonDataAtIndex(uint32_t idx); diff --git a/lldb/include/lldb/Host/Debug.h b/lldb/include/lldb/Host/Debug.h index 402325c4c166e..7da59dd04a66b 100644 --- a/lldb/include/lldb/Host/Debug.h +++ b/lldb/include/lldb/Host/Debug.h @@ -144,6 +144,12 @@ struct ThreadStopInfo { uint32_t data_count; lldb::addr_t data[8]; } exception; + + // eStopReasonFork / eStopReasonVFork + struct { + lldb::pid_t child_pid; + lldb::tid_t child_tid; + } fork; } details; }; } diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index dcd022b38eb9b..64901ba1476ef 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -249,6 +249,9 @@ enum StopReason { eStopReasonThreadExiting, eStopReasonInstrumentation, eStopReasonProcessorTrace, + eStopReasonFork, + eStopReasonVFork, + eStopReasonVForkDone, }; /// Command Return Status Types. diff --git a/lldb/packages/Python/lldbsuite/test/lldbutil.py b/lldb/packages/Python/lldbsuite/test/lldbutil.py index 5fff3726a65e6..20a6d28274b3d 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbutil.py @@ -252,6 +252,12 @@ def stop_reason_to_str(enum): return "watchpoint" elif enum == lldb.eStopReasonExec: return "exec" + elif enum == lldb.eStopReasonFork: + return "fork" + elif enum == lldb.eStopReasonVFork: + return "vfork" + elif enum == lldb.eStopReasonVForkDone: + return "vforkdone" elif enum == lldb.eStopReasonSignal: return "signal" elif enum == lldb.eStopReasonException: diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 4a1b53d4a5927..7b3d93905cce5 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -173,6 +173,7 @@ size_t SBThread::GetStopReasonDataCount() { case eStopReasonThreadExiting: case eStopReasonInstrumentation: case eStopReasonProcessorTrace: + case eStopReasonVForkDone: // There is no data for these stop reasons. return 0; @@ -195,6 +196,12 @@ size_t SBThread::GetStopReasonDataCount() { case eStopReasonException: return 1; + + case eStopReasonFork: + return 1; + + case eStopReasonVFork: + return 1; } } } @@ -225,6 +232,7 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { case eStopReasonThreadExiting: case eStopReasonInstrumentation: case eStopReasonProcessorTrace: + case eStopReasonVForkDone: // There is no data for these stop reasons. return 0; @@ -258,6 +266,12 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { case eStopReasonException: return stop_info_sp->GetValue(); + + case eStopReasonFork: + return stop_info_sp->GetValue(); + + case eStopReasonVFork: + return stop_info_sp->GetValue(); } } } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 6694e99267b3c..49f560122e514 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -659,6 +659,12 @@ static const char *GetStopReasonString(StopReason stop_reason) { return "exec"; case eStopReasonProcessorTrace: return "processor trace"; + case eStopReasonFork: + return "fork"; + case eStopReasonVFork: + return "vfork"; + case eStopReasonVForkDone: + return "vforkdone"; case eStopReasonInstrumentation: case eStopReasonInvalid: case eStopReasonPlanComplete: @@ -934,6 +940,22 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( } } + // Include child process PID/TID for forks. + if (tid_stop_info.reason == eStopReasonFork || + tid_stop_info.reason == eStopReasonVFork) { + assert(bool(m_extensions_supported & + NativeProcessProtocol::Extension::multiprocess)); + if (tid_stop_info.reason == eStopReasonFork) + assert(bool(m_extensions_supported & + NativeProcessProtocol::Extension::fork)); + if (tid_stop_info.reason == eStopReasonVFork) + assert(bool(m_extensions_supported & + NativeProcessProtocol::Extension::vfork)); + response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str, + tid_stop_info.details.fork.child_pid, + tid_stop_info.details.fork.child_tid); + } + return SendPacketNoLock(response.GetString()); } diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 5af8567733e3d..a5a3f8126e642 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -822,6 +822,9 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp, case eStopReasonWatchpoint: case eStopReasonException: case eStopReasonExec: + case eStopReasonFork: + case eStopReasonVFork: + case eStopReasonVForkDone: case eStopReasonThreadExiting: case eStopReasonInstrumentation: case eStopReasonProcessorTrace: diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index ed40356bef604..061500152a499 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -131,6 +131,9 @@ void StackFrameList::ResetCurrentInlinedDepth() { case eStopReasonWatchpoint: case eStopReasonException: case eStopReasonExec: + case eStopReasonFork: + case eStopReasonVFork: + case eStopReasonVForkDone: case eStopReasonSignal: // In all these cases we want to stop in the deepest frame. m_current_inlined_pc = curr_pc; diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 57cfaddac6d23..b423f1b5f1fe2 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -1679,6 +1679,12 @@ std::string Thread::StopReasonAsString(lldb::StopReason reason) { return "exception"; case eStopReasonExec: return "exec"; + case eStopReasonFork: + return "fork"; + case eStopReasonVFork: + return "vfork"; + case eStopReasonVForkDone: + return "vfork done"; case eStopReasonPlanComplete: return "plan complete"; case eStopReasonThreadExiting: diff --git a/lldb/tools/lldb-vscode/JSONUtils.cpp b/lldb/tools/lldb-vscode/JSONUtils.cpp index 6894ec0fff839..a64e9778074a0 100644 --- a/lldb/tools/lldb-vscode/JSONUtils.cpp +++ b/lldb/tools/lldb-vscode/JSONUtils.cpp @@ -878,6 +878,15 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, case lldb::eStopReasonExec: body.try_emplace("reason", "entry"); break; + case lldb::eStopReasonFork: + body.try_emplace("reason", "fork"); + break; + case lldb::eStopReasonVFork: + body.try_emplace("reason", "vfork"); + break; + case lldb::eStopReasonVForkDone: + body.try_emplace("reason", "vforkdone"); + break; case lldb::eStopReasonThreadExiting: case lldb::eStopReasonInvalid: case lldb::eStopReasonNone: diff --git a/lldb/tools/lldb-vscode/LLDBUtils.cpp b/lldb/tools/lldb-vscode/LLDBUtils.cpp index a5bc400dfccce..621f4ec37c83d 100644 --- a/lldb/tools/lldb-vscode/LLDBUtils.cpp +++ b/lldb/tools/lldb-vscode/LLDBUtils.cpp @@ -56,6 +56,9 @@ bool ThreadHasStopReason(lldb::SBThread &thread) { case lldb::eStopReasonException: case lldb::eStopReasonExec: case lldb::eStopReasonProcessorTrace: + case lldb::eStopReasonFork: + case lldb::eStopReasonVFork: + case lldb::eStopReasonVForkDone: return true; case lldb::eStopReasonThreadExiting: case lldb::eStopReasonInvalid: