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
|
||||
|
||||
platform = lldbplatformutil.getPlatform()
|
||||
if platform not in ["linux"]:
|
||||
if platform not in ["freebsd", "linux"]:
|
||||
configuration.skip_categories.append("fork")
|
||||
|
||||
|
||||
|
|
|
@ -128,13 +128,19 @@ NativeProcessFreeBSD::Factory::Attach(
|
|||
return std::move(process_up);
|
||||
}
|
||||
|
||||
NativeProcessFreeBSD::Extension
|
||||
NativeProcessFreeBSD::Factory::GetSupportedExtensions() const {
|
||||
return Extension::multiprocess | Extension::fork | Extension::vfork;
|
||||
}
|
||||
|
||||
// Public Instance Methods
|
||||
|
||||
NativeProcessFreeBSD::NativeProcessFreeBSD(::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());
|
||||
|
@ -247,19 +253,6 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) {
|
|||
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) {
|
||||
for (const auto &t : m_threads) {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
assert(info.pl_siginfo.si_signo == SIGTRAP);
|
||||
LLDB_LOG(log, "SIGTRAP siginfo: si_code = {0}, pid = {1}",
|
||||
|
@ -933,7 +946,8 @@ bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const {
|
|||
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));
|
||||
LLDB_LOG(log, "fork, child_pid={0}", child_pid);
|
||||
|
||||
|
@ -955,16 +969,42 @@ void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid) {
|
|||
return;
|
||||
}
|
||||
|
||||
MainLoop unused_loop;
|
||||
NativeProcessFreeBSD 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, pt_error.ToError(),
|
||||
"unable to resume parent process {1}: {0}", GetID());
|
||||
SetState(StateType::eStateInvalid);
|
||||
struct ptrace_lwpinfo info;
|
||||
const auto siginfo_err = PtraceWrapper(PT_LWPINFO, child_pid, &info, sizeof(info));
|
||||
if (siginfo_err.Fail()) {
|
||||
LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);
|
||||
return;
|
||||
}
|
||||
assert(info.pl_event == PL_EVENT_SIGNAL);
|
||||
lldb::tid_t child_tid = info.pl_lwpid;
|
||||
|
||||
std::unique_ptr<NativeProcessFreeBSD> child_process{
|
||||
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>>
|
||||
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
|
||||
MainLoop &mainloop) const override;
|
||||
|
||||
Extension GetSupportedExtensions() const override;
|
||||
};
|
||||
|
||||
// NativeProcessProtocol Interface
|
||||
|
@ -96,6 +98,7 @@ protected:
|
|||
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;
|
||||
|
||||
|
@ -113,7 +116,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,
|
||||
NativeThreadFreeBSD &parent_thread);
|
||||
|
||||
Status PopulateMemoryRegionCache();
|
||||
void SigchldHandler();
|
||||
|
|
|
@ -130,6 +130,30 @@ void NativeThreadFreeBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
|
|||
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() {
|
||||
SetStopped();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue