blob: 1a4cb21d000e0821073731d9a377f0b4c83399fe [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"
Pavel Labathc1a6b122017-07-03 09:25:55 +000024#include "llvm/Support/Errno.h"
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +000025
26// System includes - They have to be included after framework includes because
Adrian Prantl05097242018-04-30 16:49:04 +000027// they define some 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
Pavel Labath82abefa2017-07-18 09:24:48 +000066llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Pavel Labath96e600f2017-07-07 11:02:19 +000067NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
68 NativeDelegate &native_delegate,
69 MainLoop &mainloop) const {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000070 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
71
Pavel Labath96e600f2017-07-07 11:02:19 +000072 Status status;
73 ::pid_t pid = ProcessLauncherPosixFork()
74 .LaunchProcess(launch_info, status)
75 .GetProcessId();
76 LLDB_LOG(log, "pid = {0:x}", pid);
77 if (status.Fail()) {
78 LLDB_LOG(log, "failed to launch process: {0}", status);
79 return status.ToError();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000080 }
81
Pavel Labath96e600f2017-07-07 11:02:19 +000082 // Wait for the child process to trap on its call to execve.
83 int wstatus;
84 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
85 assert(wpid == pid);
86 (void)wpid;
87 if (!WIFSTOPPED(wstatus)) {
88 LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
89 WaitStatus::Decode(wstatus));
90 return llvm::make_error<StringError>("Could not sync with inferior process",
91 llvm::inconvertibleErrorCode());
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000092 }
Pavel Labath96e600f2017-07-07 11:02:19 +000093 LLDB_LOG(log, "inferior started, now in stopped state");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +000094
Pavel Labath36e82202018-01-29 10:46:00 +000095 ProcessInstanceInfo Info;
96 if (!Host::GetProcessInfo(pid, Info)) {
97 return llvm::make_error<StringError>("Cannot get process architecture",
98 llvm::inconvertibleErrorCode());
99 }
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000100
Pavel Labath96e600f2017-07-07 11:02:19 +0000101 // Set the architecture to the exe architecture.
102 LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
Pavel Labath36e82202018-01-29 10:46:00 +0000103 Info.GetArchitecture().GetArchitectureName());
Pavel Labath96e600f2017-07-07 11:02:19 +0000104
Pavel Labath82abefa2017-07-18 09:24:48 +0000105 std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
Pavel Labath96e600f2017-07-07 11:02:19 +0000106 pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
Pavel Labath36e82202018-01-29 10:46:00 +0000107 Info.GetArchitecture(), mainloop));
Pavel Labath96e600f2017-07-07 11:02:19 +0000108
Pavel Labath82abefa2017-07-18 09:24:48 +0000109 status = process_up->ReinitializeThreads();
Pavel Labath96e600f2017-07-07 11:02:19 +0000110 if (status.Fail())
111 return status.ToError();
112
Pavel Labatha5be48b2017-10-17 15:52:16 +0000113 for (const auto &thread : process_up->m_threads)
114 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
Kamil Rytarowski8a4bf062018-02-05 13:16:22 +0000115 process_up->SetState(StateType::eStateStopped, false);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000116
Pavel Labath82abefa2017-07-18 09:24:48 +0000117 return std::move(process_up);
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +0000118}
119
Pavel Labath82abefa2017-07-18 09:24:48 +0000120llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
121NativeProcessNetBSD::Factory::Attach(
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +0000122 lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
Pavel Labath96e600f2017-07-07 11:02:19 +0000123 MainLoop &mainloop) const {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000124 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
125 LLDB_LOG(log, "pid = {0:x}", pid);
126
127 // Retrieve the architecture for the running process.
Pavel Labath36e82202018-01-29 10:46:00 +0000128 ProcessInstanceInfo Info;
129 if (!Host::GetProcessInfo(pid, Info)) {
130 return llvm::make_error<StringError>("Cannot get process architecture",
131 llvm::inconvertibleErrorCode());
132 }
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000133
Pavel Labath36e82202018-01-29 10:46:00 +0000134 std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
135 pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000136
Pavel Labath02d4e502018-01-29 11:10:21 +0000137 Status status = process_up->Attach();
Pavel Labath96e600f2017-07-07 11:02:19 +0000138 if (!status.Success())
139 return status.ToError();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000140
Pavel Labath82abefa2017-07-18 09:24:48 +0000141 return std::move(process_up);
Kamil Rytarowski1a3d19d2017-03-21 17:30:47 +0000142}
143
144// -----------------------------------------------------------------------------
145// Public Instance Methods
146// -----------------------------------------------------------------------------
147
Pavel Labath96e600f2017-07-07 11:02:19 +0000148NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
149 NativeDelegate &delegate,
150 const ArchSpec &arch,
151 MainLoop &mainloop)
152 : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) {
153 if (m_terminal_fd != -1) {
154 Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
155 assert(status.Success());
156 }
157
158 Status status;
159 m_sigchld_handle = mainloop.RegisterSignal(
160 SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
161 assert(m_sigchld_handle && status.Success());
162}
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000163
164// Handles all waitpid events from the inferior process.
165void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000166 switch (signal) {
167 case SIGTRAP:
168 return MonitorSIGTRAP(pid);
169 case SIGSTOP:
170 return MonitorSIGSTOP(pid);
171 default:
172 return MonitorSignal(pid, signal);
173 }
174}
175
Pavel Labath3508fc82017-06-19 12:47:50 +0000176void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000177 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
178
Pavel Labath3508fc82017-06-19 12:47:50 +0000179 LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000180
181 /* Stop Tracking All Threads attached to Process */
182 m_threads.clear();
183
Pavel Labath3508fc82017-06-19 12:47:50 +0000184 SetExitStatus(status, true);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000185
186 // Notify delegate that our process has exited.
187 SetState(StateType::eStateExited, true);
188}
189
190void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000191 ptrace_siginfo_t info;
192
193 const auto siginfo_err =
194 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
195
196 // Get details on the signal raised.
197 if (siginfo_err.Success()) {
198 // Handle SIGSTOP from LLGS (LLDB GDB Server)
199 if (info.psi_siginfo.si_code == SI_USER &&
200 info.psi_siginfo.si_pid == ::getpid()) {
Pavel Labatha5be48b2017-10-17 15:52:16 +0000201 /* Stop Tracking all Threads attached to Process */
202 for (const auto &thread : m_threads) {
203 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000204 SIGSTOP, &info.psi_siginfo);
205 }
206 }
207 }
208}
209
210void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
211 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
212 ptrace_siginfo_t info;
213
214 const auto siginfo_err =
215 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
216
217 // Get details on the signal raised.
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000218 if (siginfo_err.Fail()) {
219 return;
220 }
221
222 switch (info.psi_siginfo.si_code) {
223 case TRAP_BRKPT:
Pavel Labatha5be48b2017-10-17 15:52:16 +0000224 for (const auto &thread : m_threads) {
225 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
226 FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread));
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000227 }
228 SetState(StateType::eStateStopped, true);
229 break;
230 case TRAP_TRACE:
Pavel Labatha5be48b2017-10-17 15:52:16 +0000231 for (const auto &thread : m_threads)
232 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace();
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000233 SetState(StateType::eStateStopped, true);
234 break;
235 case TRAP_EXEC: {
Zachary Turner97206d52017-05-12 04:51:55 +0000236 Status error = ReinitializeThreads();
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000237 if (error.Fail()) {
238 SetState(StateType::eStateInvalid);
239 return;
240 }
241
242 // Let our delegate know we have just exec'd.
243 NotifyDidExec();
244
Pavel Labatha5be48b2017-10-17 15:52:16 +0000245 for (const auto &thread : m_threads)
246 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000247 SetState(StateType::eStateStopped, true);
248 } break;
249 case TRAP_DBREG: {
250 // If a watchpoint was hit, report it
251 uint32_t wp_index;
Pavel Labatha5be48b2017-10-17 15:52:16 +0000252 Status error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid])
253 .GetRegisterContext()
Pavel Labathd37349f2017-11-10 11:05:49 +0000254 .GetWatchpointHitIndex(
Pavel Labatha5be48b2017-10-17 15:52:16 +0000255 wp_index, (uintptr_t)info.psi_siginfo.si_addr);
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000256 if (error.Fail())
257 LLDB_LOG(log,
258 "received error while checking for watchpoint hits, pid = "
259 "{0}, LWP = {1}, error = {2}",
260 GetID(), info.psi_lwpid, error);
261 if (wp_index != LLDB_INVALID_INDEX32) {
Pavel Labatha5be48b2017-10-17 15:52:16 +0000262 for (const auto &thread : m_threads)
263 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint(
264 wp_index);
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000265 SetState(StateType::eStateStopped, true);
266 break;
267 }
268
269 // If a breakpoint was hit, report it
270 uint32_t bp_index;
Pavel Labatha5be48b2017-10-17 15:52:16 +0000271 error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid])
272 .GetRegisterContext()
Pavel Labathd37349f2017-11-10 11:05:49 +0000273 .GetHardwareBreakHitIndex(bp_index,
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000274 (uintptr_t)info.psi_siginfo.si_addr);
275 if (error.Fail())
276 LLDB_LOG(log,
277 "received error while checking for hardware "
278 "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
279 GetID(), info.psi_lwpid, error);
280 if (bp_index != LLDB_INVALID_INDEX32) {
Pavel Labatha5be48b2017-10-17 15:52:16 +0000281 for (const auto &thread : m_threads)
282 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000283 SetState(StateType::eStateStopped, true);
284 break;
285 }
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000286 } break;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000287 }
288}
289
290void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000291 ptrace_siginfo_t info;
292 const auto siginfo_err =
293 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
294
Pavel Labatha5be48b2017-10-17 15:52:16 +0000295 for (const auto &thread : m_threads) {
296 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000297 info.psi_siginfo.si_signo, &info.psi_siginfo);
298 }
299 SetState(StateType::eStateStopped, true);
300}
301
Zachary Turner97206d52017-05-12 04:51:55 +0000302Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
303 int data, int *result) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000304 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
Zachary Turner97206d52017-05-12 04:51:55 +0000305 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000306 int ret;
307
308 errno = 0;
309 ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);
310
311 if (ret == -1)
312 error.SetErrorToErrno();
313
314 if (result)
315 *result = ret;
316
317 LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
318
319 if (error.Fail())
320 LLDB_LOG(log, "ptrace() failed: {0}", error);
321
322 return error;
323}
324
Zachary Turner97206d52017-05-12 04:51:55 +0000325Status NativeProcessNetBSD::GetSoftwareBreakpointPCOffset(
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000326 uint32_t &actual_opcode_size) {
327 // FIXME put this behind a breakpoint protocol class that can be
328 // set per architecture. Need ARM, MIPS support here.
329 static const uint8_t g_i386_opcode[] = {0xCC};
330 switch (m_arch.GetMachine()) {
331 case llvm::Triple::x86_64:
332 actual_opcode_size = static_cast<uint32_t>(sizeof(g_i386_opcode));
Zachary Turner97206d52017-05-12 04:51:55 +0000333 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000334 default:
335 assert(false && "CPU type not supported!");
Zachary Turner97206d52017-05-12 04:51:55 +0000336 return Status("CPU type not supported");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000337 }
338}
339
Zachary Turner97206d52017-05-12 04:51:55 +0000340Status
341NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000342 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
Zachary Turner97206d52017-05-12 04:51:55 +0000343 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000344 // Find out the size of a breakpoint (might depend on where we are in the
345 // code).
Pavel Labathd37349f2017-11-10 11:05:49 +0000346 NativeRegisterContext& context = thread.GetRegisterContext();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000347 uint32_t breakpoint_size = 0;
348 error = GetSoftwareBreakpointPCOffset(breakpoint_size);
349 if (error.Fail()) {
350 LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error);
351 return error;
352 } else
353 LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
Adrian Prantl05097242018-04-30 16:49:04 +0000354 // First try probing for a breakpoint at a software breakpoint location: PC -
355 // breakpoint size.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000356 const lldb::addr_t initial_pc_addr =
Pavel Labathd37349f2017-11-10 11:05:49 +0000357 context.GetPCfromBreakpointLocation();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000358 lldb::addr_t breakpoint_addr = initial_pc_addr;
359 if (breakpoint_size > 0) {
360 // Do not allow breakpoint probe to wrap around.
361 if (breakpoint_addr >= breakpoint_size)
362 breakpoint_addr -= breakpoint_size;
363 }
364 // Check if we stopped because of a breakpoint.
365 NativeBreakpointSP breakpoint_sp;
366 error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp);
367 if (!error.Success() || !breakpoint_sp) {
368 // We didn't find one at a software probe location. Nothing to do.
369 LLDB_LOG(log,
370 "pid {0} no lldb breakpoint found at current pc with "
371 "adjustment: {1}",
372 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000373 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000374 }
375 // If the breakpoint is not a software breakpoint, nothing to do.
376 if (!breakpoint_sp->IsSoftwareBreakpoint()) {
377 LLDB_LOG(
378 log,
379 "pid {0} breakpoint found at {1:x}, not software, nothing to adjust",
380 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000381 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000382 }
383 //
384 // We have a software breakpoint and need to adjust the PC.
385 //
386 // Sanity check.
387 if (breakpoint_size == 0) {
388 // Nothing to do! How did we get here?
389 LLDB_LOG(log,
390 "pid {0} breakpoint found at {1:x}, it is software, but the "
391 "size is zero, nothing to do (unexpected)",
392 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000393 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000394 }
395 //
396 // We have a software breakpoint and need to adjust the PC.
397 //
398 // Sanity check.
399 if (breakpoint_size == 0) {
400 // Nothing to do! How did we get here?
401 LLDB_LOG(log,
402 "pid {0} breakpoint found at {1:x}, it is software, but the "
403 "size is zero, nothing to do (unexpected)",
404 GetID(), breakpoint_addr);
Zachary Turner97206d52017-05-12 04:51:55 +0000405 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000406 }
407 // Change the program counter.
408 LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(),
409 thread.GetID(), initial_pc_addr, breakpoint_addr);
Pavel Labathd37349f2017-11-10 11:05:49 +0000410 error = context.SetPC(breakpoint_addr);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000411 if (error.Fail()) {
412 LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(),
413 thread.GetID(), error);
414 return error;
415 }
416 return error;
417}
418
Zachary Turner97206d52017-05-12 04:51:55 +0000419Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000420 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
421 LLDB_LOG(log, "pid {0}", GetID());
422
Pavel Labatha5be48b2017-10-17 15:52:16 +0000423 const auto &thread = m_threads[0];
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000424 const ResumeAction *const action =
Pavel Labatha5be48b2017-10-17 15:52:16 +0000425 resume_actions.GetActionForThread(thread->GetID(), true);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000426
427 if (action == nullptr) {
428 LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
Pavel Labatha5be48b2017-10-17 15:52:16 +0000429 thread->GetID());
Zachary Turner97206d52017-05-12 04:51:55 +0000430 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000431 }
432
Zachary Turner97206d52017-05-12 04:51:55 +0000433 Status error;
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000434
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000435 switch (action->state) {
436 case eStateRunning: {
437 // Run the thread, possibly feeding it the signal.
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000438 error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
439 action->signal);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000440 if (!error.Success())
441 return error;
Pavel Labatha5be48b2017-10-17 15:52:16 +0000442 for (const auto &thread : m_threads)
443 static_cast<NativeThreadNetBSD &>(*thread).SetRunning();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000444 SetState(eStateRunning, true);
445 break;
446 }
447 case eStateStepping:
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000448 // Run the thread, possibly feeding it the signal.
449 error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
450 action->signal);
451 if (!error.Success())
452 return error;
Pavel Labatha5be48b2017-10-17 15:52:16 +0000453 for (const auto &thread : m_threads)
454 static_cast<NativeThreadNetBSD &>(*thread).SetStepping();
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000455 SetState(eStateStepping, true);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000456 break;
457
458 case eStateSuspended:
459 case eStateStopped:
460 llvm_unreachable("Unexpected state");
461
462 default:
Zachary Turner97206d52017-05-12 04:51:55 +0000463 return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
464 "for pid %" PRIu64 ", tid %" PRIu64,
465 __FUNCTION__, StateAsCString(action->state), GetID(),
Pavel Labatha5be48b2017-10-17 15:52:16 +0000466 thread->GetID());
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000467 }
468
Zachary Turner97206d52017-05-12 04:51:55 +0000469 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000470}
471
Zachary Turner97206d52017-05-12 04:51:55 +0000472Status NativeProcessNetBSD::Halt() {
473 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000474
475 if (kill(GetID(), SIGSTOP) != 0)
476 error.SetErrorToErrno();
477
478 return error;
479}
480
Zachary Turner97206d52017-05-12 04:51:55 +0000481Status NativeProcessNetBSD::Detach() {
482 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000483
484 // Stop monitoring the inferior.
485 m_sigchld_handle.reset();
486
487 // Tell ptrace to detach from the process.
488 if (GetID() == LLDB_INVALID_PROCESS_ID)
489 return error;
490
491 return PtraceWrapper(PT_DETACH, GetID());
492}
493
Zachary Turner97206d52017-05-12 04:51:55 +0000494Status NativeProcessNetBSD::Signal(int signo) {
495 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000496
497 if (kill(GetID(), signo))
498 error.SetErrorToErrno();
499
500 return error;
501}
502
Zachary Turner97206d52017-05-12 04:51:55 +0000503Status NativeProcessNetBSD::Kill() {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000504 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
505 LLDB_LOG(log, "pid {0}", GetID());
506
Zachary Turner97206d52017-05-12 04:51:55 +0000507 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000508
509 switch (m_state) {
510 case StateType::eStateInvalid:
511 case StateType::eStateExited:
512 case StateType::eStateCrashed:
513 case StateType::eStateDetached:
514 case StateType::eStateUnloaded:
515 // Nothing to do - the process is already dead.
516 LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
517 StateAsCString(m_state));
518 return error;
519
520 case StateType::eStateConnected:
521 case StateType::eStateAttaching:
522 case StateType::eStateLaunching:
523 case StateType::eStateStopped:
524 case StateType::eStateRunning:
525 case StateType::eStateStepping:
526 case StateType::eStateSuspended:
527 // We can try to kill a process in these states.
528 break;
529 }
530
531 if (kill(GetID(), SIGKILL) != 0) {
532 error.SetErrorToErrno();
533 return error;
534 }
535
536 return error;
537}
538
Zachary Turner97206d52017-05-12 04:51:55 +0000539Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
540 MemoryRegionInfo &range_info) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000541
542 if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
543 // We're done.
Zachary Turner97206d52017-05-12 04:51:55 +0000544 return Status("unsupported");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000545 }
546
Zachary Turner97206d52017-05-12 04:51:55 +0000547 Status error = PopulateMemoryRegionCache();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000548 if (error.Fail()) {
549 return error;
550 }
551
552 lldb::addr_t prev_base_address = 0;
553 // FIXME start by finding the last region that is <= target address using
554 // binary search. Data is sorted.
555 // There can be a ton of regions on pthreads apps with lots of threads.
556 for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
557 ++it) {
558 MemoryRegionInfo &proc_entry_info = it->first;
559 // Sanity check assumption that memory map entries are ascending.
560 assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
561 "descending memory map entries detected, unexpected");
562 prev_base_address = proc_entry_info.GetRange().GetRangeBase();
563 UNUSED_IF_ASSERT_DISABLED(prev_base_address);
Adrian Prantl05097242018-04-30 16:49:04 +0000564 // If the target address comes before this entry, indicate distance to next
565 // region.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000566 if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
567 range_info.GetRange().SetRangeBase(load_addr);
568 range_info.GetRange().SetByteSize(
569 proc_entry_info.GetRange().GetRangeBase() - load_addr);
570 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
571 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
572 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
573 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
574 return error;
575 } else if (proc_entry_info.GetRange().Contains(load_addr)) {
576 // The target address is within the memory region we're processing here.
577 range_info = proc_entry_info;
578 return error;
579 }
580 // The target memory address comes somewhere after the region we just
581 // parsed.
582 }
583 // If we made it here, we didn't find an entry that contained the given
Adrian Prantl05097242018-04-30 16:49:04 +0000584 // address. Return the load_addr as start and the amount of bytes betwwen
585 // load address and the end of the memory as size.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000586 range_info.GetRange().SetRangeBase(load_addr);
587 range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
588 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
589 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
590 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
591 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
592 return error;
593}
594
Zachary Turner97206d52017-05-12 04:51:55 +0000595Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000596 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
597 // If our cache is empty, pull the latest. There should always be at least
598 // one memory region if memory region handling is supported.
599 if (!m_mem_region_cache.empty()) {
600 LLDB_LOG(log, "reusing {0} cached memory region entries",
601 m_mem_region_cache.size());
Zachary Turner97206d52017-05-12 04:51:55 +0000602 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000603 }
604
605 struct kinfo_vmentry *vm;
606 size_t count, i;
607 vm = kinfo_getvmmap(GetID(), &count);
608 if (vm == NULL) {
609 m_supports_mem_region = LazyBool::eLazyBoolNo;
Zachary Turner97206d52017-05-12 04:51:55 +0000610 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000611 error.SetErrorString("not supported");
612 return error;
613 }
614 for (i = 0; i < count; i++) {
615 MemoryRegionInfo info;
616 info.Clear();
617 info.GetRange().SetRangeBase(vm[i].kve_start);
618 info.GetRange().SetRangeEnd(vm[i].kve_end);
619 info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
620
621 if (vm[i].kve_protection & VM_PROT_READ)
622 info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
623 else
624 info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
625
626 if (vm[i].kve_protection & VM_PROT_WRITE)
627 info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
628 else
629 info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
630
631 if (vm[i].kve_protection & VM_PROT_EXECUTE)
632 info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
633 else
634 info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
635
636 if (vm[i].kve_path[0])
637 info.SetName(vm[i].kve_path);
638
639 m_mem_region_cache.emplace_back(
640 info, FileSpec(info.GetName().GetCString(), true));
641 }
642 free(vm);
643
644 if (m_mem_region_cache.empty()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000645 // No entries after attempting to read them. This shouldn't happen. Assume
646 // we don't support map entries.
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000647 LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
648 "for memory region metadata retrieval");
649 m_supports_mem_region = LazyBool::eLazyBoolNo;
Zachary Turner97206d52017-05-12 04:51:55 +0000650 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000651 error.SetErrorString("not supported");
652 return error;
653 }
654 LLDB_LOG(log, "read {0} memory region entries from process {1}",
655 m_mem_region_cache.size(), GetID());
656 // We support memory retrieval, remember that.
657 m_supports_mem_region = LazyBool::eLazyBoolYes;
Zachary Turner97206d52017-05-12 04:51:55 +0000658 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000659}
660
Zachary Turner97206d52017-05-12 04:51:55 +0000661Status NativeProcessNetBSD::AllocateMemory(size_t size, uint32_t permissions,
662 lldb::addr_t &addr) {
663 return Status("Unimplemented");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000664}
665
Zachary Turner97206d52017-05-12 04:51:55 +0000666Status NativeProcessNetBSD::DeallocateMemory(lldb::addr_t addr) {
667 return Status("Unimplemented");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000668}
669
670lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
671 // punt on this for now
672 return LLDB_INVALID_ADDRESS;
673}
674
675size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }
676
Zachary Turner97206d52017-05-12 04:51:55 +0000677Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
678 bool hardware) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000679 if (hardware)
Zachary Turner97206d52017-05-12 04:51:55 +0000680 return Status("NativeProcessNetBSD does not support hardware breakpoints");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000681 else
682 return SetSoftwareBreakpoint(addr, size);
683}
684
Zachary Turner97206d52017-05-12 04:51:55 +0000685Status NativeProcessNetBSD::GetSoftwareBreakpointTrapOpcode(
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000686 size_t trap_opcode_size_hint, size_t &actual_opcode_size,
687 const uint8_t *&trap_opcode_bytes) {
688 static const uint8_t g_i386_opcode[] = {0xCC};
689
690 switch (m_arch.GetMachine()) {
691 case llvm::Triple::x86:
692 case llvm::Triple::x86_64:
693 trap_opcode_bytes = g_i386_opcode;
694 actual_opcode_size = sizeof(g_i386_opcode);
Zachary Turner97206d52017-05-12 04:51:55 +0000695 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000696 default:
697 assert(false && "CPU type not supported!");
Zachary Turner97206d52017-05-12 04:51:55 +0000698 return Status("CPU type not supported");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000699 }
700}
701
Zachary Turner97206d52017-05-12 04:51:55 +0000702Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
703 FileSpec &file_spec) {
704 return Status("Unimplemented");
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000705}
706
Zachary Turner97206d52017-05-12 04:51:55 +0000707Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
708 lldb::addr_t &load_addr) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000709 load_addr = LLDB_INVALID_ADDRESS;
Zachary Turner97206d52017-05-12 04:51:55 +0000710 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000711}
712
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000713void NativeProcessNetBSD::SigchldHandler() {
714 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
715 // Process all pending waitpid notifications.
716 int status;
Pavel Labathc1a6b122017-07-03 09:25:55 +0000717 ::pid_t wait_pid =
718 llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000719
720 if (wait_pid == 0)
721 return; // We are done.
722
723 if (wait_pid == -1) {
Zachary Turner97206d52017-05-12 04:51:55 +0000724 Status error(errno, eErrorTypePOSIX);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000725 LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
726 }
727
Pavel Labath3508fc82017-06-19 12:47:50 +0000728 WaitStatus wait_status = WaitStatus::Decode(status);
729 bool exited = wait_status.type == WaitStatus::Exit ||
730 (wait_status.type == WaitStatus::Signal &&
731 wait_pid == static_cast<::pid_t>(GetID()));
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000732
733 LLDB_LOG(log,
Pavel Labath3508fc82017-06-19 12:47:50 +0000734 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
735 GetID(), wait_pid, status, exited);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000736
737 if (exited)
Pavel Labath3508fc82017-06-19 12:47:50 +0000738 MonitorExited(wait_pid, wait_status);
739 else {
Kamil Rytarowski4bb74412017-06-20 13:51:06 +0000740 assert(wait_status.type == WaitStatus::Stop);
Pavel Labath3508fc82017-06-19 12:47:50 +0000741 MonitorCallback(wait_pid, wait_status.status);
742 }
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000743}
744
Kamil Rytarowski269eec02017-05-24 23:59:50 +0000745bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
Pavel Labatha5be48b2017-10-17 15:52:16 +0000746 for (const auto &thread : m_threads) {
747 assert(thread && "thread list should not contain NULL threads");
748 if (thread->GetID() == thread_id) {
Kamil Rytarowski269eec02017-05-24 23:59:50 +0000749 // We have this thread.
750 return true;
751 }
752 }
753
754 // We don't have this thread.
755 return false;
756}
757
Pavel Labatha5be48b2017-10-17 15:52:16 +0000758NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000759
760 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
761 LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
762
763 assert(!HasThreadNoLock(thread_id) &&
764 "attempted to add a thread by id that already exists");
765
766 // If this is the first thread, save it as the current thread
767 if (m_threads.empty())
768 SetCurrentThreadID(thread_id);
769
Pavel Labatha5be48b2017-10-17 15:52:16 +0000770 m_threads.push_back(llvm::make_unique<NativeThreadNetBSD>(*this, thread_id));
771 return static_cast<NativeThreadNetBSD &>(*m_threads.back());
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000772}
773
Pavel Labath96e600f2017-07-07 11:02:19 +0000774Status NativeProcessNetBSD::Attach() {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000775 // Attach to the requested process.
776 // An attach will cause the thread to stop with a SIGSTOP.
Pavel Labath96e600f2017-07-07 11:02:19 +0000777 Status status = PtraceWrapper(PT_ATTACH, m_pid);
778 if (status.Fail())
779 return status;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000780
Pavel Labath96e600f2017-07-07 11:02:19 +0000781 int wstatus;
Adrian Prantl05097242018-04-30 16:49:04 +0000782 // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
783 // point we should have a thread stopped if waitpid succeeds.
Pavel Labath96e600f2017-07-07 11:02:19 +0000784 if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0)
785 return Status(errno, eErrorTypePOSIX);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000786
787 /* Initialize threads */
Pavel Labath96e600f2017-07-07 11:02:19 +0000788 status = ReinitializeThreads();
789 if (status.Fail())
790 return status;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000791
Pavel Labatha5be48b2017-10-17 15:52:16 +0000792 for (const auto &thread : m_threads)
793 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
Kamil Rytarowski36e23ec2017-04-18 12:53:35 +0000794
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000795 // Let our process instance know the thread has stopped.
796 SetState(StateType::eStateStopped);
Pavel Labath96e600f2017-07-07 11:02:19 +0000797 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000798}
799
Zachary Turner97206d52017-05-12 04:51:55 +0000800Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
801 size_t size, size_t &bytes_read) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000802 unsigned char *dst = static_cast<unsigned char *>(buf);
803 struct ptrace_io_desc io;
804
805 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
806 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
807
808 bytes_read = 0;
809 io.piod_op = PIOD_READ_D;
810 io.piod_len = size;
811
812 do {
813 io.piod_offs = (void *)(addr + bytes_read);
814 io.piod_addr = dst + bytes_read;
815
Zachary Turner97206d52017-05-12 04:51:55 +0000816 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000817 if (error.Fail())
818 return error;
819
820 bytes_read = io.piod_len;
821 io.piod_len = size - bytes_read;
822 } while (bytes_read < size);
823
Zachary Turner97206d52017-05-12 04:51:55 +0000824 return Status();
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000825}
826
Zachary Turner97206d52017-05-12 04:51:55 +0000827Status NativeProcessNetBSD::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
828 size_t size,
829 size_t &bytes_read) {
830 Status error = ReadMemory(addr, buf, size, bytes_read);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000831 if (error.Fail())
832 return error;
833 return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size);
834}
835
Zachary Turner97206d52017-05-12 04:51:55 +0000836Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
837 size_t size, size_t &bytes_written) {
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000838 const unsigned char *src = static_cast<const unsigned char *>(buf);
Zachary Turner97206d52017-05-12 04:51:55 +0000839 Status error;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000840 struct ptrace_io_desc io;
841
842 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
843 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
844
845 bytes_written = 0;
846 io.piod_op = PIOD_WRITE_D;
847 io.piod_len = size;
848
849 do {
Kamil Rytarowski269eec02017-05-24 23:59:50 +0000850 io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000851 io.piod_offs = (void *)(addr + bytes_written);
852
Zachary Turner97206d52017-05-12 04:51:55 +0000853 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000854 if (error.Fail())
855 return error;
856
857 bytes_written = io.piod_len;
858 io.piod_len = size - bytes_written;
859 } while (bytes_written < size);
860
861 return error;
862}
863
864llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
865NativeProcessNetBSD::GetAuxvData() const {
866 /*
867 * ELF_AUX_ENTRIES is currently restricted to kernel
868 * (<sys/exec_elf.h> r. 1.155 specifies 15)
869 *
870 * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
871 * information isn't needed.
872 */
873 size_t auxv_size = 100 * sizeof(AuxInfo);
874
Pavel Labathe831bb32018-01-15 11:32:43 +0000875 ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
Pavel Labathdbda2852018-01-15 11:50:05 +0000876 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000877
Kamil Rytarowski269eec02017-05-24 23:59:50 +0000878 struct ptrace_io_desc io;
879 io.piod_op = PIOD_READ_AUXV;
880 io.piod_offs = 0;
Pavel Labathe831bb32018-01-15 11:32:43 +0000881 io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
Kamil Rytarowski269eec02017-05-24 23:59:50 +0000882 io.piod_len = auxv_size;
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000883
Zachary Turner97206d52017-05-12 04:51:55 +0000884 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000885
886 if (error.Fail())
887 return std::error_code(error.GetError(), std::generic_category());
888
889 if (io.piod_len < 1)
890 return std::error_code(ECANCELED, std::generic_category());
891
Pavel Labathe831bb32018-01-15 11:32:43 +0000892 return std::move(buf);
Kamil Rytarowskif07a9992017-03-28 22:43:17 +0000893}
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000894
Zachary Turner97206d52017-05-12 04:51:55 +0000895Status NativeProcessNetBSD::ReinitializeThreads() {
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000896 // Clear old threads
897 m_threads.clear();
898
899 // Initialize new thread
900 struct ptrace_lwpinfo info = {};
Zachary Turner97206d52017-05-12 04:51:55 +0000901 Status error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000902 if (error.Fail()) {
903 return error;
904 }
905 // Reinitialize from scratch threads and register them in process
906 while (info.pl_lwpid != 0) {
Pavel Labatha5be48b2017-10-17 15:52:16 +0000907 AddThread(info.pl_lwpid);
Kamil Rytarowski3eef2b52017-03-30 20:25:29 +0000908 error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
909 if (error.Fail()) {
910 return error;
911 }
912 }
913
914 return error;
915}