[Lldb-commits] [lldb] 6c37984 - [lldb] [gdb-remote server] Introduce new stop reasons for fork and vfork

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Sat Apr 24 02:26:36 PDT 2021


Author: Michał Górny
Date: 2021-04-24T11:08:33+02:00
New Revision: 6c37984ebaf4ee01df6a9b3f78e45f70dcd6fb33

URL: https://github.com/llvm/llvm-project/commit/6c37984ebaf4ee01df6a9b3f78e45f70dcd6fb33
DIFF: https://github.com/llvm/llvm-project/commit/6c37984ebaf4ee01df6a9b3f78e45f70dcd6fb33.diff

LOG: [lldb] [gdb-remote server] Introduce new stop reasons for fork and vfork

Introduce three new stop reasons for fork, vfork and vforkdone events.
This includes server support for serializing fork/vfork events into
gdb-remote protocol.  The stop infos for the two base events take a pair
of PID and TID for the newly forked process.

Differential Revision: https://reviews.llvm.org/D100196

Added: 
    

Modified: 
    lldb/bindings/interface/SBThread.i
    lldb/bindings/interface/SBThreadPlan.i
    lldb/docs/python_api_enums.rst
    lldb/examples/python/performance.py
    lldb/include/lldb/API/SBThread.h
    lldb/include/lldb/API/SBThreadPlan.h
    lldb/include/lldb/Host/Debug.h
    lldb/include/lldb/lldb-enumerations.h
    lldb/packages/Python/lldbsuite/test/lldbutil.py
    lldb/source/API/SBThread.cpp
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/source/Target/Process.cpp
    lldb/source/Target/StackFrameList.cpp
    lldb/source/Target/Thread.cpp
    lldb/tools/lldb-vscode/JSONUtils.cpp
    lldb/tools/lldb-vscode/LLDBUtils.cpp

Removed: 
    


################################################################################
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:


        


More information about the lldb-commits mailing list