blob: a4d775860a6504fcddae7b96f3dc26c3d13a6644 [file] [log] [blame]
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +00001//===-- NativeProcessNetBSD.cpp ------------------------------- -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "NativeProcessNetBSD.h"
11
12// C Includes
13
14// C++ Includes
15
16// Other libraries and framework includes
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +000017#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000018#include "lldb/Core/State.h"
19#include "lldb/Host/HostProcess.h"
20#include "lldb/Host/common/NativeBreakpoint.h"
21#include "lldb/Host/common/NativeRegisterContext.h"
22#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
23#include "lldb/Target/Process.h"
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +000024
25// System includes - They have to be included after framework includes because
26// they define some
27// macros which collide with variable names in other modules
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000028// clang-format off
29#include <sys/types.h>
30#include <sys/ptrace.h>
31#include <sys/sysctl.h>
32#include <sys/wait.h>
33#include <uvm/uvm_prot.h>
34#include <elf.h>
35#include <util.h>
36// clang-format on
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +000037
38using namespace lldb;
39using namespace lldb_private;
40using namespace lldb_private::process_netbsd;
41using namespace llvm;
42
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000043// Simple helper function to ensure flags are enabled on the given file
44// descriptor.
Zachary Turner97206d52017-05-12 04:51:55 +000045static Status EnsureFDFlags(int fd, int flags) {
46 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000047
48 int status = fcntl(fd, F_GETFL);
49 if (status == -1) {
50 error.SetErrorToErrno();
51 return error;
52 }
53
54 if (fcntl(fd, F_SETFL, status | flags) == -1) {
55 error.SetErrorToErrno();
56 return error;
57 }
58
59 return error;
60}
61
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +000062// -----------------------------------------------------------------------------
63// Public Static Methods
64// -----------------------------------------------------------------------------
65
Zachary Turner97206d52017-05-12 04:51:55 +000066Status NativeProcessProtocol::Launch(
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +000067 ProcessLaunchInfo &launch_info,
68 NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
69 NativeProcessProtocolSP &native_process_sp) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000070 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
71
Zachary Turner97206d52017-05-12 04:51:55 +000072 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000073
74 // Verify the working directory is valid if one was specified.
75 FileSpec working_dir{launch_info.GetWorkingDirectory()};
76 if (working_dir && (!working_dir.ResolvePath() ||
77 !llvm::sys::fs::is_directory(working_dir.GetPath()))) {
78 error.SetErrorStringWithFormat("No such file or directory: %s",
79 working_dir.GetCString());
80 return error;
81 }
82
83 // Create the NativeProcessNetBSD in launch mode.
84 native_process_sp.reset(new NativeProcessNetBSD());
85
86 if (!native_process_sp->RegisterNativeDelegate(native_delegate)) {
87 native_process_sp.reset();
88 error.SetErrorStringWithFormat("failed to register the native delegate");
89 return error;
90 }
91
92 error = std::static_pointer_cast<NativeProcessNetBSD>(native_process_sp)
93 ->LaunchInferior(mainloop, launch_info);
94
95 if (error.Fail()) {
96 native_process_sp.reset();
97 LLDB_LOG(log, "failed to launch process: {0}", error);
98 return error;
99 }
100
101 launch_info.SetProcessID(native_process_sp->GetID());
102
103 return error;
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +0000104}
105
Zachary Turner97206d52017-05-12 04:51:55 +0000106Status NativeProcessProtocol::Attach(
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +0000107 lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
108 MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000109 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
110 LLDB_LOG(log, "pid = {0:x}", pid);
111
112 // Retrieve the architecture for the running process.
113 ArchSpec process_arch;
Zachary Turner97206d52017-05-12 04:51:55 +0000114 Status error = ResolveProcessArchitecture(pid, process_arch);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000115 if (!error.Success())
116 return error;
117
118 std::shared_ptr<NativeProcessNetBSD> native_process_netbsd_sp(
119 new NativeProcessNetBSD());
120
121 if (!native_process_netbsd_sp->RegisterNativeDelegate(native_delegate)) {
122 error.SetErrorStringWithFormat("failed to register the native delegate");
123 return error;
124 }
125
126 native_process_netbsd_sp->AttachToInferior(mainloop, pid, error);
127 if (!error.Success())
128 return error;
129
130 native_process_sp = native_process_netbsd_sp;
131 return error;
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +0000132}
133
134// -----------------------------------------------------------------------------
135// Public Instance Methods
136// -----------------------------------------------------------------------------
137
138NativeProcessNetBSD::NativeProcessNetBSD()
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000139 : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(),
140 m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache() {}
141
142// Handles all waitpid events from the inferior process.
143void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000144 switch (signal) {
145 case SIGTRAP:
146 return MonitorSIGTRAP(pid);
147 case SIGSTOP:
148 return MonitorSIGSTOP(pid);
149 default:
150 return MonitorSignal(pid, signal);
151 }
152}
153
Pavel Labath3508fc82017-06-19 12:47:50 +0000154void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000155 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
156
Pavel Labath3508fc82017-06-19 12:47:50 +0000157 LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000158
159 /* Stop Tracking All Threads attached to Process */
160 m_threads.clear();
161
Pavel Labath3508fc82017-06-19 12:47:50 +0000162 SetExitStatus(status, true);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000163
164 // Notify delegate that our process has exited.
165 SetState(StateType::eStateExited, true);
166}
167
168void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000169 ptrace_siginfo_t info;
170
171 const auto siginfo_err =
172 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
173
174 // Get details on the signal raised.
175 if (siginfo_err.Success()) {
176 // Handle SIGSTOP from LLGS (LLDB GDB Server)
177 if (info.psi_siginfo.si_code == SI_USER &&
178 info.psi_siginfo.si_pid == ::getpid()) {
179 /* Stop Tracking All Threads attached to Process */
180 for (const auto &thread_sp : m_threads) {
181 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
182 SIGSTOP, &info.psi_siginfo);
183 }
184 }
185 }
186}
187
188void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
189 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
190 ptrace_siginfo_t info;
191
192 const auto siginfo_err =
193 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
194
195 // Get details on the signal raised.
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000196 if (siginfo_err.Fail()) {
197 return;
198 }
199
200 switch (info.psi_siginfo.si_code) {
201 case TRAP_BRKPT:
202 for (const auto &thread_sp : m_threads) {
203 static_pointer_cast<NativeThreadNetBSD>(thread_sp)
204 ->SetStoppedByBreakpoint();
205 FixupBreakpointPCAsNeeded(
206 *static_pointer_cast<NativeThreadNetBSD>(thread_sp));
207 }
208 SetState(StateType::eStateStopped, true);
209 break;
210 case TRAP_TRACE:
211 for (const auto &thread_sp : m_threads) {
212 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
213 }
214 SetState(StateType::eStateStopped, true);
215 break;
216 case TRAP_EXEC: {
Zachary Turner97206d52017-05-12 04:51:55 +0000217 Status error = ReinitializeThreads();
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000218 if (error.Fail()) {
219 SetState(StateType::eStateInvalid);
220 return;
221 }
222
223 // Let our delegate know we have just exec'd.
224 NotifyDidExec();
225
226 for (const auto &thread_sp : m_threads) {
227 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByExec();
228 }
229 SetState(StateType::eStateStopped, true);
230 } break;
231 case TRAP_DBREG: {
232 // If a watchpoint was hit, report it
233 uint32_t wp_index;
Zachary Turner97206d52017-05-12 04:51:55 +0000234 Status error =
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000235 static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
236 ->GetRegisterContext()
237 ->GetWatchpointHitIndex(wp_index,
238 (uintptr_t)info.psi_siginfo.si_addr);
239 if (error.Fail())
240 LLDB_LOG(log,
241 "received error while checking for watchpoint hits, pid = "
242 "{0}, LWP = {1}, error = {2}",
243 GetID(), info.psi_lwpid, error);
244 if (wp_index != LLDB_INVALID_INDEX32) {
245 for (const auto &thread_sp : m_threads) {
246 static_pointer_cast<NativeThreadNetBSD>(thread_sp)
247 ->SetStoppedByWatchpoint(wp_index);
248 }
249 SetState(StateType::eStateStopped, true);
250 break;
251 }
252
253 // If a breakpoint was hit, report it
254 uint32_t bp_index;
255 error = static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
256 ->GetRegisterContext()
257 ->GetHardwareBreakHitIndex(bp_index,
258 (uintptr_t)info.psi_siginfo.si_addr);
259 if (error.Fail())
260 LLDB_LOG(log,
261 "received error while checking for hardware "
262 "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
263 GetID(), info.psi_lwpid, error);
264 if (bp_index != LLDB_INVALID_INDEX32) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000265 for (const auto &thread_sp : m_threads) {
266 static_pointer_cast<NativeThreadNetBSD>(thread_sp)
267 ->SetStoppedByBreakpoint();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000268 }
269 SetState(StateType::eStateStopped, true);
270 break;
271 }
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000272 } break;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000273 }
274}
275
276void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000277 ptrace_siginfo_t info;
278 const auto siginfo_err =
279 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
280
281 for (const auto &thread_sp : m_threads) {
282 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
283 info.psi_siginfo.si_signo, &info.psi_siginfo);
284 }
285 SetState(StateType::eStateStopped, true);
286}
287
Zachary Turner97206d52017-05-12 04:51:55 +0000288Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
289 int data, int *result) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000290 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
Zachary Turner97206d52017-05-12 04:51:55 +0000291 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000292 int ret;
293
294 errno = 0;
295 ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);
296
297 if (ret == -1)
298 error.SetErrorToErrno();
299
300 if (result)
301 *result = ret;
302
303 LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
304
305 if (error.Fail())
306 LLDB_LOG(log, "ptrace() failed: {0}", error);
307
308 return error;
309}
310
Zachary Turner97206d52017-05-12 04:51:55 +0000311Status NativeProcessNetBSD::GetSoftwareBreakpointPCOffset(
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000312 uint32_t &actual_opcode_size) {
313 // FIXME put this behind a breakpoint protocol class that can be
314 // set per architecture. Need ARM, MIPS support here.
315 static const uint8_t g_i386_opcode[] = {0xCC};
316 switch (m_arch.GetMachine()) {
317 case llvm::Triple::x86_64:
318 actual_opcode_size = static_cast<uint32_t>(sizeof(g_i386_opcode));
Zachary Turner97206d52017-05-12 04:51:55 +0000319 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000320 default:
321 assert(false && "CPU type not supported!");
Zachary Turner97206d52017-05-12 04:51:55 +0000322 return Status("CPU type not supported");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000323 }
324}
325
Zachary Turner97206d52017-05-12 04:51:55 +0000326Status
327NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000328 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
Zachary Turner97206d52017-05-12 04:51:55 +0000329 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000330 // Find out the size of a breakpoint (might depend on where we are in the
331 // code).
332 NativeRegisterContextSP context_sp = thread.GetRegisterContext();
333 if (!context_sp) {
334 error.SetErrorString("cannot get a NativeRegisterContext for the thread");
335 LLDB_LOG(log, "failed: {0}", error);
336 return error;
337 }
338 uint32_t breakpoint_size = 0;
339 error = GetSoftwareBreakpointPCOffset(breakpoint_size);
340 if (error.Fail()) {
341 LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error);
342 return error;
343 } else
344 LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000345 // First try probing for a breakpoint at a software breakpoint location: PC
346 // - breakpoint size.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000347 const lldb::addr_t initial_pc_addr =
348 context_sp->GetPCfromBreakpointLocation();
349 lldb::addr_t breakpoint_addr = initial_pc_addr;
350 if (breakpoint_size > 0) {
351 // Do not allow breakpoint probe to wrap around.
352 if (breakpoint_addr >= breakpoint_size)
353 breakpoint_addr -= breakpoint_size;
354 }
355 // Check if we stopped because of a breakpoint.
356 NativeBreakpointSP breakpoint_sp;
357 error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp);
358 if (!error.Success() || !breakpoint_sp) {
359 // We didn't find one at a software probe location. Nothing to do.
360 LLDB_LOG(log,
361 "pid {0} no lldb breakpoint found at current pc with "
362 "adjustment: {1}",
363 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000364 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000365 }
366 // If the breakpoint is not a software breakpoint, nothing to do.
367 if (!breakpoint_sp->IsSoftwareBreakpoint()) {
368 LLDB_LOG(
369 log,
370 "pid {0} breakpoint found at {1:x}, not software, nothing to adjust",
371 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000372 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000373 }
374 //
375 // We have a software breakpoint and need to adjust the PC.
376 //
377 // Sanity check.
378 if (breakpoint_size == 0) {
379 // Nothing to do! How did we get here?
380 LLDB_LOG(log,
381 "pid {0} breakpoint found at {1:x}, it is software, but the "
382 "size is zero, nothing to do (unexpected)",
383 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000384 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000385 }
386 //
387 // We have a software breakpoint and need to adjust the PC.
388 //
389 // Sanity check.
390 if (breakpoint_size == 0) {
391 // Nothing to do! How did we get here?
392 LLDB_LOG(log,
393 "pid {0} breakpoint found at {1:x}, it is software, but the "
394 "size is zero, nothing to do (unexpected)",
395 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000396 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000397 }
398 // Change the program counter.
399 LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(),
400 thread.GetID(), initial_pc_addr, breakpoint_addr);
401 error = context_sp->SetPC(breakpoint_addr);
402 if (error.Fail()) {
403 LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(),
404 thread.GetID(), error);
405 return error;
406 }
407 return error;
408}
409
Zachary Turner97206d52017-05-12 04:51:55 +0000410Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000411 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
412 LLDB_LOG(log, "pid {0}", GetID());
413
414 const auto &thread_sp = m_threads[0];
415 const ResumeAction *const action =
416 resume_actions.GetActionForThread(thread_sp->GetID(), true);
417
418 if (action == nullptr) {
419 LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
420 thread_sp->GetID());
Zachary Turner97206d52017-05-12 04:51:55 +0000421 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000422 }
423
Zachary Turner97206d52017-05-12 04:51:55 +0000424 Status error;
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000425
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000426 switch (action->state) {
427 case eStateRunning: {
428 // Run the thread, possibly feeding it the signal.
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000429 error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
430 action->signal);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000431 if (!error.Success())
432 return error;
433 for (const auto &thread_sp : m_threads) {
434 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetRunning();
435 }
436 SetState(eStateRunning, true);
437 break;
438 }
439 case eStateStepping:
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000440 // Run the thread, possibly feeding it the signal.
441 error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
442 action->signal);
443 if (!error.Success())
444 return error;
445 for (const auto &thread_sp : m_threads) {
446 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStepping();
447 }
448 SetState(eStateStepping, true);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000449 break;
450
451 case eStateSuspended:
452 case eStateStopped:
453 llvm_unreachable("Unexpected state");
454
455 default:
Zachary Turner97206d52017-05-12 04:51:55 +0000456 return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
457 "for pid %" PRIu64 ", tid %" PRIu64,
458 __FUNCTION__, StateAsCString(action->state), GetID(),
459 thread_sp->GetID());
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000460 }
461
Zachary Turner97206d52017-05-12 04:51:55 +0000462 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000463}
464
Zachary Turner97206d52017-05-12 04:51:55 +0000465Status NativeProcessNetBSD::Halt() {
466 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000467
468 if (kill(GetID(), SIGSTOP) != 0)
469 error.SetErrorToErrno();
470
471 return error;
472}
473
Zachary Turner97206d52017-05-12 04:51:55 +0000474Status NativeProcessNetBSD::Detach() {
475 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000476
477 // Stop monitoring the inferior.
478 m_sigchld_handle.reset();
479
480 // Tell ptrace to detach from the process.
481 if (GetID() == LLDB_INVALID_PROCESS_ID)
482 return error;
483
484 return PtraceWrapper(PT_DETACH, GetID());
485}
486
Zachary Turner97206d52017-05-12 04:51:55 +0000487Status NativeProcessNetBSD::Signal(int signo) {
488 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000489
490 if (kill(GetID(), signo))
491 error.SetErrorToErrno();
492
493 return error;
494}
495
Zachary Turner97206d52017-05-12 04:51:55 +0000496Status NativeProcessNetBSD::Kill() {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000497 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
498 LLDB_LOG(log, "pid {0}", GetID());
499
Zachary Turner97206d52017-05-12 04:51:55 +0000500 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000501
502 switch (m_state) {
503 case StateType::eStateInvalid:
504 case StateType::eStateExited:
505 case StateType::eStateCrashed:
506 case StateType::eStateDetached:
507 case StateType::eStateUnloaded:
508 // Nothing to do - the process is already dead.
509 LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
510 StateAsCString(m_state));
511 return error;
512
513 case StateType::eStateConnected:
514 case StateType::eStateAttaching:
515 case StateType::eStateLaunching:
516 case StateType::eStateStopped:
517 case StateType::eStateRunning:
518 case StateType::eStateStepping:
519 case StateType::eStateSuspended:
520 // We can try to kill a process in these states.
521 break;
522 }
523
524 if (kill(GetID(), SIGKILL) != 0) {
525 error.SetErrorToErrno();
526 return error;
527 }
528
529 return error;
530}
531
Zachary Turner97206d52017-05-12 04:51:55 +0000532Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
533 MemoryRegionInfo &range_info) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000534
535 if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
536 // We're done.
Zachary Turner97206d52017-05-12 04:51:55 +0000537 return Status("unsupported");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000538 }
539
Zachary Turner97206d52017-05-12 04:51:55 +0000540 Status error = PopulateMemoryRegionCache();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000541 if (error.Fail()) {
542 return error;
543 }
544
545 lldb::addr_t prev_base_address = 0;
546 // FIXME start by finding the last region that is <= target address using
547 // binary search. Data is sorted.
548 // There can be a ton of regions on pthreads apps with lots of threads.
549 for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
550 ++it) {
551 MemoryRegionInfo &proc_entry_info = it->first;
552 // Sanity check assumption that memory map entries are ascending.
553 assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
554 "descending memory map entries detected, unexpected");
555 prev_base_address = proc_entry_info.GetRange().GetRangeBase();
556 UNUSED_IF_ASSERT_DISABLED(prev_base_address);
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000557 // If the target address comes before this entry, indicate distance to
558 // next region.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000559 if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
560 range_info.GetRange().SetRangeBase(load_addr);
561 range_info.GetRange().SetByteSize(
562 proc_entry_info.GetRange().GetRangeBase() - load_addr);
563 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
564 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
565 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
566 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
567 return error;
568 } else if (proc_entry_info.GetRange().Contains(load_addr)) {
569 // The target address is within the memory region we're processing here.
570 range_info = proc_entry_info;
571 return error;
572 }
573 // The target memory address comes somewhere after the region we just
574 // parsed.
575 }
576 // If we made it here, we didn't find an entry that contained the given
577 // address. Return the
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000578 // load_addr as start and the amount of bytes betwwen load address and the
579 // end of the memory as size.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000580 range_info.GetRange().SetRangeBase(load_addr);
581 range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
582 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
583 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
584 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
585 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
586 return error;
587}
588
Zachary Turner97206d52017-05-12 04:51:55 +0000589Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000590 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
591 // If our cache is empty, pull the latest. There should always be at least
592 // one memory region if memory region handling is supported.
593 if (!m_mem_region_cache.empty()) {
594 LLDB_LOG(log, "reusing {0} cached memory region entries",
595 m_mem_region_cache.size());
Zachary Turner97206d52017-05-12 04:51:55 +0000596 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000597 }
598
599 struct kinfo_vmentry *vm;
600 size_t count, i;
601 vm = kinfo_getvmmap(GetID(), &count);
602 if (vm == NULL) {
603 m_supports_mem_region = LazyBool::eLazyBoolNo;
Zachary Turner97206d52017-05-12 04:51:55 +0000604 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000605 error.SetErrorString("not supported");
606 return error;
607 }
608 for (i = 0; i < count; i++) {
609 MemoryRegionInfo info;
610 info.Clear();
611 info.GetRange().SetRangeBase(vm[i].kve_start);
612 info.GetRange().SetRangeEnd(vm[i].kve_end);
613 info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
614
615 if (vm[i].kve_protection & VM_PROT_READ)
616 info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
617 else
618 info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
619
620 if (vm[i].kve_protection & VM_PROT_WRITE)
621 info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
622 else
623 info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
624
625 if (vm[i].kve_protection & VM_PROT_EXECUTE)
626 info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
627 else
628 info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
629
630 if (vm[i].kve_path[0])
631 info.SetName(vm[i].kve_path);
632
633 m_mem_region_cache.emplace_back(
634 info, FileSpec(info.GetName().GetCString(), true));
635 }
636 free(vm);
637
638 if (m_mem_region_cache.empty()) {
639 // No entries after attempting to read them. This shouldn't happen.
640 // Assume we don't support map entries.
641 LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
642 "for memory region metadata retrieval");
643 m_supports_mem_region = LazyBool::eLazyBoolNo;
Zachary Turner97206d52017-05-12 04:51:55 +0000644 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000645 error.SetErrorString("not supported");
646 return error;
647 }
648 LLDB_LOG(log, "read {0} memory region entries from process {1}",
649 m_mem_region_cache.size(), GetID());
650 // We support memory retrieval, remember that.
651 m_supports_mem_region = LazyBool::eLazyBoolYes;
Zachary Turner97206d52017-05-12 04:51:55 +0000652 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000653}
654
Zachary Turner97206d52017-05-12 04:51:55 +0000655Status NativeProcessNetBSD::AllocateMemory(size_t size, uint32_t permissions,
656 lldb::addr_t &addr) {
657 return Status("Unimplemented");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000658}
659
Zachary Turner97206d52017-05-12 04:51:55 +0000660Status NativeProcessNetBSD::DeallocateMemory(lldb::addr_t addr) {
661 return Status("Unimplemented");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000662}
663
664lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
665 // punt on this for now
666 return LLDB_INVALID_ADDRESS;
667}
668
669size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }
670
671bool NativeProcessNetBSD::GetArchitecture(ArchSpec &arch) const {
672 arch = m_arch;
673 return true;
674}
675
Zachary Turner97206d52017-05-12 04:51:55 +0000676Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
677 bool hardware) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000678 if (hardware)
Zachary Turner97206d52017-05-12 04:51:55 +0000679 return Status("NativeProcessNetBSD does not support hardware breakpoints");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000680 else
681 return SetSoftwareBreakpoint(addr, size);
682}
683
Zachary Turner97206d52017-05-12 04:51:55 +0000684Status NativeProcessNetBSD::GetSoftwareBreakpointTrapOpcode(
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000685 size_t trap_opcode_size_hint, size_t &actual_opcode_size,
686 const uint8_t *&trap_opcode_bytes) {
687 static const uint8_t g_i386_opcode[] = {0xCC};
688
689 switch (m_arch.GetMachine()) {
690 case llvm::Triple::x86:
691 case llvm::Triple::x86_64:
692 trap_opcode_bytes = g_i386_opcode;
693 actual_opcode_size = sizeof(g_i386_opcode);
Zachary Turner97206d52017-05-12 04:51:55 +0000694 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000695 default:
696 assert(false && "CPU type not supported!");
Zachary Turner97206d52017-05-12 04:51:55 +0000697 return Status("CPU type not supported");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000698 }
699}
700
Zachary Turner97206d52017-05-12 04:51:55 +0000701Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
702 FileSpec &file_spec) {
703 return Status("Unimplemented");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000704}
705
Zachary Turner97206d52017-05-12 04:51:55 +0000706Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
707 lldb::addr_t &load_addr) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000708 load_addr = LLDB_INVALID_ADDRESS;
Zachary Turner97206d52017-05-12 04:51:55 +0000709 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000710}
711
Zachary Turner97206d52017-05-12 04:51:55 +0000712Status NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
713 ProcessLaunchInfo &launch_info) {
714 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000715 m_sigchld_handle = mainloop.RegisterSignal(
716 SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
717 if (!m_sigchld_handle)
718 return error;
719
720 SetState(eStateLaunching);
721
722 ::pid_t pid = ProcessLauncherPosixFork()
723 .LaunchProcess(launch_info, error)
724 .GetProcessId();
725 if (error.Fail())
726 return error;
727
728 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
729
730 // Wait for the child process to trap on its call to execve.
731 ::pid_t wpid;
732 int status;
733 if ((wpid = waitpid(pid, &status, 0)) < 0) {
734 error.SetErrorToErrno();
735 LLDB_LOG(log, "waitpid for inferior failed with %s", error);
736
737 // Mark the inferior as invalid.
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000738 // FIXME this could really use a new state - eStateLaunchFailure. For
739 // now, using eStateInvalid.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000740 SetState(StateType::eStateInvalid);
741
742 return error;
743 }
744 assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) &&
745 "Could not sync with inferior process.");
746
747 LLDB_LOG(log, "inferior started, now in stopped state");
748
749 // Release the master terminal descriptor and pass it off to the
750 // NativeProcessNetBSD instance. Similarly stash the inferior pid.
751 m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
752 m_pid = pid;
753 launch_info.SetProcessID(pid);
754
755 if (m_terminal_fd != -1) {
756 error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
757 if (error.Fail()) {
758 LLDB_LOG(log,
759 "inferior EnsureFDFlags failed for ensuring terminal "
760 "O_NONBLOCK setting: {0}",
761 error);
762
763 // Mark the inferior as invalid.
764 // FIXME this could really use a new state - eStateLaunchFailure. For
765 // now, using eStateInvalid.
766 SetState(StateType::eStateInvalid);
767
768 return error;
769 }
770 }
771
772 LLDB_LOG(log, "adding pid = {0}", pid);
773
774 ResolveProcessArchitecture(m_pid, m_arch);
775
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000776 error = ReinitializeThreads();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000777 if (error.Fail()) {
778 SetState(StateType::eStateInvalid);
779 return error;
780 }
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000781
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000782 for (const auto &thread_sp : m_threads) {
783 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
784 SIGSTOP);
785 }
786
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000787 /* Set process stopped */
788 SetState(StateType::eStateStopped);
789
790 if (error.Fail())
791 LLDB_LOG(log, "inferior launching failed {0}", error);
792 return error;
793}
794
795void NativeProcessNetBSD::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
Zachary Turner97206d52017-05-12 04:51:55 +0000796 Status &error) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000797 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
798 LLDB_LOG(log, "pid = {0:x}", pid);
799
800 m_sigchld_handle = mainloop.RegisterSignal(
801 SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
802 if (!m_sigchld_handle)
803 return;
804
805 error = ResolveProcessArchitecture(pid, m_arch);
806 if (!error.Success())
807 return;
808
809 // Set the architecture to the exe architecture.
810 LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
811 m_arch.GetArchitectureName());
812
813 m_pid = pid;
814 SetState(eStateAttaching);
815
816 Attach(pid, error);
817}
818
819void NativeProcessNetBSD::SigchldHandler() {
820 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
821 // Process all pending waitpid notifications.
822 int status;
823 ::pid_t wait_pid = waitpid(GetID(), &status, WALLSIG | WNOHANG);
824
825 if (wait_pid == 0)
826 return; // We are done.
827
828 if (wait_pid == -1) {
829 if (errno == EINTR)
830 return;
831
Zachary Turner97206d52017-05-12 04:51:55 +0000832 Status error(errno, eErrorTypePOSIX);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000833 LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
834 }
835
Pavel Labath3508fc82017-06-19 12:47:50 +0000836 WaitStatus wait_status = WaitStatus::Decode(status);
837 bool exited = wait_status.type == WaitStatus::Exit ||
838 (wait_status.type == WaitStatus::Signal &&
839 wait_pid == static_cast<::pid_t>(GetID()));
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000840
841 LLDB_LOG(log,
Pavel Labath3508fc82017-06-19 12:47:50 +0000842 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
843 GetID(), wait_pid, status, exited);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000844
845 if (exited)
Pavel Labath3508fc82017-06-19 12:47:50 +0000846 MonitorExited(wait_pid, wait_status);
847 else {
Kamil Rytarowski4bb74412017-06-20 13:51:06 +0000848 assert(wait_status.type == WaitStatus::Stop);
Pavel Labath3508fc82017-06-19 12:47:50 +0000849 MonitorCallback(wait_pid, wait_status.status);
850 }
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000851}
852
Kamil Rytarowski269eec02017-05-24 23:59:50 +0000853bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
854 for (auto thread_sp : m_threads) {
855 assert(thread_sp && "thread list should not contain NULL threads");
856 if (thread_sp->GetID() == thread_id) {
857 // We have this thread.
858 return true;
859 }
860 }
861
862 // We don't have this thread.
863 return false;
864}
865
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000866NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
867
868 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
869 LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
870
871 assert(!HasThreadNoLock(thread_id) &&
872 "attempted to add a thread by id that already exists");
873
874 // If this is the first thread, save it as the current thread
875 if (m_threads.empty())
876 SetCurrentThreadID(thread_id);
877
878 auto thread_sp = std::make_shared<NativeThreadNetBSD>(this, thread_id);
879 m_threads.push_back(thread_sp);
880 return thread_sp;
881}
882
Zachary Turner97206d52017-05-12 04:51:55 +0000883::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Status &error) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000884 if (pid <= 1) {
885 error.SetErrorToGenericError();
886 error.SetErrorString("Attaching to process 1 is not allowed.");
887 return -1;
888 }
889
890 // Attach to the requested process.
891 // An attach will cause the thread to stop with a SIGSTOP.
892 error = PtraceWrapper(PT_ATTACH, pid);
893 if (error.Fail())
894 return -1;
895
896 int status;
897 // Need to use WALLSIG otherwise we receive an error with errno=ECHLD
898 // At this point we should have a thread stopped if waitpid succeeds.
899 if ((status = waitpid(pid, NULL, WALLSIG)) < 0)
900 return -1;
901
902 m_pid = pid;
903
904 /* Initialize threads */
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000905 error = ReinitializeThreads();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000906 if (error.Fail()) {
907 SetState(StateType::eStateInvalid);
908 return -1;
909 }
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000910
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000911 for (const auto &thread_sp : m_threads) {
912 static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
913 SIGSTOP);
914 }
915
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000916 // Let our process instance know the thread has stopped.
917 SetState(StateType::eStateStopped);
918
919 return pid;
920}
921
Zachary Turner97206d52017-05-12 04:51:55 +0000922Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
923 size_t size, size_t &bytes_read) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000924 unsigned char *dst = static_cast<unsigned char *>(buf);
925 struct ptrace_io_desc io;
926
927 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
928 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
929
930 bytes_read = 0;
931 io.piod_op = PIOD_READ_D;
932 io.piod_len = size;
933
934 do {
935 io.piod_offs = (void *)(addr + bytes_read);
936 io.piod_addr = dst + bytes_read;
937
Zachary Turner97206d52017-05-12 04:51:55 +0000938 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000939 if (error.Fail())
940 return error;
941
942 bytes_read = io.piod_len;
943 io.piod_len = size - bytes_read;
944 } while (bytes_read < size);
945
Zachary Turner97206d52017-05-12 04:51:55 +0000946 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000947}
948
Zachary Turner97206d52017-05-12 04:51:55 +0000949Status NativeProcessNetBSD::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
950 size_t size,
951 size_t &bytes_read) {
952 Status error = ReadMemory(addr, buf, size, bytes_read);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000953 if (error.Fail())
954 return error;
955 return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size);
956}
957
Zachary Turner97206d52017-05-12 04:51:55 +0000958Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
959 size_t size, size_t &bytes_written) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000960 const unsigned char *src = static_cast<const unsigned char *>(buf);
Zachary Turner97206d52017-05-12 04:51:55 +0000961 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000962 struct ptrace_io_desc io;
963
964 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
965 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
966
967 bytes_written = 0;
968 io.piod_op = PIOD_WRITE_D;
969 io.piod_len = size;
970
971 do {
Kamil Rytarowski269eec02017-05-24 23:59:50 +0000972 io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000973 io.piod_offs = (void *)(addr + bytes_written);
974
Zachary Turner97206d52017-05-12 04:51:55 +0000975 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000976 if (error.Fail())
977 return error;
978
979 bytes_written = io.piod_len;
980 io.piod_len = size - bytes_written;
981 } while (bytes_written < size);
982
983 return error;
984}
985
986llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
987NativeProcessNetBSD::GetAuxvData() const {
988 /*
989 * ELF_AUX_ENTRIES is currently restricted to kernel
990 * (<sys/exec_elf.h> r. 1.155 specifies 15)
991 *
992 * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
993 * information isn't needed.
994 */
995 size_t auxv_size = 100 * sizeof(AuxInfo);
996
997 ErrorOr<std::unique_ptr<MemoryBuffer>> buf =
998 llvm::MemoryBuffer::getNewMemBuffer(auxv_size);
999
Kamil Rytarowski269eec02017-05-24 23:59:50 +00001000 struct ptrace_io_desc io;
1001 io.piod_op = PIOD_READ_AUXV;
1002 io.piod_offs = 0;
1003 io.piod_addr = const_cast<void *>(static_cast<const void *>(buf.get()->getBufferStart()));
1004 io.piod_len = auxv_size;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +00001005
Zachary Turner97206d52017-05-12 04:51:55 +00001006 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +00001007
1008 if (error.Fail())
1009 return std::error_code(error.GetError(), std::generic_category());
1010
1011 if (io.piod_len < 1)
1012 return std::error_code(ECANCELED, std::generic_category());
1013
1014 return buf;
1015}
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +00001016
Zachary Turner97206d52017-05-12 04:51:55 +00001017Status NativeProcessNetBSD::ReinitializeThreads() {
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +00001018 // Clear old threads
1019 m_threads.clear();
1020
1021 // Initialize new thread
1022 struct ptrace_lwpinfo info = {};
Zachary Turner97206d52017-05-12 04:51:55 +00001023 Status error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +00001024 if (error.Fail()) {
1025 return error;
1026 }
1027 // Reinitialize from scratch threads and register them in process
1028 while (info.pl_lwpid != 0) {
1029 NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +00001030 error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
1031 if (error.Fail()) {
1032 return error;
1033 }
1034 }
1035
1036 return error;
1037}