forked from OSchip/llvm-project
[lldb] [Process/FreeBSD] Report fork/vfork events to LLGS
Differential Revision: https://reviews.llvm.org/D100547
This commit is contained in:
parent
4b9be5ac08
commit
65f2a75737
|
@ -863,7 +863,7 @@ def checkForkVForkSupport():
|
||||||
from lldbsuite.test import lldbplatformutil
|
from lldbsuite.test import lldbplatformutil
|
||||||
|
|
||||||
platform = lldbplatformutil.getPlatform()
|
platform = lldbplatformutil.getPlatform()
|
||||||
if platform not in ["linux"]:
|
if platform not in ["freebsd", "linux"]:
|
||||||
configuration.skip_categories.append("fork")
|
configuration.skip_categories.append("fork")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -128,13 +128,19 @@ NativeProcessFreeBSD::Factory::Attach(
|
||||||
return std::move(process_up);
|
return std::move(process_up);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NativeProcessFreeBSD::Extension
|
||||||
|
NativeProcessFreeBSD::Factory::GetSupportedExtensions() const {
|
||||||
|
return Extension::multiprocess | Extension::fork | Extension::vfork;
|
||||||
|
}
|
||||||
|
|
||||||
// Public Instance Methods
|
// Public Instance Methods
|
||||||
|
|
||||||
NativeProcessFreeBSD::NativeProcessFreeBSD(::pid_t pid, int terminal_fd,
|
NativeProcessFreeBSD::NativeProcessFreeBSD(::pid_t pid, int terminal_fd,
|
||||||
NativeDelegate &delegate,
|
NativeDelegate &delegate,
|
||||||
const ArchSpec &arch,
|
const ArchSpec &arch,
|
||||||
MainLoop &mainloop)
|
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) {
|
if (m_terminal_fd != -1) {
|
||||||
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
|
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
|
||||||
assert(status.Success());
|
assert(status.Success());
|
||||||
|
@ -247,19 +253,6 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.pl_flags & PL_FLAG_FORKED) {
|
|
||||||
MonitorClone(info.pl_child_pid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.pl_flags & PL_FLAG_VFORK_DONE) {
|
|
||||||
Status error =
|
|
||||||
PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
|
|
||||||
if (error.Fail())
|
|
||||||
SetState(StateType::eStateInvalid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.pl_lwpid > 0) {
|
if (info.pl_lwpid > 0) {
|
||||||
for (const auto &t : m_threads) {
|
for (const auto &t : m_threads) {
|
||||||
if (t->GetID() == static_cast<lldb::tid_t>(info.pl_lwpid))
|
if (t->GetID() == static_cast<lldb::tid_t>(info.pl_lwpid))
|
||||||
|
@ -271,6 +264,26 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
|
||||||
info.pl_lwpid);
|
info.pl_lwpid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info.pl_flags & PL_FLAG_FORKED) {
|
||||||
|
assert(thread);
|
||||||
|
MonitorClone(info.pl_child_pid, info.pl_flags & PL_FLAG_VFORKED, *thread);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.pl_flags & PL_FLAG_VFORK_DONE) {
|
||||||
|
assert(thread);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (info.pl_flags & PL_FLAG_SI) {
|
if (info.pl_flags & PL_FLAG_SI) {
|
||||||
assert(info.pl_siginfo.si_signo == SIGTRAP);
|
assert(info.pl_siginfo.si_signo == SIGTRAP);
|
||||||
LLDB_LOG(log, "SIGTRAP siginfo: si_code = {0}, pid = {1}",
|
LLDB_LOG(log, "SIGTRAP siginfo: si_code = {0}, pid = {1}",
|
||||||
|
@ -933,7 +946,8 @@ bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const {
|
||||||
return !m_arch.IsMIPS();
|
return !m_arch.IsMIPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid) {
|
void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
|
||||||
|
NativeThreadFreeBSD &parent_thread) {
|
||||||
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
|
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
|
||||||
LLDB_LOG(log, "fork, child_pid={0}", child_pid);
|
LLDB_LOG(log, "fork, child_pid={0}", child_pid);
|
||||||
|
|
||||||
|
@ -955,16 +969,42 @@ void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainLoop unused_loop;
|
struct ptrace_lwpinfo info;
|
||||||
NativeProcessFreeBSD child_process{static_cast<::pid_t>(child_pid),
|
const auto siginfo_err = PtraceWrapper(PT_LWPINFO, child_pid, &info, sizeof(info));
|
||||||
m_terminal_fd, m_delegate, m_arch,
|
if (siginfo_err.Fail()) {
|
||||||
unused_loop};
|
LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);
|
||||||
child_process.Detach();
|
return;
|
||||||
Status pt_error =
|
}
|
||||||
PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
|
assert(info.pl_event == PL_EVENT_SIGNAL);
|
||||||
if (pt_error.Fail()) {
|
lldb::tid_t child_tid = info.pl_lwpid;
|
||||||
LLDB_LOG_ERROR(log, pt_error.ToError(),
|
|
||||||
"unable to resume parent process {1}: {0}", GetID());
|
std::unique_ptr<NativeProcessFreeBSD> child_process{
|
||||||
SetState(StateType::eStateInvalid);
|
new NativeProcessFreeBSD(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<NativeThreadFreeBSD &>(*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, pt_error.ToError(),
|
||||||
|
"unable to resume parent process {1}: {0}", GetID());
|
||||||
|
SetState(StateType::eStateInvalid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ public:
|
||||||
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
|
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
|
||||||
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
|
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
|
||||||
MainLoop &mainloop) const override;
|
MainLoop &mainloop) const override;
|
||||||
|
|
||||||
|
Extension GetSupportedExtensions() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// NativeProcessProtocol Interface
|
// NativeProcessProtocol Interface
|
||||||
|
@ -96,6 +98,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
MainLoop::SignalHandleUP m_sigchld_handle;
|
MainLoop::SignalHandleUP m_sigchld_handle;
|
||||||
ArchSpec m_arch;
|
ArchSpec m_arch;
|
||||||
|
MainLoop& m_main_loop;
|
||||||
LazyBool m_supports_mem_region = eLazyBoolCalculate;
|
LazyBool m_supports_mem_region = eLazyBoolCalculate;
|
||||||
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
|
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
|
||||||
|
|
||||||
|
@ -113,7 +116,8 @@ private:
|
||||||
void MonitorSIGSTOP(lldb::pid_t pid);
|
void MonitorSIGSTOP(lldb::pid_t pid);
|
||||||
void MonitorSIGTRAP(lldb::pid_t pid);
|
void MonitorSIGTRAP(lldb::pid_t pid);
|
||||||
void MonitorSignal(lldb::pid_t pid, int signal);
|
void MonitorSignal(lldb::pid_t pid, int signal);
|
||||||
void MonitorClone(::pid_t child_pid);
|
void MonitorClone(::pid_t child_pid, bool is_vfork,
|
||||||
|
NativeThreadFreeBSD &parent_thread);
|
||||||
|
|
||||||
Status PopulateMemoryRegionCache();
|
Status PopulateMemoryRegionCache();
|
||||||
void SigchldHandler();
|
void SigchldHandler();
|
||||||
|
|
|
@ -130,6 +130,30 @@ void NativeThreadFreeBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
|
||||||
m_stop_info.details.signal.signo = SIGTRAP;
|
m_stop_info.details.signal.signo = SIGTRAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeThreadFreeBSD::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 NativeThreadFreeBSD::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 NativeThreadFreeBSD::SetStoppedByVForkDone() {
|
||||||
|
SetStopped();
|
||||||
|
|
||||||
|
m_stop_info.reason = StopReason::eStopReasonVForkDone;
|
||||||
|
}
|
||||||
|
|
||||||
void NativeThreadFreeBSD::SetStoppedWithNoReason() {
|
void NativeThreadFreeBSD::SetStoppedWithNoReason() {
|
||||||
SetStopped();
|
SetStopped();
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,9 @@ private:
|
||||||
void SetStoppedByTrace();
|
void SetStoppedByTrace();
|
||||||
void SetStoppedByExec();
|
void SetStoppedByExec();
|
||||||
void SetStoppedByWatchpoint(uint32_t wp_index);
|
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 SetStoppedWithNoReason();
|
||||||
void SetStopped();
|
void SetStopped();
|
||||||
void SetRunning();
|
void SetRunning();
|
||||||
|
|
Loading…
Reference in New Issue