1 //===-- NativeProcessNetBSD.cpp -------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "NativeProcessNetBSD.h"
10
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"
19
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
22 // clang-format off
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <sys/sysctl.h>
26 #include <sys/wait.h>
27 #include <uvm/uvm_prot.h>
28 #include <elf.h>
29 #include <util.h>
30 // clang-format on
31
32 using namespace lldb;
33 using namespace lldb_private;
34 using namespace lldb_private::process_netbsd;
35 using namespace llvm;
36
37 // Simple helper function to ensure flags are enabled on the given file
38 // descriptor.
EnsureFDFlags(int fd,int flags)39 static Status EnsureFDFlags(int fd, int flags) {
40 Status error;
41
42 int status = fcntl(fd, F_GETFL);
43 if (status == -1) {
44 error.SetErrorToErrno();
45 return error;
46 }
47
48 if (fcntl(fd, F_SETFL, status | flags) == -1) {
49 error.SetErrorToErrno();
50 return error;
51 }
52
53 return error;
54 }
55
56 // Public Static Methods
57
58 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo & launch_info,NativeDelegate & native_delegate,MainLoop & mainloop) const59 NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
60 NativeDelegate &native_delegate,
61 MainLoop &mainloop) const {
62 Log *log = GetLog(POSIXLog::Process);
63
64 Status status;
65 ::pid_t pid = ProcessLauncherPosixFork()
66 .LaunchProcess(launch_info, status)
67 .GetProcessId();
68 LLDB_LOG(log, "pid = {0:x}", pid);
69 if (status.Fail()) {
70 LLDB_LOG(log, "failed to launch process: {0}", status);
71 return status.ToError();
72 }
73
74 // Wait for the child process to trap on its call to execve.
75 int wstatus;
76 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
77 assert(wpid == pid);
78 (void)wpid;
79 if (!WIFSTOPPED(wstatus)) {
80 LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
81 WaitStatus::Decode(wstatus));
82 return llvm::make_error<StringError>("Could not sync with inferior process",
83 llvm::inconvertibleErrorCode());
84 }
85 LLDB_LOG(log, "inferior started, now in stopped state");
86
87 ProcessInstanceInfo Info;
88 if (!Host::GetProcessInfo(pid, Info)) {
89 return llvm::make_error<StringError>("Cannot get process architecture",
90 llvm::inconvertibleErrorCode());
91 }
92
93 // Set the architecture to the exe architecture.
94 LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
95 Info.GetArchitecture().GetArchitectureName());
96
97 std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
98 pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
99 Info.GetArchitecture(), mainloop));
100
101 status = process_up->SetupTrace();
102 if (status.Fail())
103 return status.ToError();
104
105 for (const auto &thread : process_up->m_threads)
106 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
107 process_up->SetState(StateType::eStateStopped, false);
108
109 return std::move(process_up);
110 }
111
112 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const113 NativeProcessNetBSD::Factory::Attach(
114 lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
115 MainLoop &mainloop) const {
116 Log *log = GetLog(POSIXLog::Process);
117 LLDB_LOG(log, "pid = {0:x}", pid);
118
119 // Retrieve the architecture for the running process.
120 ProcessInstanceInfo Info;
121 if (!Host::GetProcessInfo(pid, Info)) {
122 return llvm::make_error<StringError>("Cannot get process architecture",
123 llvm::inconvertibleErrorCode());
124 }
125
126 std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
127 pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
128
129 Status status = process_up->Attach();
130 if (!status.Success())
131 return status.ToError();
132
133 return std::move(process_up);
134 }
135
136 NativeProcessNetBSD::Extension
GetSupportedExtensions() const137 NativeProcessNetBSD::Factory::GetSupportedExtensions() const {
138 return Extension::multiprocess | Extension::fork | Extension::vfork |
139 Extension::pass_signals | Extension::auxv | Extension::libraries_svr4 |
140 Extension::savecore;
141 }
142
143 // Public Instance Methods
144
NativeProcessNetBSD(::pid_t pid,int terminal_fd,NativeDelegate & delegate,const ArchSpec & arch,MainLoop & mainloop)145 NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
146 NativeDelegate &delegate,
147 const ArchSpec &arch,
148 MainLoop &mainloop)
149 : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
150 m_main_loop(mainloop) {
151 if (m_terminal_fd != -1) {
152 Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
153 assert(status.Success());
154 }
155
156 Status status;
157 m_sigchld_handle = mainloop.RegisterSignal(
158 SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
159 assert(m_sigchld_handle && status.Success());
160 }
161
162 // Handles all waitpid events from the inferior process.
MonitorCallback(lldb::pid_t pid,int signal)163 void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
164 switch (signal) {
165 case SIGTRAP:
166 return MonitorSIGTRAP(pid);
167 case SIGSTOP:
168 return MonitorSIGSTOP(pid);
169 default:
170 return MonitorSignal(pid, signal);
171 }
172 }
173
MonitorExited(lldb::pid_t pid,WaitStatus status)174 void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
175 Log *log = GetLog(POSIXLog::Process);
176
177 LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
178
179 /* Stop Tracking All Threads attached to Process */
180 m_threads.clear();
181
182 SetExitStatus(status, true);
183
184 // Notify delegate that our process has exited.
185 SetState(StateType::eStateExited, true);
186 }
187
MonitorSIGSTOP(lldb::pid_t pid)188 void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
189 ptrace_siginfo_t info;
190
191 const auto siginfo_err =
192 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
193
194 // Get details on the signal raised.
195 if (siginfo_err.Success()) {
196 // Handle SIGSTOP from LLGS (LLDB GDB Server)
197 if (info.psi_siginfo.si_code == SI_USER &&
198 info.psi_siginfo.si_pid == ::getpid()) {
199 /* Stop Tracking all Threads attached to Process */
200 for (const auto &thread : m_threads) {
201 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
202 SIGSTOP, &info.psi_siginfo);
203 }
204 }
205 SetState(StateType::eStateStopped, true);
206 }
207 }
208
MonitorSIGTRAP(lldb::pid_t pid)209 void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
210 Log *log = GetLog(POSIXLog::Process);
211 ptrace_siginfo_t info;
212
213 const auto siginfo_err =
214 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
215
216 // Get details on the signal raised.
217 if (siginfo_err.Fail()) {
218 LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);
219 return;
220 }
221
222 LLDB_LOG(log, "got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid,
223 info.psi_lwpid, info.psi_siginfo.si_code);
224 NativeThreadNetBSD *thread = nullptr;
225
226 if (info.psi_lwpid > 0) {
227 for (const auto &t : m_threads) {
228 if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
229 thread = static_cast<NativeThreadNetBSD *>(t.get());
230 break;
231 }
232 static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
233 }
234 if (!thread)
235 LLDB_LOG(log, "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
236 info.psi_lwpid);
237 }
238
239 switch (info.psi_siginfo.si_code) {
240 case TRAP_BRKPT:
241 if (thread) {
242 thread->SetStoppedByBreakpoint();
243 FixupBreakpointPCAsNeeded(*thread);
244 }
245 SetState(StateType::eStateStopped, true);
246 return;
247 case TRAP_TRACE:
248 if (thread)
249 thread->SetStoppedByTrace();
250 SetState(StateType::eStateStopped, true);
251 return;
252 case TRAP_EXEC: {
253 Status error = ReinitializeThreads();
254 if (error.Fail()) {
255 SetState(StateType::eStateInvalid);
256 return;
257 }
258
259 // Let our delegate know we have just exec'd.
260 NotifyDidExec();
261
262 for (const auto &thread : m_threads)
263 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
264 SetState(StateType::eStateStopped, true);
265 return;
266 }
267 case TRAP_CHLD: {
268 ptrace_state_t pst;
269 Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
270 if (error.Fail()) {
271 SetState(StateType::eStateInvalid);
272 return;
273 }
274
275 assert(thread);
276 if (pst.pe_report_event == PTRACE_VFORK_DONE) {
277 if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {
278 thread->SetStoppedByVForkDone();
279 SetState(StateType::eStateStopped, true);
280 } else {
281 Status error =
282 PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
283 if (error.Fail())
284 SetState(StateType::eStateInvalid);
285 }
286 } else {
287 assert(pst.pe_report_event == PTRACE_FORK ||
288 pst.pe_report_event == PTRACE_VFORK);
289 MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK,
290 *thread);
291 }
292 return;
293 }
294 case TRAP_LWP: {
295 ptrace_state_t pst;
296 Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
297 if (error.Fail()) {
298 SetState(StateType::eStateInvalid);
299 return;
300 }
301
302 switch (pst.pe_report_event) {
303 case PTRACE_LWP_CREATE: {
304 LLDB_LOG(log, "monitoring new thread, pid = {0}, LWP = {1}", pid,
305 pst.pe_lwp);
306 NativeThreadNetBSD &t = AddThread(pst.pe_lwp);
307 error = t.CopyWatchpointsFrom(
308 static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));
309 if (error.Fail()) {
310 LLDB_LOG(log, "failed to copy watchpoints to new thread {0}: {1}",
311 pst.pe_lwp, error);
312 SetState(StateType::eStateInvalid);
313 return;
314 }
315 } break;
316 case PTRACE_LWP_EXIT:
317 LLDB_LOG(log, "removing exited thread, pid = {0}, LWP = {1}", pid,
318 pst.pe_lwp);
319 RemoveThread(pst.pe_lwp);
320 break;
321 }
322
323 error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
324 if (error.Fail())
325 SetState(StateType::eStateInvalid);
326 return;
327 }
328 case TRAP_DBREG: {
329 if (!thread)
330 break;
331
332 auto ®ctx = static_cast<NativeRegisterContextNetBSD &>(
333 thread->GetRegisterContext());
334 uint32_t wp_index = LLDB_INVALID_INDEX32;
335 Status error = regctx.GetWatchpointHitIndex(
336 wp_index, (uintptr_t)info.psi_siginfo.si_addr);
337 if (error.Fail())
338 LLDB_LOG(log,
339 "received error while checking for watchpoint hits, pid = "
340 "{0}, LWP = {1}, error = {2}",
341 pid, info.psi_lwpid, error);
342 if (wp_index != LLDB_INVALID_INDEX32) {
343 thread->SetStoppedByWatchpoint(wp_index);
344 regctx.ClearWatchpointHit(wp_index);
345 SetState(StateType::eStateStopped, true);
346 return;
347 }
348
349 thread->SetStoppedByTrace();
350 SetState(StateType::eStateStopped, true);
351 return;
352 }
353 }
354
355 // Either user-generated SIGTRAP or an unknown event that would
356 // otherwise leave the debugger hanging.
357 LLDB_LOG(log, "unknown SIGTRAP, passing to generic handler");
358 MonitorSignal(pid, SIGTRAP);
359 }
360
MonitorSignal(lldb::pid_t pid,int signal)361 void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
362 Log *log = GetLog(POSIXLog::Process);
363 ptrace_siginfo_t info;
364
365 const auto siginfo_err =
366 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
367 if (siginfo_err.Fail()) {
368 LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);
369 return;
370 }
371
372 for (const auto &abs_thread : m_threads) {
373 NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
374 assert(info.psi_lwpid >= 0);
375 if (info.psi_lwpid == 0 ||
376 static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
377 thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
378 else
379 thread.SetStoppedWithNoReason();
380 }
381 SetState(StateType::eStateStopped, true);
382 }
383
PtraceWrapper(int req,lldb::pid_t pid,void * addr,int data,int * result)384 Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
385 int data, int *result) {
386 Log *log = GetLog(POSIXLog::Ptrace);
387 Status error;
388 int ret;
389
390 errno = 0;
391 ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);
392
393 if (ret == -1)
394 error.SetErrorToErrno();
395
396 if (result)
397 *result = ret;
398
399 LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
400
401 if (error.Fail())
402 LLDB_LOG(log, "ptrace() failed: {0}", error);
403
404 return error;
405 }
406
ComputeSignalInfo(const std::vector<std::unique_ptr<NativeThreadProtocol>> & threads,const ResumeActionList & resume_actions)407 static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
408 const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
409 const ResumeActionList &resume_actions) {
410 // We need to account for three possible scenarios:
411 // 1. no signal being sent.
412 // 2. a signal being sent to one thread.
413 // 3. a signal being sent to the whole process.
414
415 // Count signaled threads. While at it, determine which signal is being sent
416 // and ensure there's only one.
417 size_t signaled_threads = 0;
418 int signal = LLDB_INVALID_SIGNAL_NUMBER;
419 lldb::tid_t signaled_lwp;
420 for (const auto &thread : threads) {
421 assert(thread && "thread list should not contain NULL threads");
422 const ResumeAction *action =
423 resume_actions.GetActionForThread(thread->GetID(), true);
424 if (action) {
425 if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
426 signaled_threads++;
427 if (action->signal != signal) {
428 if (signal != LLDB_INVALID_SIGNAL_NUMBER)
429 return Status("NetBSD does not support passing multiple signals "
430 "simultaneously")
431 .ToError();
432 signal = action->signal;
433 signaled_lwp = thread->GetID();
434 }
435 }
436 }
437 }
438
439 if (signaled_threads == 0) {
440 ptrace_siginfo_t siginfo;
441 siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
442 return siginfo;
443 }
444
445 if (signaled_threads > 1 && signaled_threads < threads.size())
446 return Status("NetBSD does not support passing signal to 1<i<all threads")
447 .ToError();
448
449 ptrace_siginfo_t siginfo;
450 siginfo.psi_siginfo.si_signo = signal;
451 siginfo.psi_siginfo.si_code = SI_USER;
452 siginfo.psi_siginfo.si_pid = getpid();
453 siginfo.psi_siginfo.si_uid = getuid();
454 if (signaled_threads == 1)
455 siginfo.psi_lwpid = signaled_lwp;
456 else // signal for the whole process
457 siginfo.psi_lwpid = 0;
458 return siginfo;
459 }
460
Resume(const ResumeActionList & resume_actions)461 Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
462 Log *log = GetLog(POSIXLog::Process);
463 LLDB_LOG(log, "pid {0}", GetID());
464
465 Status ret;
466
467 Expected<ptrace_siginfo_t> siginfo =
468 ComputeSignalInfo(m_threads, resume_actions);
469 if (!siginfo)
470 return Status(siginfo.takeError());
471
472 for (const auto &abs_thread : m_threads) {
473 assert(abs_thread && "thread list should not contain NULL threads");
474 NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
475
476 const ResumeAction *action =
477 resume_actions.GetActionForThread(thread.GetID(), true);
478 // we need to explicit issue suspend requests, so it is simpler to map it
479 // into proper action
480 ResumeAction suspend_action{thread.GetID(), eStateSuspended,
481 LLDB_INVALID_SIGNAL_NUMBER};
482
483 if (action == nullptr) {
484 LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
485 thread.GetID());
486 action = &suspend_action;
487 }
488
489 LLDB_LOG(
490 log,
491 "processing resume action state {0} signal {1} for pid {2} tid {3}",
492 action->state, action->signal, GetID(), thread.GetID());
493
494 switch (action->state) {
495 case eStateRunning:
496 ret = thread.Resume();
497 break;
498 case eStateStepping:
499 ret = thread.SingleStep();
500 break;
501 case eStateSuspended:
502 case eStateStopped:
503 if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
504 return Status("Passing signal to suspended thread unsupported");
505
506 ret = thread.Suspend();
507 break;
508
509 default:
510 return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
511 "for pid %" PRIu64 ", tid %" PRIu64,
512 __FUNCTION__, StateAsCString(action->state), GetID(),
513 thread.GetID());
514 }
515
516 if (!ret.Success())
517 return ret;
518 }
519
520 int signal = 0;
521 if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
522 ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
523 sizeof(*siginfo));
524 if (!ret.Success())
525 return ret;
526 signal = siginfo->psi_siginfo.si_signo;
527 }
528
529 ret =
530 PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), signal);
531 if (ret.Success())
532 SetState(eStateRunning, true);
533 return ret;
534 }
535
Halt()536 Status NativeProcessNetBSD::Halt() { return PtraceWrapper(PT_STOP, GetID()); }
537
Detach()538 Status NativeProcessNetBSD::Detach() {
539 Status error;
540
541 // Stop monitoring the inferior.
542 m_sigchld_handle.reset();
543
544 // Tell ptrace to detach from the process.
545 if (GetID() == LLDB_INVALID_PROCESS_ID)
546 return error;
547
548 return PtraceWrapper(PT_DETACH, GetID(), reinterpret_cast<void *>(1));
549 }
550
Signal(int signo)551 Status NativeProcessNetBSD::Signal(int signo) {
552 Status error;
553
554 if (kill(GetID(), signo))
555 error.SetErrorToErrno();
556
557 return error;
558 }
559
Interrupt()560 Status NativeProcessNetBSD::Interrupt() {
561 return PtraceWrapper(PT_STOP, GetID());
562 }
563
Kill()564 Status NativeProcessNetBSD::Kill() {
565 Log *log = GetLog(POSIXLog::Process);
566 LLDB_LOG(log, "pid {0}", GetID());
567
568 Status error;
569
570 switch (m_state) {
571 case StateType::eStateInvalid:
572 case StateType::eStateExited:
573 case StateType::eStateCrashed:
574 case StateType::eStateDetached:
575 case StateType::eStateUnloaded:
576 // Nothing to do - the process is already dead.
577 LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
578 StateAsCString(m_state));
579 return error;
580
581 case StateType::eStateConnected:
582 case StateType::eStateAttaching:
583 case StateType::eStateLaunching:
584 case StateType::eStateStopped:
585 case StateType::eStateRunning:
586 case StateType::eStateStepping:
587 case StateType::eStateSuspended:
588 // We can try to kill a process in these states.
589 break;
590 }
591
592 if (kill(GetID(), SIGKILL) != 0) {
593 error.SetErrorToErrno();
594 return error;
595 }
596
597 return error;
598 }
599
GetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & range_info)600 Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
601 MemoryRegionInfo &range_info) {
602
603 if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
604 // We're done.
605 return Status("unsupported");
606 }
607
608 Status error = PopulateMemoryRegionCache();
609 if (error.Fail()) {
610 return error;
611 }
612
613 lldb::addr_t prev_base_address = 0;
614 // FIXME start by finding the last region that is <= target address using
615 // binary search. Data is sorted.
616 // There can be a ton of regions on pthreads apps with lots of threads.
617 for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
618 ++it) {
619 MemoryRegionInfo &proc_entry_info = it->first;
620 // Sanity check assumption that memory map entries are ascending.
621 assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
622 "descending memory map entries detected, unexpected");
623 prev_base_address = proc_entry_info.GetRange().GetRangeBase();
624 UNUSED_IF_ASSERT_DISABLED(prev_base_address);
625 // If the target address comes before this entry, indicate distance to next
626 // region.
627 if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
628 range_info.GetRange().SetRangeBase(load_addr);
629 range_info.GetRange().SetByteSize(
630 proc_entry_info.GetRange().GetRangeBase() - load_addr);
631 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
632 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
633 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
634 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
635 return error;
636 } else if (proc_entry_info.GetRange().Contains(load_addr)) {
637 // The target address is within the memory region we're processing here.
638 range_info = proc_entry_info;
639 return error;
640 }
641 // The target memory address comes somewhere after the region we just
642 // parsed.
643 }
644 // If we made it here, we didn't find an entry that contained the given
645 // address. Return the load_addr as start and the amount of bytes betwwen
646 // load address and the end of the memory as size.
647 range_info.GetRange().SetRangeBase(load_addr);
648 range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
649 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
650 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
651 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
652 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
653 return error;
654 }
655
PopulateMemoryRegionCache()656 Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
657 Log *log = GetLog(POSIXLog::Process);
658 // If our cache is empty, pull the latest. There should always be at least
659 // one memory region if memory region handling is supported.
660 if (!m_mem_region_cache.empty()) {
661 LLDB_LOG(log, "reusing {0} cached memory region entries",
662 m_mem_region_cache.size());
663 return Status();
664 }
665
666 struct kinfo_vmentry *vm;
667 size_t count, i;
668 vm = kinfo_getvmmap(GetID(), &count);
669 if (vm == NULL) {
670 m_supports_mem_region = LazyBool::eLazyBoolNo;
671 Status error;
672 error.SetErrorString("not supported");
673 return error;
674 }
675 for (i = 0; i < count; i++) {
676 MemoryRegionInfo info;
677 info.Clear();
678 info.GetRange().SetRangeBase(vm[i].kve_start);
679 info.GetRange().SetRangeEnd(vm[i].kve_end);
680 info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
681
682 if (vm[i].kve_protection & VM_PROT_READ)
683 info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
684 else
685 info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
686
687 if (vm[i].kve_protection & VM_PROT_WRITE)
688 info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
689 else
690 info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
691
692 if (vm[i].kve_protection & VM_PROT_EXECUTE)
693 info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
694 else
695 info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
696
697 if (vm[i].kve_path[0])
698 info.SetName(vm[i].kve_path);
699
700 m_mem_region_cache.emplace_back(info,
701 FileSpec(info.GetName().GetCString()));
702 }
703 free(vm);
704
705 if (m_mem_region_cache.empty()) {
706 // No entries after attempting to read them. This shouldn't happen. Assume
707 // we don't support map entries.
708 LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
709 "for memory region metadata retrieval");
710 m_supports_mem_region = LazyBool::eLazyBoolNo;
711 Status error;
712 error.SetErrorString("not supported");
713 return error;
714 }
715 LLDB_LOG(log, "read {0} memory region entries from process {1}",
716 m_mem_region_cache.size(), GetID());
717 // We support memory retrieval, remember that.
718 m_supports_mem_region = LazyBool::eLazyBoolYes;
719 return Status();
720 }
721
GetSharedLibraryInfoAddress()722 lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
723 // punt on this for now
724 return LLDB_INVALID_ADDRESS;
725 }
726
UpdateThreads()727 size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }
728
SetBreakpoint(lldb::addr_t addr,uint32_t size,bool hardware)729 Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
730 bool hardware) {
731 if (hardware)
732 return Status("NativeProcessNetBSD does not support hardware breakpoints");
733 else
734 return SetSoftwareBreakpoint(addr, size);
735 }
736
GetLoadedModuleFileSpec(const char * module_path,FileSpec & file_spec)737 Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
738 FileSpec &file_spec) {
739 Status error = PopulateMemoryRegionCache();
740 if (error.Fail())
741 return error;
742
743 FileSpec module_file_spec(module_path);
744 FileSystem::Instance().Resolve(module_file_spec);
745
746 file_spec.Clear();
747 for (const auto &it : m_mem_region_cache) {
748 if (it.second.GetFilename() == module_file_spec.GetFilename()) {
749 file_spec = it.second;
750 return Status();
751 }
752 }
753 return Status("Module file (%s) not found in process' memory map!",
754 module_file_spec.GetFilename().AsCString());
755 }
756
GetFileLoadAddress(const llvm::StringRef & file_name,lldb::addr_t & load_addr)757 Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
758 lldb::addr_t &load_addr) {
759 load_addr = LLDB_INVALID_ADDRESS;
760 Status error = PopulateMemoryRegionCache();
761 if (error.Fail())
762 return error;
763
764 FileSpec file(file_name);
765 for (const auto &it : m_mem_region_cache) {
766 if (it.second == file) {
767 load_addr = it.first.GetRange().GetRangeBase();
768 return Status();
769 }
770 }
771 return Status("No load address found for file %s.", file_name.str().c_str());
772 }
773
SigchldHandler()774 void NativeProcessNetBSD::SigchldHandler() {
775 Log *log = GetLog(POSIXLog::Process);
776 int status;
777 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status,
778 WALLSIG | WNOHANG);
779
780 if (wait_pid == 0)
781 return;
782
783 if (wait_pid == -1) {
784 Status error(errno, eErrorTypePOSIX);
785 LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
786 return;
787 }
788
789 WaitStatus wait_status = WaitStatus::Decode(status);
790 bool exited = wait_status.type == WaitStatus::Exit ||
791 (wait_status.type == WaitStatus::Signal &&
792 wait_pid == static_cast<::pid_t>(GetID()));
793
794 LLDB_LOG(log,
795 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
796 GetID(), wait_pid, status, exited);
797
798 if (exited)
799 MonitorExited(wait_pid, wait_status);
800 else {
801 assert(wait_status.type == WaitStatus::Stop);
802 MonitorCallback(wait_pid, wait_status.status);
803 }
804 }
805
HasThreadNoLock(lldb::tid_t thread_id)806 bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
807 for (const auto &thread : m_threads) {
808 assert(thread && "thread list should not contain NULL threads");
809 if (thread->GetID() == thread_id) {
810 // We have this thread.
811 return true;
812 }
813 }
814
815 // We don't have this thread.
816 return false;
817 }
818
AddThread(lldb::tid_t thread_id)819 NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
820 Log *log = GetLog(POSIXLog::Thread);
821 LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
822
823 assert(thread_id > 0);
824 assert(!HasThreadNoLock(thread_id) &&
825 "attempted to add a thread by id that already exists");
826
827 // If this is the first thread, save it as the current thread
828 if (m_threads.empty())
829 SetCurrentThreadID(thread_id);
830
831 m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*this, thread_id));
832 return static_cast<NativeThreadNetBSD &>(*m_threads.back());
833 }
834
RemoveThread(lldb::tid_t thread_id)835 void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
836 Log *log = GetLog(POSIXLog::Thread);
837 LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
838
839 assert(thread_id > 0);
840 assert(HasThreadNoLock(thread_id) &&
841 "attempted to remove a thread that does not exist");
842
843 for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
844 if ((*it)->GetID() == thread_id) {
845 m_threads.erase(it);
846 break;
847 }
848 }
849 }
850
Attach()851 Status NativeProcessNetBSD::Attach() {
852 // Attach to the requested process.
853 // An attach will cause the thread to stop with a SIGSTOP.
854 Status status = PtraceWrapper(PT_ATTACH, m_pid);
855 if (status.Fail())
856 return status;
857
858 int wstatus;
859 // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
860 // point we should have a thread stopped if waitpid succeeds.
861 if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid, m_pid, nullptr,
862 WALLSIG)) < 0)
863 return Status(errno, eErrorTypePOSIX);
864
865 // Initialize threads and tracing status
866 // NB: this needs to be called before we set thread state
867 status = SetupTrace();
868 if (status.Fail())
869 return status;
870
871 for (const auto &thread : m_threads)
872 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
873
874 // Let our process instance know the thread has stopped.
875 SetCurrentThreadID(m_threads.front()->GetID());
876 SetState(StateType::eStateStopped, false);
877 return Status();
878 }
879
ReadMemory(lldb::addr_t addr,void * buf,size_t size,size_t & bytes_read)880 Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
881 size_t size, size_t &bytes_read) {
882 unsigned char *dst = static_cast<unsigned char *>(buf);
883 struct ptrace_io_desc io;
884
885 Log *log = GetLog(POSIXLog::Memory);
886 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
887
888 bytes_read = 0;
889 io.piod_op = PIOD_READ_D;
890 io.piod_len = size;
891
892 do {
893 io.piod_offs = (void *)(addr + bytes_read);
894 io.piod_addr = dst + bytes_read;
895
896 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
897 if (error.Fail() || io.piod_len == 0)
898 return error;
899
900 bytes_read += io.piod_len;
901 io.piod_len = size - bytes_read;
902 } while (bytes_read < size);
903
904 return Status();
905 }
906
WriteMemory(lldb::addr_t addr,const void * buf,size_t size,size_t & bytes_written)907 Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
908 size_t size, size_t &bytes_written) {
909 const unsigned char *src = static_cast<const unsigned char *>(buf);
910 Status error;
911 struct ptrace_io_desc io;
912
913 Log *log = GetLog(POSIXLog::Memory);
914 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
915
916 bytes_written = 0;
917 io.piod_op = PIOD_WRITE_D;
918 io.piod_len = size;
919
920 do {
921 io.piod_addr =
922 const_cast<void *>(static_cast<const void *>(src + bytes_written));
923 io.piod_offs = (void *)(addr + bytes_written);
924
925 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
926 if (error.Fail() || io.piod_len == 0)
927 return error;
928
929 bytes_written += io.piod_len;
930 io.piod_len = size - bytes_written;
931 } while (bytes_written < size);
932
933 return error;
934 }
935
936 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
GetAuxvData() const937 NativeProcessNetBSD::GetAuxvData() const {
938 /*
939 * ELF_AUX_ENTRIES is currently restricted to kernel
940 * (<sys/exec_elf.h> r. 1.155 specifies 15)
941 *
942 * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
943 * information isn't needed.
944 */
945 size_t auxv_size = 100 * sizeof(AuxInfo);
946
947 ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
948 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
949
950 struct ptrace_io_desc io;
951 io.piod_op = PIOD_READ_AUXV;
952 io.piod_offs = 0;
953 io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
954 io.piod_len = auxv_size;
955
956 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
957
958 if (error.Fail())
959 return std::error_code(error.GetError(), std::generic_category());
960
961 if (io.piod_len < 1)
962 return std::error_code(ECANCELED, std::generic_category());
963
964 return std::move(buf);
965 }
966
SetupTrace()967 Status NativeProcessNetBSD::SetupTrace() {
968 // Enable event reporting
969 ptrace_event_t events;
970 Status status =
971 PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
972 if (status.Fail())
973 return status;
974 // TODO: PTRACE_POSIX_SPAWN?
975 events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |
976 PTRACE_VFORK | PTRACE_VFORK_DONE;
977 status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
978 if (status.Fail())
979 return status;
980
981 return ReinitializeThreads();
982 }
983
ReinitializeThreads()984 Status NativeProcessNetBSD::ReinitializeThreads() {
985 // Clear old threads
986 m_threads.clear();
987
988 // Initialize new thread
989 #ifdef PT_LWPSTATUS
990 struct ptrace_lwpstatus info = {};
991 int op = PT_LWPNEXT;
992 #else
993 struct ptrace_lwpinfo info = {};
994 int op = PT_LWPINFO;
995 #endif
996
997 Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));
998
999 if (error.Fail()) {
1000 return error;
1001 }
1002 // Reinitialize from scratch threads and register them in process
1003 while (info.pl_lwpid != 0) {
1004 AddThread(info.pl_lwpid);
1005 error = PtraceWrapper(op, GetID(), &info, sizeof(info));
1006 if (error.Fail()) {
1007 return error;
1008 }
1009 }
1010
1011 return error;
1012 }
1013
MonitorClone(::pid_t child_pid,bool is_vfork,NativeThreadNetBSD & parent_thread)1014 void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
1015 NativeThreadNetBSD &parent_thread) {
1016 Log *log = GetLog(POSIXLog::Process);
1017 LLDB_LOG(log, "clone, child_pid={0}", child_pid);
1018
1019 int status;
1020 ::pid_t wait_pid =
1021 llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
1022 if (wait_pid != child_pid) {
1023 LLDB_LOG(log,
1024 "waiting for pid {0} failed. Assuming the pid has "
1025 "disappeared in the meantime",
1026 child_pid);
1027 return;
1028 }
1029 if (WIFEXITED(status)) {
1030 LLDB_LOG(log,
1031 "waiting for pid {0} returned an 'exited' event. Not "
1032 "tracking it.",
1033 child_pid);
1034 return;
1035 }
1036
1037 ptrace_siginfo_t info;
1038 const auto siginfo_err =
1039 PtraceWrapper(PT_GET_SIGINFO, child_pid, &info, sizeof(info));
1040 if (siginfo_err.Fail()) {
1041 LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);
1042 return;
1043 }
1044 assert(info.psi_lwpid >= 0);
1045 lldb::tid_t child_tid = info.psi_lwpid;
1046
1047 std::unique_ptr<NativeProcessNetBSD> child_process{
1048 new NativeProcessNetBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,
1049 m_delegate, m_arch, m_main_loop)};
1050 if (!is_vfork)
1051 child_process->m_software_breakpoints = m_software_breakpoints;
1052
1053 Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
1054 if ((m_enabled_extensions & expected_ext) == expected_ext) {
1055 child_process->SetupTrace();
1056 for (const auto &thread : child_process->m_threads)
1057 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
1058 child_process->SetState(StateType::eStateStopped, false);
1059
1060 m_delegate.NewSubprocess(this, std::move(child_process));
1061 if (is_vfork)
1062 parent_thread.SetStoppedByVFork(child_pid, child_tid);
1063 else
1064 parent_thread.SetStoppedByFork(child_pid, child_tid);
1065 SetState(StateType::eStateStopped, true);
1066 } else {
1067 child_process->Detach();
1068 Status pt_error =
1069 PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
1070 if (pt_error.Fail()) {
1071 LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),
1072 "unable to resume parent process {1}: {0}", GetID());
1073 SetState(StateType::eStateInvalid);
1074 }
1075 }
1076 }
1077
1078 llvm::Expected<std::string>
SaveCore(llvm::StringRef path_hint)1079 NativeProcessNetBSD::SaveCore(llvm::StringRef path_hint) {
1080 llvm::SmallString<128> path{path_hint};
1081 Status error;
1082
1083 // Try with the suggested path first.
1084 if (!path.empty()) {
1085 error = PtraceWrapper(PT_DUMPCORE, GetID(), path.data(), path.size());
1086 if (!error.Fail())
1087 return path.str().str();
1088
1089 // If the request errored, fall back to a generic temporary file.
1090 }
1091
1092 if (std::error_code errc =
1093 llvm::sys::fs::createTemporaryFile("lldb", "core", path))
1094 return llvm::createStringError(errc, "Unable to create a temporary file");
1095
1096 error = PtraceWrapper(PT_DUMPCORE, GetID(), path.data(), path.size());
1097 if (error.Fail())
1098 return error.ToError();
1099 return path.str().str();
1100 }
1101