[lldb] [Process/NetBSD] Report fork/vfork events to LLGS

Differential Revision: https://reviews.llvm.org/D100554
This commit is contained in:
Michał Górny 2021-04-15 15:08:03 +02:00
parent 65f2a75737
commit 06215023f4
5 changed files with 96 additions and 22 deletions

View File

@ -863,7 +863,7 @@ def checkForkVForkSupport():
from lldbsuite.test import lldbplatformutil
platform = lldbplatformutil.getPlatform()
if platform not in ["freebsd", "linux"]:
if platform not in ["freebsd", "linux", "netbsd"]:
configuration.skip_categories.append("fork")

View File

@ -133,13 +133,19 @@ NativeProcessNetBSD::Factory::Attach(
return std::move(process_up);
}
NativeProcessNetBSD::Extension
NativeProcessNetBSD::Factory::GetSupportedExtensions() const {
return Extension::multiprocess | Extension::fork | Extension::vfork;
}
// Public Instance Methods
NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
NativeDelegate &delegate,
const ArchSpec &arch,
MainLoop &mainloop)
: NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
: NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
m_main_loop(mainloop) {
if (m_terminal_fd != -1) {
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
assert(status.Success());
@ -264,14 +270,23 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
return;
}
assert(thread);
if (pst.pe_report_event == PTRACE_VFORK_DONE) {
Status error =
PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
if (error.Fail())
SetState(StateType::eStateInvalid);
return;
} else
MonitorClone(pst.pe_other_pid);
if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {
thread->SetStoppedByVForkDone();
SetState(StateType::eStateStopped, true);
} else {
Status error =
PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
if (error.Fail())
SetState(StateType::eStateInvalid);
}
} else {
assert(pst.pe_report_event == PTRACE_FORK ||
pst.pe_report_event == PTRACE_VFORK);
MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK,
*thread);
}
return;
}
case TRAP_LWP: {
@ -994,7 +1009,8 @@ Status NativeProcessNetBSD::ReinitializeThreads() {
return error;
}
void NativeProcessNetBSD::MonitorClone(::pid_t child_pid) {
void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
NativeThreadNetBSD &parent_thread) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "clone, child_pid={0}", child_pid);
@ -1016,16 +1032,43 @@ void NativeProcessNetBSD::MonitorClone(::pid_t child_pid) {
return;
}
MainLoop unused_loop;
NativeProcessNetBSD child_process{static_cast<::pid_t>(child_pid),
m_terminal_fd, m_delegate, m_arch,
unused_loop};
child_process.Detach();
Status pt_error =
PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
if (pt_error.Fail()) {
LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),
"unable to resume parent process {1}: {0}", GetID());
SetState(StateType::eStateInvalid);
ptrace_siginfo_t info;
const auto siginfo_err =
PtraceWrapper(PT_GET_SIGINFO, child_pid, &info, sizeof(info));
if (siginfo_err.Fail()) {
LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);
return;
}
assert(info.psi_lwpid >= 0);
lldb::tid_t child_tid = info.psi_lwpid;
std::unique_ptr<NativeProcessNetBSD> child_process{
new NativeProcessNetBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,
m_delegate, m_arch, m_main_loop)};
if (!is_vfork)
child_process->m_software_breakpoints = m_software_breakpoints;
Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
if ((m_enabled_extensions & expected_ext) == expected_ext) {
child_process->SetupTrace();
for (const auto &thread : child_process->m_threads)
static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
child_process->SetState(StateType::eStateStopped, false);
m_delegate.NewSubprocess(this, std::move(child_process));
if (is_vfork)
parent_thread.SetStoppedByVFork(child_pid, child_tid);
else
parent_thread.SetStoppedByFork(child_pid, child_tid);
SetState(StateType::eStateStopped, true);
} else {
child_process->Detach();
Status pt_error =
PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
if (pt_error.Fail()) {
LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),
"unable to resume parent process {1}: {0}", GetID());
SetState(StateType::eStateInvalid);
}
}
}

View File

@ -36,6 +36,8 @@ public:
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
Extension GetSupportedExtensions() const override;
};
// NativeProcessProtocol Interface
@ -89,6 +91,7 @@ public:
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
MainLoop& m_main_loop;
LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
@ -106,7 +109,8 @@ private:
void MonitorSIGSTOP(lldb::pid_t pid);
void MonitorSIGTRAP(lldb::pid_t pid);
void MonitorSignal(lldb::pid_t pid, int signal);
void MonitorClone(::pid_t child_pid);
void MonitorClone(::pid_t child_pid, bool is_vfork,
NativeThreadNetBSD &parent_thread);
Status PopulateMemoryRegionCache();
void SigchldHandler();

View File

@ -130,6 +130,30 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
m_stop_info.details.signal.signo = SIGTRAP;
}
void NativeThreadNetBSD::SetStoppedByFork(lldb::pid_t child_pid,
lldb::tid_t child_tid) {
SetStopped();
m_stop_info.reason = StopReason::eStopReasonFork;
m_stop_info.details.fork.child_pid = child_pid;
m_stop_info.details.fork.child_tid = child_tid;
}
void NativeThreadNetBSD::SetStoppedByVFork(lldb::pid_t child_pid,
lldb::tid_t child_tid) {
SetStopped();
m_stop_info.reason = StopReason::eStopReasonVFork;
m_stop_info.details.fork.child_pid = child_pid;
m_stop_info.details.fork.child_tid = child_tid;
}
void NativeThreadNetBSD::SetStoppedByVForkDone() {
SetStopped();
m_stop_info.reason = StopReason::eStopReasonVForkDone;
}
void NativeThreadNetBSD::SetStoppedWithNoReason() {
SetStopped();

View File

@ -59,6 +59,9 @@ private:
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
void SetStoppedByVForkDone();
void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();