Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -5436,13 +5436,39 @@ void ProcessGDBRemote::DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) { + lldb::pid_t orig_pid = m_gdb_comm.GetCurrentProcessID(); + + 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 + GetBreakpointSiteList().ForEach([this](BreakpointSite *bp_site) { + if (bp_site->IsEnabled() && + (bp_site->GetType() == BreakpointSite::eSoftware || + bp_site->GetType() == BreakpointSite::eExternal)) { + m_gdb_comm.SendGDBStoppointTypePacket( + eBreakpointSoftware, false, bp_site->GetLoadAddress(), + bp_site->GetTrapOpcodeMaxByteSize()); + } + }); + + // Reset gdb-remote to the original process. Thread ID does not really + // matter, the next command will set it anyway. + if (!m_gdb_comm.SetCurrentThread(m_thread_ids.front(), orig_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() : ""); - return; + LLDB_LOG(log, "ProcessGDBRemote::DidFork() detach packet send failed: {0}", + error.AsCString() ? error.AsCString() : ""); + return; } } Index: lldb/test/Shell/Subprocess/clone-follow-parent-softbp.test =================================================================== --- /dev/null +++ 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 Index: lldb/test/Shell/Subprocess/fork-follow-parent-softbp.test =================================================================== --- /dev/null +++ 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