[Lldb-commits] [lldb] 8307869 - [lldb] [gdb-remote client] Remove breakpoints in forked processes

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Tue Aug 31 05:10:25 PDT 2021


Author: Michał Górny
Date: 2021-08-31T13:41:35+02:00
New Revision: 8307869a224633d3516d98071b45fdec7314f8a3

URL: https://github.com/llvm/llvm-project/commit/8307869a224633d3516d98071b45fdec7314f8a3
DIFF: https://github.com/llvm/llvm-project/commit/8307869a224633d3516d98071b45fdec7314f8a3.diff

LOG: [lldb] [gdb-remote client] Remove breakpoints in forked processes

Remove software breakpoints from forked processes in order to restore
the original program code before detaching it.

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

Added: 
    lldb/test/Shell/Subprocess/clone-follow-parent-softbp.test
    lldb/test/Shell/Subprocess/fork-follow-parent-softbp.test

Modified: 
    lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f135f8975cec7..f81e2acf3e17a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -5485,16 +5485,49 @@ CommandObject *ProcessGDBRemote::GetPluginCommandObject() {
   return m_command_sp.get();
 }
 
+void ProcessGDBRemote::DidForkSwitchSoftwareBreakpoints(bool enable) {
+  GetBreakpointSiteList().ForEach([this, enable](BreakpointSite *bp_site) {
+    if (bp_site->IsEnabled() &&
+        (bp_site->GetType() == BreakpointSite::eSoftware ||
+         bp_site->GetType() == BreakpointSite::eExternal)) {
+      m_gdb_comm.SendGDBStoppointTypePacket(
+          eBreakpointSoftware, enable, bp_site->GetLoadAddress(),
+          bp_site->GetTrapOpcodeMaxByteSize(), GetInterruptTimeout());
+    }
+  });
+}
+
 void ProcessGDBRemote::DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {
   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
 
+  lldb::pid_t parent_pid = m_gdb_comm.GetCurrentProcessID();
+  // Any valid TID will suffice, thread-relevant actions will set a proper TID
+  // anyway.
+  lldb::tid_t parent_tid = m_thread_ids.front();
+
+  if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) {
+    // Switch to the new process to clear breakpoints there.
+    if (!m_gdb_comm.SetCurrentThread(child_tid, child_pid)) {
+      LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to set pid/tid");
+      return;
+    }
+
+    // Disable all software breakpoints in the forked process.
+    DidForkSwitchSoftwareBreakpoints(false);
+
+    // Reset gdb-remote to the original process.
+    if (!m_gdb_comm.SetCurrentThread(parent_tid, parent_pid)) {
+      LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to reset pid/tid");
+      return;
+    }
+  }
+
   LLDB_LOG(log, "Detaching forked child {0}", child_pid);
   Status error = m_gdb_comm.Detach(false, child_pid);
   if (error.Fail()) {
-      LLDB_LOG(log,
-               "ProcessGDBRemote::DidFork() detach packet send failed: {0}",
-                error.AsCString() ? error.AsCString() : "<unknown error>");
-      return;
+    LLDB_LOG(log, "ProcessGDBRemote::DidFork() detach packet send failed: {0}",
+             error.AsCString() ? error.AsCString() : "<unknown error>");
+    return;
   }
 }
 

diff  --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index e86f697439500..70b3ca1ca3a22 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -462,6 +462,9 @@ class ProcessGDBRemote : public Process,
 
   ProcessGDBRemote(const ProcessGDBRemote &) = delete;
   const ProcessGDBRemote &operator=(const ProcessGDBRemote &) = delete;
+
+  // fork helpers
+  void DidForkSwitchSoftwareBreakpoints(bool enable);
 };
 
 } // namespace process_gdb_remote

diff  --git a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py b/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
index 5bbee0b33de81..0222e8453f7a0 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
@@ -147,7 +147,12 @@ def respond(self, packet):
         if packet == "s":
             return self.haltReason()
         if packet[0] == "H":
-            return self.selectThread(packet[1], int(packet[2:], 16))
+            tid = packet[2:]
+            if "." in tid:
+                assert tid.startswith("p")
+                # TODO: do we want to do anything with PID?
+                tid = tid.split(".", 1)[1]
+            return self.selectThread(packet[1], int(tid, 16))
         if packet[0:6] == "qXfer:":
             obj, read, annex, location = packet[6:].split(":")
             offset, length = [int(x, 16) for x in location.split(',')]

diff  --git a/lldb/test/Shell/Subprocess/clone-follow-parent-softbp.test b/lldb/test/Shell/Subprocess/clone-follow-parent-softbp.test
new file mode 100644
index 0000000000000..852ed9dcbce25
--- /dev/null
+++ b/lldb/test/Shell/Subprocess/clone-follow-parent-softbp.test
@@ -0,0 +1,13 @@
+# REQUIRES: native && (system-linux || system-netbsd)
+# clone() tests fails on arm64 Linux, PR #49899
+# UNSUPPORTED: system-linux && target-aarch64
+# RUN: %clangxx_host %p/Inputs/fork.cpp -DTEST_CLONE -o %t
+# RUN: %lldb -b -s %s %t | FileCheck %s
+b parent_func
+b child_func
+process launch
+# CHECK-NOT: function run in parent
+# CHECK: stop reason = breakpoint
+continue
+# CHECK: function run in parent
+# CHECK: child exited: 0

diff  --git a/lldb/test/Shell/Subprocess/fork-follow-parent-softbp.test b/lldb/test/Shell/Subprocess/fork-follow-parent-softbp.test
new file mode 100644
index 0000000000000..6618834ae4055
--- /dev/null
+++ b/lldb/test/Shell/Subprocess/fork-follow-parent-softbp.test
@@ -0,0 +1,12 @@
+# REQUIRES: native
+# UNSUPPORTED: system-windows
+# RUN: %clangxx_host %p/Inputs/fork.cpp -DTEST_FORK=fork -o %t
+# RUN: %lldb -b -s %s %t | FileCheck %s
+b parent_func
+b child_func
+process launch
+# CHECK-NOT: function run in parent
+# CHECK: stop reason = breakpoint
+continue
+# CHECK: function run in parent
+# CHECK: child exited: 0


        


More information about the lldb-commits mailing list