1061da546Spatrick //===-- NativeProcessOpenBSD.cpp ------------------------------- -*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // The LLVM Compiler Infrastructure
4061da546Spatrick //
5061da546Spatrick // This file is distributed under the University of Illinois Open Source
6061da546Spatrick // License. See LICENSE.TXT for details.
7061da546Spatrick //
8061da546Spatrick //===----------------------------------------------------------------------===//
9061da546Spatrick
10061da546Spatrick #include "NativeProcessOpenBSD.h"
11061da546Spatrick
12061da546Spatrick // C Includes
13061da546Spatrick #include <errno.h>
14061da546Spatrick #define _DYN_LOADER
15061da546Spatrick #include <elf.h>
16061da546Spatrick #include <util.h>
17061da546Spatrick
18061da546Spatrick // C++ Includes
19061da546Spatrick
20061da546Spatrick #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
21061da546Spatrick #include "lldb/Host/HostProcess.h"
22061da546Spatrick #include "lldb/Host/common/NativeRegisterContext.h"
23061da546Spatrick #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
24061da546Spatrick #include "llvm/Support/Errno.h"
25061da546Spatrick #include "lldb/Target/Process.h"
26061da546Spatrick #include "lldb/Utility/State.h"
27061da546Spatrick
28061da546Spatrick // System includes - They have to be included after framework includes because
29061da546Spatrick // they define some macros which collide with variable names in other modules
30061da546Spatrick // clang-format off
31061da546Spatrick #include <sys/types.h>
32061da546Spatrick #include <sys/ptrace.h>
33061da546Spatrick #include <sys/sysctl.h>
34061da546Spatrick #include <sys/wait.h>
35061da546Spatrick // clang-format on
36061da546Spatrick
37061da546Spatrick using namespace lldb;
38061da546Spatrick using namespace lldb_private;
39061da546Spatrick using namespace lldb_private::process_openbsd;
40061da546Spatrick using namespace llvm;
41061da546Spatrick
42061da546Spatrick // Simple helper function to ensure flags are enabled on the given file
43061da546Spatrick // descriptor.
EnsureFDFlags(int fd,int flags)44061da546Spatrick static Status EnsureFDFlags(int fd, int flags) {
45061da546Spatrick Status error;
46061da546Spatrick
47061da546Spatrick int status = fcntl(fd, F_GETFL);
48061da546Spatrick if (status == -1) {
49061da546Spatrick error.SetErrorToErrno();
50061da546Spatrick return error;
51061da546Spatrick }
52061da546Spatrick
53061da546Spatrick if (fcntl(fd, F_SETFL, status | flags) == -1) {
54061da546Spatrick error.SetErrorToErrno();
55061da546Spatrick return error;
56061da546Spatrick }
57061da546Spatrick
58061da546Spatrick return error;
59061da546Spatrick }
60061da546Spatrick
61061da546Spatrick // -----------------------------------------------------------------------------
62061da546Spatrick // Public Static Methods
63061da546Spatrick // -----------------------------------------------------------------------------
64061da546Spatrick
65061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo & launch_info,NativeDelegate & native_delegate,MainLoop & mainloop) const66061da546Spatrick NativeProcessOpenBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
67061da546Spatrick NativeDelegate &native_delegate,
68061da546Spatrick MainLoop &mainloop) const {
69*101d251dSrobert Log *log = GetLog(POSIXLog::Process);
70061da546Spatrick
71061da546Spatrick Status status;
72061da546Spatrick ::pid_t pid = ProcessLauncherPosixFork()
73061da546Spatrick .LaunchProcess(launch_info, status)
74061da546Spatrick .GetProcessId();
75061da546Spatrick LLDB_LOG(log, "pid = {0:x}", pid);
76061da546Spatrick if (status.Fail()) {
77061da546Spatrick LLDB_LOG(log, "failed to launch process: {0}", status);
78061da546Spatrick return status.ToError();
79061da546Spatrick }
80061da546Spatrick
81061da546Spatrick // Wait for the child process to trap on its call to execve.
82061da546Spatrick int wstatus;
83061da546Spatrick ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
84061da546Spatrick assert(wpid == pid);
85061da546Spatrick (void)wpid;
86061da546Spatrick if (!WIFSTOPPED(wstatus)) {
87061da546Spatrick LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
88061da546Spatrick WaitStatus::Decode(wstatus));
89061da546Spatrick return llvm::make_error<StringError>("Could not sync with inferior process",
90061da546Spatrick llvm::inconvertibleErrorCode());
91061da546Spatrick }
92061da546Spatrick LLDB_LOG(log, "inferior started, now in stopped state");
93061da546Spatrick
94061da546Spatrick ProcessInstanceInfo Info;
95061da546Spatrick if (!Host::GetProcessInfo(pid, Info)) {
96061da546Spatrick return llvm::make_error<StringError>("Cannot get process architecture",
97061da546Spatrick llvm::inconvertibleErrorCode());
98061da546Spatrick }
99061da546Spatrick
100061da546Spatrick // Set the architecture to the exe architecture.
101061da546Spatrick LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
102061da546Spatrick Info.GetArchitecture().GetArchitectureName());
103061da546Spatrick
104061da546Spatrick std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
105adae0cfdSpatrick pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
106061da546Spatrick Info.GetArchitecture(), mainloop));
107061da546Spatrick
108061da546Spatrick status = process_up->ReinitializeThreads();
109061da546Spatrick if (status.Fail())
110061da546Spatrick return status.ToError();
111061da546Spatrick
112061da546Spatrick for (const auto &thread : process_up->m_threads)
113061da546Spatrick static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
114061da546Spatrick process_up->SetState(StateType::eStateStopped, false);
115061da546Spatrick
116061da546Spatrick return std::move(process_up);
117061da546Spatrick }
118061da546Spatrick
119061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const120061da546Spatrick NativeProcessOpenBSD::Factory::Attach(
121061da546Spatrick lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
122061da546Spatrick MainLoop &mainloop) const {
123061da546Spatrick
124*101d251dSrobert Log *log = GetLog(POSIXLog::Process);
125061da546Spatrick LLDB_LOG(log, "pid = {0:x}", pid);
126061da546Spatrick
127061da546Spatrick // Retrieve the architecture for the running process.
128061da546Spatrick ProcessInstanceInfo Info;
129061da546Spatrick if (!Host::GetProcessInfo(pid, Info)) {
130061da546Spatrick return llvm::make_error<StringError>("Cannot get process architecture",
131061da546Spatrick llvm::inconvertibleErrorCode());
132061da546Spatrick }
133061da546Spatrick
134061da546Spatrick std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
135061da546Spatrick pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
136061da546Spatrick
137061da546Spatrick Status status = process_up->Attach();
138061da546Spatrick if (!status.Success())
139061da546Spatrick return status.ToError();
140061da546Spatrick
141061da546Spatrick return std::move(process_up);
142061da546Spatrick }
143061da546Spatrick
144a0747c9fSpatrick NativeProcessOpenBSD::Extension
GetSupportedExtensions() const145a0747c9fSpatrick NativeProcessOpenBSD::Factory::GetSupportedExtensions() const {
146a0747c9fSpatrick return Extension::multiprocess | Extension::fork | Extension::vfork |
147a0747c9fSpatrick Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
148a0747c9fSpatrick }
149a0747c9fSpatrick
150a0747c9fSpatrick
151061da546Spatrick // -----------------------------------------------------------------------------
152061da546Spatrick // Public Instance Methods
153061da546Spatrick // -----------------------------------------------------------------------------
154061da546Spatrick
NativeProcessOpenBSD(::pid_t pid,int terminal_fd,NativeDelegate & delegate,const ArchSpec & arch,MainLoop & mainloop)155061da546Spatrick NativeProcessOpenBSD::NativeProcessOpenBSD(::pid_t pid, int terminal_fd,
156061da546Spatrick NativeDelegate &delegate,
157061da546Spatrick const ArchSpec &arch,
158061da546Spatrick MainLoop &mainloop)
159061da546Spatrick : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) {
160061da546Spatrick if (m_terminal_fd != -1) {
161061da546Spatrick Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
162061da546Spatrick assert(status.Success());
163061da546Spatrick }
164061da546Spatrick
165061da546Spatrick Status status;
166061da546Spatrick m_sigchld_handle = mainloop.RegisterSignal(
167061da546Spatrick SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
168061da546Spatrick assert(m_sigchld_handle && status.Success());
169061da546Spatrick }
170061da546Spatrick
171061da546Spatrick // Handles all waitpid events from the inferior process.
MonitorCallback(lldb::pid_t pid,int signal)172061da546Spatrick void NativeProcessOpenBSD::MonitorCallback(lldb::pid_t pid, int signal) {
173061da546Spatrick switch (signal) {
174061da546Spatrick case SIGTRAP:
175061da546Spatrick return MonitorSIGTRAP(pid);
176061da546Spatrick default:
177061da546Spatrick return MonitorSignal(pid, signal);
178061da546Spatrick }
179061da546Spatrick }
180061da546Spatrick
MonitorExited(lldb::pid_t pid,WaitStatus status)181061da546Spatrick void NativeProcessOpenBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
182*101d251dSrobert Log *log = GetLog(POSIXLog::Process);
183061da546Spatrick
184061da546Spatrick LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
185061da546Spatrick
186061da546Spatrick /* Stop Tracking All Threads attached to Process */
187061da546Spatrick m_threads.clear();
188061da546Spatrick
189061da546Spatrick SetExitStatus(status, true);
190061da546Spatrick
191061da546Spatrick // Notify delegate that our process has exited.
192061da546Spatrick SetState(StateType::eStateExited, true);
193061da546Spatrick }
194061da546Spatrick
MonitorSIGTRAP(lldb::pid_t pid)195061da546Spatrick void NativeProcessOpenBSD::MonitorSIGTRAP(lldb::pid_t pid) {
196061da546Spatrick for (const auto &thread : m_threads) {
197061da546Spatrick static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedByBreakpoint();
198061da546Spatrick FixupBreakpointPCAsNeeded(static_cast<NativeThreadOpenBSD &>(*thread));
199061da546Spatrick }
200061da546Spatrick SetState(StateType::eStateStopped, true);
201061da546Spatrick }
202061da546Spatrick
203061da546Spatrick
MonitorSignal(lldb::pid_t pid,int signal)204061da546Spatrick void NativeProcessOpenBSD::MonitorSignal(lldb::pid_t pid, int signal) {
205061da546Spatrick for (const auto &thread : m_threads) {
206061da546Spatrick static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(signal);
207061da546Spatrick }
208061da546Spatrick SetState(StateType::eStateStopped, true);
209061da546Spatrick }
210061da546Spatrick
PtraceWrapper(int req,lldb::pid_t pid,void * addr,int data,int * result)211061da546Spatrick Status NativeProcessOpenBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
212061da546Spatrick int data, int *result) {
213*101d251dSrobert Log *log = GetLog(POSIXLog::Process);
214061da546Spatrick Status error;
215061da546Spatrick int ret;
216061da546Spatrick
217061da546Spatrick errno = 0;
218061da546Spatrick ret = ptrace(req, static_cast<::pid_t>(pid), (caddr_t)addr, data);
219061da546Spatrick
220061da546Spatrick if (ret == -1)
221061da546Spatrick error.SetErrorToErrno();
222061da546Spatrick
223061da546Spatrick if (result)
224061da546Spatrick *result = ret;
225061da546Spatrick
226061da546Spatrick LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
227061da546Spatrick
228061da546Spatrick if (error.Fail())
229061da546Spatrick LLDB_LOG(log, "ptrace() failed: {0}", error);
230061da546Spatrick
231061da546Spatrick return error;
232061da546Spatrick }
233061da546Spatrick
Resume(const ResumeActionList & resume_actions)234061da546Spatrick Status NativeProcessOpenBSD::Resume(const ResumeActionList &resume_actions) {
235*101d251dSrobert Log *log = GetLog(POSIXLog::Process);
236061da546Spatrick LLDB_LOG(log, "pid {0}", GetID());
237061da546Spatrick
238061da546Spatrick const auto &thread = m_threads[0];
239061da546Spatrick const ResumeAction *const action =
240061da546Spatrick resume_actions.GetActionForThread(thread->GetID(), true);
241061da546Spatrick
242061da546Spatrick if (action == nullptr) {
243061da546Spatrick LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
244061da546Spatrick thread->GetID());
245061da546Spatrick return Status();
246061da546Spatrick }
247061da546Spatrick
248061da546Spatrick Status error;
249972f549bSmortimer int signal = action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
250061da546Spatrick
251061da546Spatrick switch (action->state) {
252061da546Spatrick case eStateRunning: {
253061da546Spatrick // Run the thread, possibly feeding it the signal.
254061da546Spatrick error = NativeProcessOpenBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
255972f549bSmortimer signal);
256061da546Spatrick if (!error.Success())
257061da546Spatrick return error;
258061da546Spatrick for (const auto &thread : m_threads)
259061da546Spatrick static_cast<NativeThreadOpenBSD &>(*thread).SetRunning();
260061da546Spatrick SetState(eStateRunning, true);
261061da546Spatrick break;
262061da546Spatrick }
263061da546Spatrick case eStateStepping:
264061da546Spatrick #ifdef PT_STEP
265061da546Spatrick // Run the thread, possibly feeding it the signal.
266061da546Spatrick error = NativeProcessOpenBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
267972f549bSmortimer signal);
268061da546Spatrick if (!error.Success())
269061da546Spatrick return error;
270061da546Spatrick for (const auto &thread : m_threads)
271061da546Spatrick static_cast<NativeThreadOpenBSD &>(*thread).SetStepping();
272061da546Spatrick SetState(eStateStepping, true);
273061da546Spatrick break;
274061da546Spatrick #else
275061da546Spatrick return Status("NativeProcessOpenBSD stepping not supported on this platform");
276061da546Spatrick #endif
277061da546Spatrick
278061da546Spatrick case eStateSuspended:
279061da546Spatrick case eStateStopped:
280061da546Spatrick llvm_unreachable("Unexpected state");
281061da546Spatrick
282061da546Spatrick default:
283061da546Spatrick return Status("NativeProcessOpenBSD::%s (): unexpected state %s specified "
284061da546Spatrick "for pid %" PRIu64 ", tid %" PRIu64,
285061da546Spatrick __FUNCTION__, StateAsCString(action->state), GetID(),
286061da546Spatrick thread->GetID());
287061da546Spatrick }
288061da546Spatrick
289061da546Spatrick return Status();
290061da546Spatrick }
291061da546Spatrick
Halt()292061da546Spatrick Status NativeProcessOpenBSD::Halt() {
293061da546Spatrick Status error;
294061da546Spatrick
295061da546Spatrick if (kill(GetID(), SIGSTOP) != 0)
296061da546Spatrick error.SetErrorToErrno();
297061da546Spatrick
298061da546Spatrick return error;
299061da546Spatrick }
300061da546Spatrick
Detach()301061da546Spatrick Status NativeProcessOpenBSD::Detach() {
302061da546Spatrick Status error;
303061da546Spatrick
304061da546Spatrick // Stop monitoring the inferior.
305061da546Spatrick m_sigchld_handle.reset();
306061da546Spatrick
307061da546Spatrick // Tell ptrace to detach from the process.
308061da546Spatrick if (GetID() == LLDB_INVALID_PROCESS_ID)
309061da546Spatrick return error;
310061da546Spatrick
311061da546Spatrick return PtraceWrapper(PT_DETACH, GetID());
312061da546Spatrick }
313061da546Spatrick
Signal(int signo)314061da546Spatrick Status NativeProcessOpenBSD::Signal(int signo) {
315061da546Spatrick Status error;
316061da546Spatrick
317061da546Spatrick if (kill(GetID(), signo))
318061da546Spatrick error.SetErrorToErrno();
319061da546Spatrick
320061da546Spatrick return error;
321061da546Spatrick }
322061da546Spatrick
Kill()323061da546Spatrick Status NativeProcessOpenBSD::Kill() {
324*101d251dSrobert Log *log = GetLog(POSIXLog::Process);
325061da546Spatrick LLDB_LOG(log, "pid {0}", GetID());
326061da546Spatrick
327061da546Spatrick Status error;
328061da546Spatrick
329061da546Spatrick switch (m_state) {
330061da546Spatrick case StateType::eStateInvalid:
331061da546Spatrick case StateType::eStateExited:
332061da546Spatrick case StateType::eStateCrashed:
333061da546Spatrick case StateType::eStateDetached:
334061da546Spatrick case StateType::eStateUnloaded:
335061da546Spatrick // Nothing to do - the process is already dead.
336061da546Spatrick LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
337061da546Spatrick StateAsCString(m_state));
338061da546Spatrick return error;
339061da546Spatrick
340061da546Spatrick case StateType::eStateConnected:
341061da546Spatrick case StateType::eStateAttaching:
342061da546Spatrick case StateType::eStateLaunching:
343061da546Spatrick case StateType::eStateStopped:
344061da546Spatrick case StateType::eStateRunning:
345061da546Spatrick case StateType::eStateStepping:
346061da546Spatrick case StateType::eStateSuspended:
347061da546Spatrick // We can try to kill a process in these states.
348061da546Spatrick break;
349061da546Spatrick }
350061da546Spatrick
351061da546Spatrick if (kill(GetID(), SIGKILL) != 0) {
352061da546Spatrick error.SetErrorToErrno();
353061da546Spatrick return error;
354061da546Spatrick }
355061da546Spatrick
356061da546Spatrick return error;
357061da546Spatrick }
358061da546Spatrick
GetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & range_info)359061da546Spatrick Status NativeProcessOpenBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
360061da546Spatrick MemoryRegionInfo &range_info) {
361061da546Spatrick return Status("Unimplemented");
362061da546Spatrick }
363061da546Spatrick
PopulateMemoryRegionCache()364061da546Spatrick Status NativeProcessOpenBSD::PopulateMemoryRegionCache() {
365061da546Spatrick return Status("Unimplemented");
366061da546Spatrick }
367061da546Spatrick
AllocateMemory(size_t size,uint32_t permissions)368a0747c9fSpatrick llvm::Expected<lldb::addr_t> NativeProcessOpenBSD::AllocateMemory(size_t size,
369a0747c9fSpatrick uint32_t permissions) {
370a0747c9fSpatrick return llvm::make_error<UnimplementedError>();
371061da546Spatrick }
372061da546Spatrick
DeallocateMemory(lldb::addr_t addr)373a0747c9fSpatrick llvm::Error NativeProcessOpenBSD::DeallocateMemory(lldb::addr_t addr) {
374a0747c9fSpatrick return llvm::make_error<UnimplementedError>();
375061da546Spatrick }
376061da546Spatrick
GetSharedLibraryInfoAddress()377061da546Spatrick lldb::addr_t NativeProcessOpenBSD::GetSharedLibraryInfoAddress() {
378061da546Spatrick // punt on this for now
379061da546Spatrick return LLDB_INVALID_ADDRESS;
380061da546Spatrick }
381061da546Spatrick
UpdateThreads()382061da546Spatrick size_t NativeProcessOpenBSD::UpdateThreads() { return m_threads.size(); }
383061da546Spatrick
SetBreakpoint(lldb::addr_t addr,uint32_t size,bool hardware)384061da546Spatrick Status NativeProcessOpenBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
385061da546Spatrick bool hardware) {
386061da546Spatrick if (hardware)
387061da546Spatrick return Status("NativeProcessOpenBSD does not support hardware breakpoints");
388061da546Spatrick else
389061da546Spatrick return SetSoftwareBreakpoint(addr, size);
390061da546Spatrick }
391061da546Spatrick
GetLoadedModuleFileSpec(const char * module_path,FileSpec & file_spec)392061da546Spatrick Status NativeProcessOpenBSD::GetLoadedModuleFileSpec(const char *module_path,
393061da546Spatrick FileSpec &file_spec) {
394061da546Spatrick return Status("Unimplemented");
395061da546Spatrick }
396061da546Spatrick
GetFileLoadAddress(const llvm::StringRef & file_name,lldb::addr_t & load_addr)397061da546Spatrick Status NativeProcessOpenBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
398061da546Spatrick lldb::addr_t &load_addr) {
399061da546Spatrick load_addr = LLDB_INVALID_ADDRESS;
400061da546Spatrick return Status();
401061da546Spatrick }
402061da546Spatrick
SigchldHandler()403061da546Spatrick void NativeProcessOpenBSD::SigchldHandler() {
404*101d251dSrobert Log *log = GetLog(POSIXLog::Process);
405061da546Spatrick // Process all pending waitpid notifications.
406061da546Spatrick int status;
407061da546Spatrick ::pid_t wait_pid =
408061da546Spatrick llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
409061da546Spatrick
410061da546Spatrick if (wait_pid == 0)
411061da546Spatrick return; // We are done.
412061da546Spatrick
413061da546Spatrick if (wait_pid == -1) {
414061da546Spatrick Status error(errno, eErrorTypePOSIX);
415061da546Spatrick LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
416061da546Spatrick }
417061da546Spatrick
418061da546Spatrick WaitStatus wait_status = WaitStatus::Decode(status);
419061da546Spatrick bool exited = wait_status.type == WaitStatus::Exit ||
420061da546Spatrick (wait_status.type == WaitStatus::Signal &&
421061da546Spatrick wait_pid == static_cast<::pid_t>(GetID()));
422061da546Spatrick
423061da546Spatrick LLDB_LOG(log,
424061da546Spatrick "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
425061da546Spatrick GetID(), wait_pid, status, exited);
426061da546Spatrick
427061da546Spatrick if (exited)
428061da546Spatrick MonitorExited(wait_pid, wait_status);
429061da546Spatrick else {
430061da546Spatrick assert(wait_status.type == WaitStatus::Stop);
431061da546Spatrick MonitorCallback(wait_pid, wait_status.status);
432061da546Spatrick }
433061da546Spatrick }
434061da546Spatrick
HasThreadNoLock(lldb::tid_t thread_id)435061da546Spatrick bool NativeProcessOpenBSD::HasThreadNoLock(lldb::tid_t thread_id) {
436061da546Spatrick for (const auto &thread : m_threads) {
437061da546Spatrick assert(thread && "thread list should not contain NULL threads");
438061da546Spatrick if (thread->GetID() == thread_id) {
439061da546Spatrick // We have this thread.
440061da546Spatrick return true;
441061da546Spatrick }
442061da546Spatrick }
443061da546Spatrick
444061da546Spatrick // We don't have this thread.
445061da546Spatrick return false;
446061da546Spatrick }
447061da546Spatrick
AddThread(lldb::tid_t thread_id)448061da546Spatrick NativeThreadOpenBSD &NativeProcessOpenBSD::AddThread(lldb::tid_t thread_id) {
449061da546Spatrick
450*101d251dSrobert Log *log = GetLog(POSIXLog::Thread);
451061da546Spatrick LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
452061da546Spatrick
453061da546Spatrick assert(!HasThreadNoLock(thread_id) &&
454061da546Spatrick "attempted to add a thread by id that already exists");
455061da546Spatrick
456061da546Spatrick // If this is the first thread, save it as the current thread
457061da546Spatrick if (m_threads.empty())
458061da546Spatrick SetCurrentThreadID(thread_id);
459061da546Spatrick
460061da546Spatrick m_threads.push_back(std::make_unique<NativeThreadOpenBSD>(*this, thread_id));
461061da546Spatrick return static_cast<NativeThreadOpenBSD &>(*m_threads.back());
462061da546Spatrick }
463061da546Spatrick
Attach()464061da546Spatrick Status NativeProcessOpenBSD::Attach() {
465061da546Spatrick // Attach to the requested process.
466061da546Spatrick // An attach will cause the thread to stop with a SIGSTOP.
467061da546Spatrick Status status = PtraceWrapper(PT_ATTACH, m_pid);
468061da546Spatrick if (status.Fail())
469061da546Spatrick return status;
470061da546Spatrick
471061da546Spatrick int wstatus;
472061da546Spatrick // At this point we should have a thread stopped if waitpid succeeds.
473061da546Spatrick if ((wstatus = waitpid(m_pid, NULL, 0)) < 0)
474061da546Spatrick return Status(errno, eErrorTypePOSIX);
475061da546Spatrick
476061da546Spatrick /* Initialize threads */
477061da546Spatrick status = ReinitializeThreads();
478061da546Spatrick if (status.Fail())
479061da546Spatrick return status;
480061da546Spatrick
481061da546Spatrick for (const auto &thread : m_threads)
482061da546Spatrick static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
483061da546Spatrick
484061da546Spatrick // Let our process instance know the thread has stopped.
485061da546Spatrick SetState(StateType::eStateStopped);
486061da546Spatrick return Status();
487061da546Spatrick }
488061da546Spatrick
ReadMemory(lldb::addr_t addr,void * buf,size_t size,size_t & bytes_read)489061da546Spatrick Status NativeProcessOpenBSD::ReadMemory(lldb::addr_t addr, void *buf,
490061da546Spatrick size_t size, size_t &bytes_read) {
491061da546Spatrick unsigned char *dst = static_cast<unsigned char *>(buf);
492061da546Spatrick struct ptrace_io_desc io;
493061da546Spatrick
494*101d251dSrobert Log *log = GetLog(POSIXLog::Memory);
495061da546Spatrick LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
496061da546Spatrick
497061da546Spatrick bytes_read = 0;
498061da546Spatrick io.piod_op = PIOD_READ_D;
499061da546Spatrick io.piod_len = size;
500061da546Spatrick
501061da546Spatrick do {
502061da546Spatrick io.piod_offs = (void *)(addr + bytes_read);
503061da546Spatrick io.piod_addr = dst + bytes_read;
504061da546Spatrick
505061da546Spatrick Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
506061da546Spatrick if (error.Fail())
507061da546Spatrick return error;
508061da546Spatrick
509061da546Spatrick bytes_read = io.piod_len;
510061da546Spatrick io.piod_len = size - bytes_read;
511061da546Spatrick } while (bytes_read < size);
512061da546Spatrick
513061da546Spatrick return Status();
514061da546Spatrick }
515061da546Spatrick
WriteMemory(lldb::addr_t addr,const void * buf,size_t size,size_t & bytes_written)516061da546Spatrick Status NativeProcessOpenBSD::WriteMemory(lldb::addr_t addr, const void *buf,
517061da546Spatrick size_t size, size_t &bytes_written) {
518061da546Spatrick const unsigned char *src = static_cast<const unsigned char *>(buf);
519061da546Spatrick Status error;
520061da546Spatrick struct ptrace_io_desc io;
521061da546Spatrick
522*101d251dSrobert Log *log = GetLog(POSIXLog::Memory);
523061da546Spatrick LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
524061da546Spatrick
525061da546Spatrick bytes_written = 0;
526061da546Spatrick io.piod_op = PIOD_WRITE_D;
527061da546Spatrick io.piod_len = size;
528061da546Spatrick
529061da546Spatrick do {
530061da546Spatrick io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
531061da546Spatrick io.piod_offs = (void *)(addr + bytes_written);
532061da546Spatrick
533061da546Spatrick Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
534061da546Spatrick if (error.Fail())
535061da546Spatrick return error;
536061da546Spatrick
537061da546Spatrick bytes_written = io.piod_len;
538061da546Spatrick io.piod_len = size - bytes_written;
539061da546Spatrick } while (bytes_written < size);
540061da546Spatrick
541061da546Spatrick return error;
542061da546Spatrick }
543061da546Spatrick
544061da546Spatrick llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
GetAuxvData() const545061da546Spatrick NativeProcessOpenBSD::GetAuxvData() const {
546061da546Spatrick size_t auxv_size = 100 * sizeof(AuxInfo);
547061da546Spatrick
548061da546Spatrick ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
549061da546Spatrick llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
550061da546Spatrick
551061da546Spatrick struct ptrace_io_desc io;
552061da546Spatrick io.piod_op = PIOD_READ_AUXV;
553061da546Spatrick io.piod_offs = 0;
554061da546Spatrick io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
555061da546Spatrick io.piod_len = auxv_size;
556061da546Spatrick
557061da546Spatrick Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
558061da546Spatrick
559061da546Spatrick if (error.Fail())
560061da546Spatrick return std::error_code(error.GetError(), std::generic_category());
561061da546Spatrick
562061da546Spatrick if (io.piod_len < 1)
563061da546Spatrick return std::error_code(ECANCELED, std::generic_category());
564061da546Spatrick
565061da546Spatrick return std::move(buf);
566061da546Spatrick }
567061da546Spatrick
ReinitializeThreads()568061da546Spatrick Status NativeProcessOpenBSD::ReinitializeThreads() {
569061da546Spatrick // Clear old threads
570061da546Spatrick m_threads.clear();
571061da546Spatrick
572061da546Spatrick // Initialize new thread
573061da546Spatrick struct ptrace_thread_state info = {};
574061da546Spatrick Status error = PtraceWrapper(PT_GET_THREAD_FIRST, GetID(), &info, sizeof(info));
575061da546Spatrick if (error.Fail()) {
576061da546Spatrick return error;
577061da546Spatrick }
578061da546Spatrick // Reinitialize from scratch threads and register them in process
579061da546Spatrick while (info.pts_tid > 0) {
580061da546Spatrick AddThread(info.pts_tid);
581061da546Spatrick error = PtraceWrapper(PT_GET_THREAD_NEXT, GetID(), &info, sizeof(info));
582061da546Spatrick if (error.Fail() && errno != 0) {
583061da546Spatrick return error;
584061da546Spatrick }
585061da546Spatrick }
586061da546Spatrick
587061da546Spatrick return error;
588061da546Spatrick }
589