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