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