1 //===-- NativeProcessNetBSD.cpp -------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "NativeProcessNetBSD.h"
11 #include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
12 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
13 #include "lldb/Host/HostProcess.h"
14 #include "lldb/Host/common/NativeRegisterContext.h"
15 #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Utility/State.h"
18 #include "llvm/Support/Errno.h"
20 // System includes - They have to be included after framework includes because
21 // they define some macros which collide with variable names in other modules
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <sys/sysctl.h>
27 #include <uvm/uvm_prot.h>
33 using namespace lldb_private
;
34 using namespace lldb_private::process_netbsd
;
37 // Simple helper function to ensure flags are enabled on the given file
39 static Status
EnsureFDFlags(int fd
, int flags
) {
42 int status
= fcntl(fd
, F_GETFL
);
44 error
.SetErrorToErrno();
48 if (fcntl(fd
, F_SETFL
, status
| flags
) == -1) {
49 error
.SetErrorToErrno();
56 // Public Static Methods
58 llvm::Expected
<std::unique_ptr
<NativeProcessProtocol
>>
59 NativeProcessNetBSD::Manager::Launch(ProcessLaunchInfo
&launch_info
,
60 NativeDelegate
&native_delegate
) {
61 Log
*log
= GetLog(POSIXLog::Process
);
64 ::pid_t pid
= ProcessLauncherPosixFork()
65 .LaunchProcess(launch_info
, status
)
67 LLDB_LOG(log
, "pid = {0:x}", pid
);
69 LLDB_LOG(log
, "failed to launch process: {0}", status
);
70 return status
.ToError();
73 // Wait for the child process to trap on its call to execve.
75 ::pid_t wpid
= llvm::sys::RetryAfterSignal(-1, ::waitpid
, pid
, &wstatus
, 0);
78 if (!WIFSTOPPED(wstatus
)) {
79 LLDB_LOG(log
, "Could not sync with inferior process: wstatus={1}",
80 WaitStatus::Decode(wstatus
));
81 return llvm::make_error
<StringError
>("Could not sync with inferior process",
82 llvm::inconvertibleErrorCode());
84 LLDB_LOG(log
, "inferior started, now in stopped state");
86 ProcessInstanceInfo Info
;
87 if (!Host::GetProcessInfo(pid
, Info
)) {
88 return llvm::make_error
<StringError
>("Cannot get process architecture",
89 llvm::inconvertibleErrorCode());
92 // Set the architecture to the exe architecture.
93 LLDB_LOG(log
, "pid = {0:x}, detected architecture {1}", pid
,
94 Info
.GetArchitecture().GetArchitectureName());
96 std::unique_ptr
<NativeProcessNetBSD
> process_up(new NativeProcessNetBSD(
97 pid
, launch_info
.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate
,
98 Info
.GetArchitecture(), m_mainloop
));
100 status
= process_up
->SetupTrace();
102 return status
.ToError();
104 for (const auto &thread
: process_up
->m_threads
)
105 static_cast<NativeThreadNetBSD
&>(*thread
).SetStoppedBySignal(SIGSTOP
);
106 process_up
->SetState(StateType::eStateStopped
, false);
108 return std::move(process_up
);
111 llvm::Expected
<std::unique_ptr
<NativeProcessProtocol
>>
112 NativeProcessNetBSD::Manager::Attach(
113 lldb::pid_t pid
, NativeProcessProtocol::NativeDelegate
&native_delegate
) {
114 Log
*log
= GetLog(POSIXLog::Process
);
115 LLDB_LOG(log
, "pid = {0:x}", pid
);
117 // Retrieve the architecture for the running process.
118 ProcessInstanceInfo Info
;
119 if (!Host::GetProcessInfo(pid
, Info
)) {
120 return llvm::make_error
<StringError
>("Cannot get process architecture",
121 llvm::inconvertibleErrorCode());
124 std::unique_ptr
<NativeProcessNetBSD
> process_up(new NativeProcessNetBSD(
125 pid
, -1, native_delegate
, Info
.GetArchitecture(), m_mainloop
));
127 Status status
= process_up
->Attach();
128 if (!status
.Success())
129 return status
.ToError();
131 return std::move(process_up
);
134 NativeProcessNetBSD::Extension
135 NativeProcessNetBSD::Manager::GetSupportedExtensions() const {
136 return Extension::multiprocess
| Extension::fork
| Extension::vfork
|
137 Extension::pass_signals
| Extension::auxv
| Extension::libraries_svr4
|
141 // Public Instance Methods
143 NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid
, int terminal_fd
,
144 NativeDelegate
&delegate
,
145 const ArchSpec
&arch
,
147 : NativeProcessELF(pid
, terminal_fd
, delegate
), m_arch(arch
),
148 m_main_loop(mainloop
) {
149 if (m_terminal_fd
!= -1) {
150 Status status
= EnsureFDFlags(m_terminal_fd
, O_NONBLOCK
);
151 assert(status
.Success());
155 m_sigchld_handle
= mainloop
.RegisterSignal(
156 SIGCHLD
, [this](MainLoopBase
&) { SigchldHandler(); }, status
);
157 assert(m_sigchld_handle
&& status
.Success());
160 // Handles all waitpid events from the inferior process.
161 void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid
, int signal
) {
164 return MonitorSIGTRAP(pid
);
166 return MonitorSIGSTOP(pid
);
168 return MonitorSignal(pid
, signal
);
172 void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid
, WaitStatus status
) {
173 Log
*log
= GetLog(POSIXLog::Process
);
175 LLDB_LOG(log
, "got exit signal({0}) , pid = {1}", status
, pid
);
177 /* Stop Tracking All Threads attached to Process */
180 SetExitStatus(status
, true);
182 // Notify delegate that our process has exited.
183 SetState(StateType::eStateExited
, true);
186 void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid
) {
187 ptrace_siginfo_t info
;
189 const auto siginfo_err
=
190 PtraceWrapper(PT_GET_SIGINFO
, pid
, &info
, sizeof(info
));
192 // Get details on the signal raised.
193 if (siginfo_err
.Success()) {
194 // Handle SIGSTOP from LLGS (LLDB GDB Server)
195 if (info
.psi_siginfo
.si_code
== SI_USER
&&
196 info
.psi_siginfo
.si_pid
== ::getpid()) {
197 /* Stop Tracking all Threads attached to Process */
198 for (const auto &thread
: m_threads
) {
199 static_cast<NativeThreadNetBSD
&>(*thread
).SetStoppedBySignal(
200 SIGSTOP
, &info
.psi_siginfo
);
203 SetState(StateType::eStateStopped
, true);
207 void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid
) {
208 Log
*log
= GetLog(POSIXLog::Process
);
209 ptrace_siginfo_t info
;
211 const auto siginfo_err
=
212 PtraceWrapper(PT_GET_SIGINFO
, pid
, &info
, sizeof(info
));
214 // Get details on the signal raised.
215 if (siginfo_err
.Fail()) {
216 LLDB_LOG(log
, "PT_GET_SIGINFO failed {0}", siginfo_err
);
220 LLDB_LOG(log
, "got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid
,
221 info
.psi_lwpid
, info
.psi_siginfo
.si_code
);
222 NativeThreadNetBSD
*thread
= nullptr;
224 if (info
.psi_lwpid
> 0) {
225 for (const auto &t
: m_threads
) {
226 if (t
->GetID() == static_cast<lldb::tid_t
>(info
.psi_lwpid
)) {
227 thread
= static_cast<NativeThreadNetBSD
*>(t
.get());
230 static_cast<NativeThreadNetBSD
*>(t
.get())->SetStoppedWithNoReason();
233 LLDB_LOG(log
, "thread not found in m_threads, pid = {0}, LWP = {1}", pid
,
237 switch (info
.psi_siginfo
.si_code
) {
240 thread
->SetStoppedByBreakpoint();
241 FixupBreakpointPCAsNeeded(*thread
);
243 SetState(StateType::eStateStopped
, true);
247 thread
->SetStoppedByTrace();
248 SetState(StateType::eStateStopped
, true);
251 Status error
= ReinitializeThreads();
253 SetState(StateType::eStateInvalid
);
257 // Let our delegate know we have just exec'd.
260 for (const auto &thread
: m_threads
)
261 static_cast<NativeThreadNetBSD
&>(*thread
).SetStoppedByExec();
262 SetState(StateType::eStateStopped
, true);
267 Status error
= PtraceWrapper(PT_GET_PROCESS_STATE
, pid
, &pst
, sizeof(pst
));
269 SetState(StateType::eStateInvalid
);
274 if (pst
.pe_report_event
== PTRACE_VFORK_DONE
) {
275 if ((m_enabled_extensions
& Extension::vfork
) == Extension::vfork
) {
276 thread
->SetStoppedByVForkDone();
277 SetState(StateType::eStateStopped
, true);
280 PtraceWrapper(PT_CONTINUE
, pid
, reinterpret_cast<void *>(1), 0);
282 SetState(StateType::eStateInvalid
);
285 assert(pst
.pe_report_event
== PTRACE_FORK
||
286 pst
.pe_report_event
== PTRACE_VFORK
);
287 MonitorClone(pst
.pe_other_pid
, pst
.pe_report_event
== PTRACE_VFORK
,
294 Status error
= PtraceWrapper(PT_GET_PROCESS_STATE
, pid
, &pst
, sizeof(pst
));
296 SetState(StateType::eStateInvalid
);
300 switch (pst
.pe_report_event
) {
301 case PTRACE_LWP_CREATE
: {
302 LLDB_LOG(log
, "monitoring new thread, pid = {0}, LWP = {1}", pid
,
304 NativeThreadNetBSD
&t
= AddThread(pst
.pe_lwp
);
305 error
= t
.CopyWatchpointsFrom(
306 static_cast<NativeThreadNetBSD
&>(*GetCurrentThread()));
308 LLDB_LOG(log
, "failed to copy watchpoints to new thread {0}: {1}",
310 SetState(StateType::eStateInvalid
);
314 case PTRACE_LWP_EXIT
:
315 LLDB_LOG(log
, "removing exited thread, pid = {0}, LWP = {1}", pid
,
317 RemoveThread(pst
.pe_lwp
);
321 error
= PtraceWrapper(PT_CONTINUE
, pid
, reinterpret_cast<void *>(1), 0);
323 SetState(StateType::eStateInvalid
);
330 auto ®ctx
= static_cast<NativeRegisterContextNetBSD
&>(
331 thread
->GetRegisterContext());
332 uint32_t wp_index
= LLDB_INVALID_INDEX32
;
333 Status error
= regctx
.GetWatchpointHitIndex(
334 wp_index
, (uintptr_t)info
.psi_siginfo
.si_addr
);
337 "received error while checking for watchpoint hits, pid = "
338 "{0}, LWP = {1}, error = {2}",
339 pid
, info
.psi_lwpid
, error
);
340 if (wp_index
!= LLDB_INVALID_INDEX32
) {
341 thread
->SetStoppedByWatchpoint(wp_index
);
342 regctx
.ClearWatchpointHit(wp_index
);
343 SetState(StateType::eStateStopped
, true);
347 thread
->SetStoppedByTrace();
348 SetState(StateType::eStateStopped
, true);
353 // Either user-generated SIGTRAP or an unknown event that would
354 // otherwise leave the debugger hanging.
355 LLDB_LOG(log
, "unknown SIGTRAP, passing to generic handler");
356 MonitorSignal(pid
, SIGTRAP
);
359 void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid
, int signal
) {
360 Log
*log
= GetLog(POSIXLog::Process
);
361 ptrace_siginfo_t info
;
363 const auto siginfo_err
=
364 PtraceWrapper(PT_GET_SIGINFO
, pid
, &info
, sizeof(info
));
365 if (siginfo_err
.Fail()) {
366 LLDB_LOG(log
, "PT_LWPINFO failed {0}", siginfo_err
);
370 for (const auto &abs_thread
: m_threads
) {
371 NativeThreadNetBSD
&thread
= static_cast<NativeThreadNetBSD
&>(*abs_thread
);
372 assert(info
.psi_lwpid
>= 0);
373 if (info
.psi_lwpid
== 0 ||
374 static_cast<lldb::tid_t
>(info
.psi_lwpid
) == thread
.GetID())
375 thread
.SetStoppedBySignal(info
.psi_siginfo
.si_signo
, &info
.psi_siginfo
);
377 thread
.SetStoppedWithNoReason();
379 SetState(StateType::eStateStopped
, true);
382 Status
NativeProcessNetBSD::PtraceWrapper(int req
, lldb::pid_t pid
, void *addr
,
383 int data
, int *result
) {
384 Log
*log
= GetLog(POSIXLog::Ptrace
);
389 ret
= ptrace(req
, static_cast<::pid_t
>(pid
), addr
, data
);
392 error
.SetErrorToErrno();
397 LLDB_LOG(log
, "ptrace({0}, {1}, {2}, {3})={4:x}", req
, pid
, addr
, data
, ret
);
400 LLDB_LOG(log
, "ptrace() failed: {0}", error
);
405 static llvm::Expected
<ptrace_siginfo_t
> ComputeSignalInfo(
406 const std::vector
<std::unique_ptr
<NativeThreadProtocol
>> &threads
,
407 const ResumeActionList
&resume_actions
) {
408 // We need to account for three possible scenarios:
409 // 1. no signal being sent.
410 // 2. a signal being sent to one thread.
411 // 3. a signal being sent to the whole process.
413 // Count signaled threads. While at it, determine which signal is being sent
414 // and ensure there's only one.
415 size_t signaled_threads
= 0;
416 int signal
= LLDB_INVALID_SIGNAL_NUMBER
;
417 lldb::tid_t signaled_lwp
;
418 for (const auto &thread
: threads
) {
419 assert(thread
&& "thread list should not contain NULL threads");
420 const ResumeAction
*action
=
421 resume_actions
.GetActionForThread(thread
->GetID(), true);
423 if (action
->signal
!= LLDB_INVALID_SIGNAL_NUMBER
) {
425 if (action
->signal
!= signal
) {
426 if (signal
!= LLDB_INVALID_SIGNAL_NUMBER
)
427 return Status("NetBSD does not support passing multiple signals "
430 signal
= action
->signal
;
431 signaled_lwp
= thread
->GetID();
437 if (signaled_threads
== 0) {
438 ptrace_siginfo_t siginfo
;
439 siginfo
.psi_siginfo
.si_signo
= LLDB_INVALID_SIGNAL_NUMBER
;
443 if (signaled_threads
> 1 && signaled_threads
< threads
.size())
444 return Status("NetBSD does not support passing signal to 1<i<all threads")
447 ptrace_siginfo_t siginfo
;
448 siginfo
.psi_siginfo
.si_signo
= signal
;
449 siginfo
.psi_siginfo
.si_code
= SI_USER
;
450 siginfo
.psi_siginfo
.si_pid
= getpid();
451 siginfo
.psi_siginfo
.si_uid
= getuid();
452 if (signaled_threads
== 1)
453 siginfo
.psi_lwpid
= signaled_lwp
;
454 else // signal for the whole process
455 siginfo
.psi_lwpid
= 0;
459 Status
NativeProcessNetBSD::Resume(const ResumeActionList
&resume_actions
) {
460 Log
*log
= GetLog(POSIXLog::Process
);
461 LLDB_LOG(log
, "pid {0}", GetID());
465 Expected
<ptrace_siginfo_t
> siginfo
=
466 ComputeSignalInfo(m_threads
, resume_actions
);
468 return Status(siginfo
.takeError());
470 for (const auto &abs_thread
: m_threads
) {
471 assert(abs_thread
&& "thread list should not contain NULL threads");
472 NativeThreadNetBSD
&thread
= static_cast<NativeThreadNetBSD
&>(*abs_thread
);
474 const ResumeAction
*action
=
475 resume_actions
.GetActionForThread(thread
.GetID(), true);
476 // we need to explicit issue suspend requests, so it is simpler to map it
477 // into proper action
478 ResumeAction suspend_action
{thread
.GetID(), eStateSuspended
,
479 LLDB_INVALID_SIGNAL_NUMBER
};
481 if (action
== nullptr) {
482 LLDB_LOG(log
, "no action specified for pid {0} tid {1}", GetID(),
484 action
= &suspend_action
;
489 "processing resume action state {0} signal {1} for pid {2} tid {3}",
490 action
->state
, action
->signal
, GetID(), thread
.GetID());
492 switch (action
->state
) {
494 ret
= thread
.Resume();
497 ret
= thread
.SingleStep();
499 case eStateSuspended
:
501 if (action
->signal
!= LLDB_INVALID_SIGNAL_NUMBER
)
502 return Status("Passing signal to suspended thread unsupported");
504 ret
= thread
.Suspend();
508 return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
509 "for pid %" PRIu64
", tid %" PRIu64
,
510 __FUNCTION__
, StateAsCString(action
->state
), GetID(),
519 if (siginfo
->psi_siginfo
.si_signo
!= LLDB_INVALID_SIGNAL_NUMBER
) {
520 ret
= PtraceWrapper(PT_SET_SIGINFO
, GetID(), &siginfo
.get(),
524 signal
= siginfo
->psi_siginfo
.si_signo
;
528 PtraceWrapper(PT_CONTINUE
, GetID(), reinterpret_cast<void *>(1), signal
);
530 SetState(eStateRunning
, true);
534 Status
NativeProcessNetBSD::Halt() { return PtraceWrapper(PT_STOP
, GetID()); }
536 Status
NativeProcessNetBSD::Detach() {
539 // Stop monitoring the inferior.
540 m_sigchld_handle
.reset();
542 // Tell ptrace to detach from the process.
543 if (GetID() == LLDB_INVALID_PROCESS_ID
)
546 return PtraceWrapper(PT_DETACH
, GetID(), reinterpret_cast<void *>(1));
549 Status
NativeProcessNetBSD::Signal(int signo
) {
552 if (kill(GetID(), signo
))
553 error
.SetErrorToErrno();
558 Status
NativeProcessNetBSD::Interrupt() {
559 return PtraceWrapper(PT_STOP
, GetID());
562 Status
NativeProcessNetBSD::Kill() {
563 Log
*log
= GetLog(POSIXLog::Process
);
564 LLDB_LOG(log
, "pid {0}", GetID());
569 case StateType::eStateInvalid
:
570 case StateType::eStateExited
:
571 case StateType::eStateCrashed
:
572 case StateType::eStateDetached
:
573 case StateType::eStateUnloaded
:
574 // Nothing to do - the process is already dead.
575 LLDB_LOG(log
, "ignored for PID {0} due to current state: {1}", GetID(),
576 StateAsCString(m_state
));
579 case StateType::eStateConnected
:
580 case StateType::eStateAttaching
:
581 case StateType::eStateLaunching
:
582 case StateType::eStateStopped
:
583 case StateType::eStateRunning
:
584 case StateType::eStateStepping
:
585 case StateType::eStateSuspended
:
586 // We can try to kill a process in these states.
590 if (kill(GetID(), SIGKILL
) != 0) {
591 error
.SetErrorToErrno();
598 Status
NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr
,
599 MemoryRegionInfo
&range_info
) {
601 if (m_supports_mem_region
== LazyBool::eLazyBoolNo
) {
603 return Status("unsupported");
606 Status error
= PopulateMemoryRegionCache();
611 lldb::addr_t prev_base_address
= 0;
612 // FIXME start by finding the last region that is <= target address using
613 // binary search. Data is sorted.
614 // There can be a ton of regions on pthreads apps with lots of threads.
615 for (auto it
= m_mem_region_cache
.begin(); it
!= m_mem_region_cache
.end();
617 MemoryRegionInfo
&proc_entry_info
= it
->first
;
618 // Sanity check assumption that memory map entries are ascending.
619 assert((proc_entry_info
.GetRange().GetRangeBase() >= prev_base_address
) &&
620 "descending memory map entries detected, unexpected");
621 prev_base_address
= proc_entry_info
.GetRange().GetRangeBase();
622 UNUSED_IF_ASSERT_DISABLED(prev_base_address
);
623 // If the target address comes before this entry, indicate distance to next
625 if (load_addr
< proc_entry_info
.GetRange().GetRangeBase()) {
626 range_info
.GetRange().SetRangeBase(load_addr
);
627 range_info
.GetRange().SetByteSize(
628 proc_entry_info
.GetRange().GetRangeBase() - load_addr
);
629 range_info
.SetReadable(MemoryRegionInfo::OptionalBool::eNo
);
630 range_info
.SetWritable(MemoryRegionInfo::OptionalBool::eNo
);
631 range_info
.SetExecutable(MemoryRegionInfo::OptionalBool::eNo
);
632 range_info
.SetMapped(MemoryRegionInfo::OptionalBool::eNo
);
634 } else if (proc_entry_info
.GetRange().Contains(load_addr
)) {
635 // The target address is within the memory region we're processing here.
636 range_info
= proc_entry_info
;
639 // The target memory address comes somewhere after the region we just
642 // If we made it here, we didn't find an entry that contained the given
643 // address. Return the load_addr as start and the amount of bytes betwwen
644 // load address and the end of the memory as size.
645 range_info
.GetRange().SetRangeBase(load_addr
);
646 range_info
.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS
);
647 range_info
.SetReadable(MemoryRegionInfo::OptionalBool::eNo
);
648 range_info
.SetWritable(MemoryRegionInfo::OptionalBool::eNo
);
649 range_info
.SetExecutable(MemoryRegionInfo::OptionalBool::eNo
);
650 range_info
.SetMapped(MemoryRegionInfo::OptionalBool::eNo
);
654 Status
NativeProcessNetBSD::PopulateMemoryRegionCache() {
655 Log
*log
= GetLog(POSIXLog::Process
);
656 // If our cache is empty, pull the latest. There should always be at least
657 // one memory region if memory region handling is supported.
658 if (!m_mem_region_cache
.empty()) {
659 LLDB_LOG(log
, "reusing {0} cached memory region entries",
660 m_mem_region_cache
.size());
664 struct kinfo_vmentry
*vm
;
666 vm
= kinfo_getvmmap(GetID(), &count
);
668 m_supports_mem_region
= LazyBool::eLazyBoolNo
;
670 error
.SetErrorString("not supported");
673 for (i
= 0; i
< count
; i
++) {
674 MemoryRegionInfo info
;
676 info
.GetRange().SetRangeBase(vm
[i
].kve_start
);
677 info
.GetRange().SetRangeEnd(vm
[i
].kve_end
);
678 info
.SetMapped(MemoryRegionInfo::OptionalBool::eYes
);
680 if (vm
[i
].kve_protection
& VM_PROT_READ
)
681 info
.SetReadable(MemoryRegionInfo::OptionalBool::eYes
);
683 info
.SetReadable(MemoryRegionInfo::OptionalBool::eNo
);
685 if (vm
[i
].kve_protection
& VM_PROT_WRITE
)
686 info
.SetWritable(MemoryRegionInfo::OptionalBool::eYes
);
688 info
.SetWritable(MemoryRegionInfo::OptionalBool::eNo
);
690 if (vm
[i
].kve_protection
& VM_PROT_EXECUTE
)
691 info
.SetExecutable(MemoryRegionInfo::OptionalBool::eYes
);
693 info
.SetExecutable(MemoryRegionInfo::OptionalBool::eNo
);
695 if (vm
[i
].kve_path
[0])
696 info
.SetName(vm
[i
].kve_path
);
698 m_mem_region_cache
.emplace_back(info
,
699 FileSpec(info
.GetName().GetCString()));
703 if (m_mem_region_cache
.empty()) {
704 // No entries after attempting to read them. This shouldn't happen. Assume
705 // we don't support map entries.
706 LLDB_LOG(log
, "failed to find any vmmap entries, assuming no support "
707 "for memory region metadata retrieval");
708 m_supports_mem_region
= LazyBool::eLazyBoolNo
;
710 error
.SetErrorString("not supported");
713 LLDB_LOG(log
, "read {0} memory region entries from process {1}",
714 m_mem_region_cache
.size(), GetID());
715 // We support memory retrieval, remember that.
716 m_supports_mem_region
= LazyBool::eLazyBoolYes
;
720 lldb::addr_t
NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
721 // punt on this for now
722 return LLDB_INVALID_ADDRESS
;
725 size_t NativeProcessNetBSD::UpdateThreads() { return m_threads
.size(); }
727 Status
NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr
, uint32_t size
,
730 return Status("NativeProcessNetBSD does not support hardware breakpoints");
732 return SetSoftwareBreakpoint(addr
, size
);
735 Status
NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path
,
736 FileSpec
&file_spec
) {
737 Status error
= PopulateMemoryRegionCache();
741 FileSpec
module_file_spec(module_path
);
742 FileSystem::Instance().Resolve(module_file_spec
);
745 for (const auto &it
: m_mem_region_cache
) {
746 if (it
.second
.GetFilename() == module_file_spec
.GetFilename()) {
747 file_spec
= it
.second
;
751 return Status("Module file (%s) not found in process' memory map!",
752 module_file_spec
.GetFilename().AsCString());
755 Status
NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef
&file_name
,
756 lldb::addr_t
&load_addr
) {
757 load_addr
= LLDB_INVALID_ADDRESS
;
758 Status error
= PopulateMemoryRegionCache();
762 FileSpec
file(file_name
);
763 for (const auto &it
: m_mem_region_cache
) {
764 if (it
.second
== file
) {
765 load_addr
= it
.first
.GetRange().GetRangeBase();
769 return Status("No load address found for file %s.", file_name
.str().c_str());
772 void NativeProcessNetBSD::SigchldHandler() {
773 Log
*log
= GetLog(POSIXLog::Process
);
775 ::pid_t wait_pid
= llvm::sys::RetryAfterSignal(-1, waitpid
, GetID(), &status
,
781 if (wait_pid
== -1) {
782 Status
error(errno
, eErrorTypePOSIX
);
783 LLDB_LOG(log
, "waitpid ({0}, &status, _) failed: {1}", GetID(), error
);
787 WaitStatus wait_status
= WaitStatus::Decode(status
);
788 bool exited
= wait_status
.type
== WaitStatus::Exit
||
789 (wait_status
.type
== WaitStatus::Signal
&&
790 wait_pid
== static_cast<::pid_t
>(GetID()));
793 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
794 GetID(), wait_pid
, status
, exited
);
797 MonitorExited(wait_pid
, wait_status
);
799 assert(wait_status
.type
== WaitStatus::Stop
);
800 MonitorCallback(wait_pid
, wait_status
.status
);
804 bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id
) {
805 for (const auto &thread
: m_threads
) {
806 assert(thread
&& "thread list should not contain NULL threads");
807 if (thread
->GetID() == thread_id
) {
808 // We have this thread.
813 // We don't have this thread.
817 NativeThreadNetBSD
&NativeProcessNetBSD::AddThread(lldb::tid_t thread_id
) {
818 Log
*log
= GetLog(POSIXLog::Thread
);
819 LLDB_LOG(log
, "pid {0} adding thread with tid {1}", GetID(), thread_id
);
821 assert(thread_id
> 0);
822 assert(!HasThreadNoLock(thread_id
) &&
823 "attempted to add a thread by id that already exists");
825 // If this is the first thread, save it as the current thread
826 if (m_threads
.empty())
827 SetCurrentThreadID(thread_id
);
829 m_threads
.push_back(std::make_unique
<NativeThreadNetBSD
>(*this, thread_id
));
830 return static_cast<NativeThreadNetBSD
&>(*m_threads
.back());
833 void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id
) {
834 Log
*log
= GetLog(POSIXLog::Thread
);
835 LLDB_LOG(log
, "pid {0} removing thread with tid {1}", GetID(), thread_id
);
837 assert(thread_id
> 0);
838 assert(HasThreadNoLock(thread_id
) &&
839 "attempted to remove a thread that does not exist");
841 for (auto it
= m_threads
.begin(); it
!= m_threads
.end(); ++it
) {
842 if ((*it
)->GetID() == thread_id
) {
849 Status
NativeProcessNetBSD::Attach() {
850 // Attach to the requested process.
851 // An attach will cause the thread to stop with a SIGSTOP.
852 Status status
= PtraceWrapper(PT_ATTACH
, m_pid
);
857 // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
858 // point we should have a thread stopped if waitpid succeeds.
859 if ((wstatus
= llvm::sys::RetryAfterSignal(-1, waitpid
, m_pid
, nullptr,
861 return Status(errno
, eErrorTypePOSIX
);
863 // Initialize threads and tracing status
864 // NB: this needs to be called before we set thread state
865 status
= SetupTrace();
869 for (const auto &thread
: m_threads
)
870 static_cast<NativeThreadNetBSD
&>(*thread
).SetStoppedBySignal(SIGSTOP
);
872 // Let our process instance know the thread has stopped.
873 SetCurrentThreadID(m_threads
.front()->GetID());
874 SetState(StateType::eStateStopped
, false);
878 Status
NativeProcessNetBSD::ReadMemory(lldb::addr_t addr
, void *buf
,
879 size_t size
, size_t &bytes_read
) {
880 unsigned char *dst
= static_cast<unsigned char *>(buf
);
881 struct ptrace_io_desc io
;
883 Log
*log
= GetLog(POSIXLog::Memory
);
884 LLDB_LOG(log
, "addr = {0}, buf = {1}, size = {2}", addr
, buf
, size
);
887 io
.piod_op
= PIOD_READ_D
;
891 io
.piod_offs
= (void *)(addr
+ bytes_read
);
892 io
.piod_addr
= dst
+ bytes_read
;
894 Status error
= NativeProcessNetBSD::PtraceWrapper(PT_IO
, GetID(), &io
);
895 if (error
.Fail() || io
.piod_len
== 0)
898 bytes_read
+= io
.piod_len
;
899 io
.piod_len
= size
- bytes_read
;
900 } while (bytes_read
< size
);
905 Status
NativeProcessNetBSD::WriteMemory(lldb::addr_t addr
, const void *buf
,
906 size_t size
, size_t &bytes_written
) {
907 const unsigned char *src
= static_cast<const unsigned char *>(buf
);
909 struct ptrace_io_desc io
;
911 Log
*log
= GetLog(POSIXLog::Memory
);
912 LLDB_LOG(log
, "addr = {0}, buf = {1}, size = {2}", addr
, buf
, size
);
915 io
.piod_op
= PIOD_WRITE_D
;
920 const_cast<void *>(static_cast<const void *>(src
+ bytes_written
));
921 io
.piod_offs
= (void *)(addr
+ bytes_written
);
923 Status error
= NativeProcessNetBSD::PtraceWrapper(PT_IO
, GetID(), &io
);
924 if (error
.Fail() || io
.piod_len
== 0)
927 bytes_written
+= io
.piod_len
;
928 io
.piod_len
= size
- bytes_written
;
929 } while (bytes_written
< size
);
934 llvm::ErrorOr
<std::unique_ptr
<llvm::MemoryBuffer
>>
935 NativeProcessNetBSD::GetAuxvData() const {
937 * ELF_AUX_ENTRIES is currently restricted to kernel
938 * (<sys/exec_elf.h> r. 1.155 specifies 15)
940 * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
941 * information isn't needed.
943 size_t auxv_size
= 100 * sizeof(AuxInfo
);
945 ErrorOr
<std::unique_ptr
<WritableMemoryBuffer
>> buf
=
946 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size
);
948 struct ptrace_io_desc io
;
949 io
.piod_op
= PIOD_READ_AUXV
;
951 io
.piod_addr
= static_cast<void *>(buf
.get()->getBufferStart());
952 io
.piod_len
= auxv_size
;
954 Status error
= NativeProcessNetBSD::PtraceWrapper(PT_IO
, GetID(), &io
);
957 return std::error_code(error
.GetError(), std::generic_category());
960 return std::error_code(ECANCELED
, std::generic_category());
962 return std::move(buf
);
965 Status
NativeProcessNetBSD::SetupTrace() {
966 // Enable event reporting
967 ptrace_event_t events
;
969 PtraceWrapper(PT_GET_EVENT_MASK
, GetID(), &events
, sizeof(events
));
972 // TODO: PTRACE_POSIX_SPAWN?
973 events
.pe_set_event
|= PTRACE_LWP_CREATE
| PTRACE_LWP_EXIT
| PTRACE_FORK
|
974 PTRACE_VFORK
| PTRACE_VFORK_DONE
;
975 status
= PtraceWrapper(PT_SET_EVENT_MASK
, GetID(), &events
, sizeof(events
));
979 return ReinitializeThreads();
982 Status
NativeProcessNetBSD::ReinitializeThreads() {
986 // Initialize new thread
988 struct ptrace_lwpstatus info
= {};
991 struct ptrace_lwpinfo info
= {};
995 Status error
= PtraceWrapper(op
, GetID(), &info
, sizeof(info
));
1000 // Reinitialize from scratch threads and register them in process
1001 while (info
.pl_lwpid
!= 0) {
1002 AddThread(info
.pl_lwpid
);
1003 error
= PtraceWrapper(op
, GetID(), &info
, sizeof(info
));
1012 void NativeProcessNetBSD::MonitorClone(::pid_t child_pid
, bool is_vfork
,
1013 NativeThreadNetBSD
&parent_thread
) {
1014 Log
*log
= GetLog(POSIXLog::Process
);
1015 LLDB_LOG(log
, "clone, child_pid={0}", child_pid
);
1019 llvm::sys::RetryAfterSignal(-1, ::waitpid
, child_pid
, &status
, 0);
1020 if (wait_pid
!= child_pid
) {
1022 "waiting for pid {0} failed. Assuming the pid has "
1023 "disappeared in the meantime",
1027 if (WIFEXITED(status
)) {
1029 "waiting for pid {0} returned an 'exited' event. Not "
1035 ptrace_siginfo_t info
;
1036 const auto siginfo_err
=
1037 PtraceWrapper(PT_GET_SIGINFO
, child_pid
, &info
, sizeof(info
));
1038 if (siginfo_err
.Fail()) {
1039 LLDB_LOG(log
, "PT_GET_SIGINFO failed {0}", siginfo_err
);
1042 assert(info
.psi_lwpid
>= 0);
1043 lldb::tid_t child_tid
= info
.psi_lwpid
;
1045 std::unique_ptr
<NativeProcessNetBSD
> child_process
{
1046 new NativeProcessNetBSD(static_cast<::pid_t
>(child_pid
), m_terminal_fd
,
1047 m_delegate
, m_arch
, m_main_loop
)};
1049 child_process
->m_software_breakpoints
= m_software_breakpoints
;
1051 Extension expected_ext
= is_vfork
? Extension::vfork
: Extension::fork
;
1052 if ((m_enabled_extensions
& expected_ext
) == expected_ext
) {
1053 child_process
->SetupTrace();
1054 for (const auto &thread
: child_process
->m_threads
)
1055 static_cast<NativeThreadNetBSD
&>(*thread
).SetStoppedBySignal(SIGSTOP
);
1056 child_process
->SetState(StateType::eStateStopped
, false);
1058 m_delegate
.NewSubprocess(this, std::move(child_process
));
1060 parent_thread
.SetStoppedByVFork(child_pid
, child_tid
);
1062 parent_thread
.SetStoppedByFork(child_pid
, child_tid
);
1063 SetState(StateType::eStateStopped
, true);
1065 child_process
->Detach();
1067 PtraceWrapper(PT_CONTINUE
, GetID(), reinterpret_cast<void *>(1), 0);
1068 if (pt_error
.Fail()) {
1069 LLDB_LOG_ERROR(log
, std::move(pt_error
.ToError()),
1070 "unable to resume parent process {1}: {0}", GetID());
1071 SetState(StateType::eStateInvalid
);
1076 llvm::Expected
<std::string
>
1077 NativeProcessNetBSD::SaveCore(llvm::StringRef path_hint
) {
1078 llvm::SmallString
<128> path
{path_hint
};
1081 // Try with the suggested path first.
1082 if (!path
.empty()) {
1083 error
= PtraceWrapper(PT_DUMPCORE
, GetID(), path
.data(), path
.size());
1085 return path
.str().str();
1087 // If the request errored, fall back to a generic temporary file.
1090 if (std::error_code errc
=
1091 llvm::sys::fs::createTemporaryFile("lldb", "core", path
))
1092 return llvm::createStringError(errc
, "Unable to create a temporary file");
1094 error
= PtraceWrapper(PT_DUMPCORE
, GetID(), path
.data(), path
.size());
1096 return error
.ToError();
1097 return path
.str().str();