xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.cpp (revision 101d251d5caf88a9341f3045ab62e122abae1b90)
1 //===-- NativeProcessOpenBSD.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 "NativeProcessOpenBSD.h"
11 
12 // C Includes
13 #include <errno.h>
14 #define _DYN_LOADER
15 #include <elf.h>
16 #include <util.h>
17 
18 // C++ Includes
19 
20 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
21 #include "lldb/Host/HostProcess.h"
22 #include "lldb/Host/common/NativeRegisterContext.h"
23 #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
24 #include "llvm/Support/Errno.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Utility/State.h"
27 
28 // System includes - They have to be included after framework includes because
29 // they define some macros which collide with variable names in other modules
30 // clang-format off
31 #include <sys/types.h>
32 #include <sys/ptrace.h>
33 #include <sys/sysctl.h>
34 #include <sys/wait.h>
35 // clang-format on
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 using namespace lldb_private::process_openbsd;
40 using namespace llvm;
41 
42 // Simple helper function to ensure flags are enabled on the given file
43 // descriptor.
EnsureFDFlags(int fd,int flags)44 static Status EnsureFDFlags(int fd, int flags) {
45   Status error;
46 
47   int status = fcntl(fd, F_GETFL);
48   if (status == -1) {
49     error.SetErrorToErrno();
50     return error;
51   }
52 
53   if (fcntl(fd, F_SETFL, status | flags) == -1) {
54     error.SetErrorToErrno();
55     return error;
56   }
57 
58   return error;
59 }
60 
61 // -----------------------------------------------------------------------------
62 // Public Static Methods
63 // -----------------------------------------------------------------------------
64 
65 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo & launch_info,NativeDelegate & native_delegate,MainLoop & mainloop) const66 NativeProcessOpenBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
67                                      NativeDelegate &native_delegate,
68                                      MainLoop &mainloop) const {
69   Log *log = GetLog(POSIXLog::Process);
70 
71   Status status;
72   ::pid_t pid = ProcessLauncherPosixFork()
73                     .LaunchProcess(launch_info, status)
74                     .GetProcessId();
75   LLDB_LOG(log, "pid = {0:x}", pid);
76   if (status.Fail()) {
77     LLDB_LOG(log, "failed to launch process: {0}", status);
78     return status.ToError();
79   }
80 
81   // Wait for the child process to trap on its call to execve.
82   int wstatus;
83   ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
84   assert(wpid == pid);
85   (void)wpid;
86   if (!WIFSTOPPED(wstatus)) {
87     LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
88              WaitStatus::Decode(wstatus));
89     return llvm::make_error<StringError>("Could not sync with inferior process",
90                                          llvm::inconvertibleErrorCode());
91   }
92   LLDB_LOG(log, "inferior started, now in stopped state");
93 
94   ProcessInstanceInfo Info;
95   if (!Host::GetProcessInfo(pid, Info)) {
96     return llvm::make_error<StringError>("Cannot get process architecture",
97                                          llvm::inconvertibleErrorCode());
98   }
99 
100   // Set the architecture to the exe architecture.
101   LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
102            Info.GetArchitecture().GetArchitectureName());
103 
104   std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
105       pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
106       Info.GetArchitecture(), mainloop));
107 
108   status = process_up->ReinitializeThreads();
109   if (status.Fail())
110     return status.ToError();
111 
112   for (const auto &thread : process_up->m_threads)
113     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
114   process_up->SetState(StateType::eStateStopped, false);
115 
116   return std::move(process_up);
117 }
118 
119 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const120 NativeProcessOpenBSD::Factory::Attach(
121     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
122     MainLoop &mainloop) const {
123 
124   Log *log = GetLog(POSIXLog::Process);
125   LLDB_LOG(log, "pid = {0:x}", pid);
126 
127   // Retrieve the architecture for the running process.
128   ProcessInstanceInfo Info;
129   if (!Host::GetProcessInfo(pid, Info)) {
130     return llvm::make_error<StringError>("Cannot get process architecture",
131                                          llvm::inconvertibleErrorCode());
132   }
133 
134   std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
135       pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
136 
137   Status status = process_up->Attach();
138   if (!status.Success())
139     return status.ToError();
140 
141   return std::move(process_up);
142 }
143 
144 NativeProcessOpenBSD::Extension
GetSupportedExtensions() const145 NativeProcessOpenBSD::Factory::GetSupportedExtensions() const {
146     return Extension::multiprocess | Extension::fork | Extension::vfork |
147            Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
148 }
149 
150 
151 // -----------------------------------------------------------------------------
152 // Public Instance Methods
153 // -----------------------------------------------------------------------------
154 
NativeProcessOpenBSD(::pid_t pid,int terminal_fd,NativeDelegate & delegate,const ArchSpec & arch,MainLoop & mainloop)155 NativeProcessOpenBSD::NativeProcessOpenBSD(::pid_t pid, int terminal_fd,
156                                          NativeDelegate &delegate,
157                                          const ArchSpec &arch,
158                                          MainLoop &mainloop)
159     : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) {
160   if (m_terminal_fd != -1) {
161     Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
162     assert(status.Success());
163   }
164 
165   Status status;
166   m_sigchld_handle = mainloop.RegisterSignal(
167       SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
168   assert(m_sigchld_handle && status.Success());
169 }
170 
171 // Handles all waitpid events from the inferior process.
MonitorCallback(lldb::pid_t pid,int signal)172 void NativeProcessOpenBSD::MonitorCallback(lldb::pid_t pid, int signal) {
173   switch (signal) {
174     case SIGTRAP:
175       return MonitorSIGTRAP(pid);
176     default:
177       return MonitorSignal(pid, signal);
178   }
179 }
180 
MonitorExited(lldb::pid_t pid,WaitStatus status)181 void NativeProcessOpenBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
182   Log *log = GetLog(POSIXLog::Process);
183 
184   LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
185 
186   /* Stop Tracking All Threads attached to Process */
187   m_threads.clear();
188 
189   SetExitStatus(status, true);
190 
191   // Notify delegate that our process has exited.
192   SetState(StateType::eStateExited, true);
193 }
194 
MonitorSIGTRAP(lldb::pid_t pid)195 void NativeProcessOpenBSD::MonitorSIGTRAP(lldb::pid_t pid) {
196   for (const auto &thread : m_threads) {
197     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedByBreakpoint();
198     FixupBreakpointPCAsNeeded(static_cast<NativeThreadOpenBSD &>(*thread));
199   }
200   SetState(StateType::eStateStopped, true);
201 }
202 
203 
MonitorSignal(lldb::pid_t pid,int signal)204 void NativeProcessOpenBSD::MonitorSignal(lldb::pid_t pid, int signal) {
205   for (const auto &thread : m_threads) {
206     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(signal);
207   }
208   SetState(StateType::eStateStopped, true);
209 }
210 
PtraceWrapper(int req,lldb::pid_t pid,void * addr,int data,int * result)211 Status NativeProcessOpenBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
212                                           int data, int *result) {
213   Log *log = GetLog(POSIXLog::Process);
214   Status error;
215   int ret;
216 
217   errno = 0;
218   ret = ptrace(req, static_cast<::pid_t>(pid), (caddr_t)addr, data);
219 
220   if (ret == -1)
221     error.SetErrorToErrno();
222 
223   if (result)
224     *result = ret;
225 
226   LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
227 
228   if (error.Fail())
229     LLDB_LOG(log, "ptrace() failed: {0}", error);
230 
231   return error;
232 }
233 
Resume(const ResumeActionList & resume_actions)234 Status NativeProcessOpenBSD::Resume(const ResumeActionList &resume_actions) {
235   Log *log = GetLog(POSIXLog::Process);
236   LLDB_LOG(log, "pid {0}", GetID());
237 
238   const auto &thread = m_threads[0];
239   const ResumeAction *const action =
240       resume_actions.GetActionForThread(thread->GetID(), true);
241 
242   if (action == nullptr) {
243     LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
244              thread->GetID());
245     return Status();
246   }
247 
248   Status error;
249   int signal = action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
250 
251   switch (action->state) {
252   case eStateRunning: {
253     // Run the thread, possibly feeding it the signal.
254     error = NativeProcessOpenBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
255                                                signal);
256     if (!error.Success())
257       return error;
258     for (const auto &thread : m_threads)
259       static_cast<NativeThreadOpenBSD &>(*thread).SetRunning();
260     SetState(eStateRunning, true);
261     break;
262   }
263   case eStateStepping:
264 #ifdef PT_STEP
265     // Run the thread, possibly feeding it the signal.
266     error = NativeProcessOpenBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
267                                                signal);
268     if (!error.Success())
269       return error;
270     for (const auto &thread : m_threads)
271       static_cast<NativeThreadOpenBSD &>(*thread).SetStepping();
272     SetState(eStateStepping, true);
273     break;
274 #else
275     return Status("NativeProcessOpenBSD stepping not supported on this platform");
276 #endif
277 
278   case eStateSuspended:
279   case eStateStopped:
280     llvm_unreachable("Unexpected state");
281 
282   default:
283     return Status("NativeProcessOpenBSD::%s (): unexpected state %s specified "
284                   "for pid %" PRIu64 ", tid %" PRIu64,
285                   __FUNCTION__, StateAsCString(action->state), GetID(),
286                   thread->GetID());
287   }
288 
289   return Status();
290 }
291 
Halt()292 Status NativeProcessOpenBSD::Halt() {
293   Status error;
294 
295   if (kill(GetID(), SIGSTOP) != 0)
296     error.SetErrorToErrno();
297 
298   return error;
299 }
300 
Detach()301 Status NativeProcessOpenBSD::Detach() {
302   Status error;
303 
304   // Stop monitoring the inferior.
305   m_sigchld_handle.reset();
306 
307   // Tell ptrace to detach from the process.
308   if (GetID() == LLDB_INVALID_PROCESS_ID)
309     return error;
310 
311   return PtraceWrapper(PT_DETACH, GetID());
312 }
313 
Signal(int signo)314 Status NativeProcessOpenBSD::Signal(int signo) {
315   Status error;
316 
317   if (kill(GetID(), signo))
318     error.SetErrorToErrno();
319 
320   return error;
321 }
322 
Kill()323 Status NativeProcessOpenBSD::Kill() {
324   Log *log = GetLog(POSIXLog::Process);
325   LLDB_LOG(log, "pid {0}", GetID());
326 
327   Status error;
328 
329   switch (m_state) {
330   case StateType::eStateInvalid:
331   case StateType::eStateExited:
332   case StateType::eStateCrashed:
333   case StateType::eStateDetached:
334   case StateType::eStateUnloaded:
335     // Nothing to do - the process is already dead.
336     LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
337              StateAsCString(m_state));
338     return error;
339 
340   case StateType::eStateConnected:
341   case StateType::eStateAttaching:
342   case StateType::eStateLaunching:
343   case StateType::eStateStopped:
344   case StateType::eStateRunning:
345   case StateType::eStateStepping:
346   case StateType::eStateSuspended:
347     // We can try to kill a process in these states.
348     break;
349   }
350 
351   if (kill(GetID(), SIGKILL) != 0) {
352     error.SetErrorToErrno();
353     return error;
354   }
355 
356   return error;
357 }
358 
GetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & range_info)359 Status NativeProcessOpenBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
360                                                 MemoryRegionInfo &range_info) {
361   return Status("Unimplemented");
362 }
363 
PopulateMemoryRegionCache()364 Status NativeProcessOpenBSD::PopulateMemoryRegionCache() {
365   return Status("Unimplemented");
366 }
367 
AllocateMemory(size_t size,uint32_t permissions)368 llvm::Expected<lldb::addr_t> NativeProcessOpenBSD::AllocateMemory(size_t size,
369                                                                  uint32_t permissions) {
370   return llvm::make_error<UnimplementedError>();
371 }
372 
DeallocateMemory(lldb::addr_t addr)373 llvm::Error NativeProcessOpenBSD::DeallocateMemory(lldb::addr_t addr) {
374   return llvm::make_error<UnimplementedError>();
375 }
376 
GetSharedLibraryInfoAddress()377 lldb::addr_t NativeProcessOpenBSD::GetSharedLibraryInfoAddress() {
378   // punt on this for now
379   return LLDB_INVALID_ADDRESS;
380 }
381 
UpdateThreads()382 size_t NativeProcessOpenBSD::UpdateThreads() { return m_threads.size(); }
383 
SetBreakpoint(lldb::addr_t addr,uint32_t size,bool hardware)384 Status NativeProcessOpenBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
385                                           bool hardware) {
386   if (hardware)
387     return Status("NativeProcessOpenBSD does not support hardware breakpoints");
388   else
389     return SetSoftwareBreakpoint(addr, size);
390 }
391 
GetLoadedModuleFileSpec(const char * module_path,FileSpec & file_spec)392 Status NativeProcessOpenBSD::GetLoadedModuleFileSpec(const char *module_path,
393                                                     FileSpec &file_spec) {
394   return Status("Unimplemented");
395 }
396 
GetFileLoadAddress(const llvm::StringRef & file_name,lldb::addr_t & load_addr)397 Status NativeProcessOpenBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
398                                                lldb::addr_t &load_addr) {
399   load_addr = LLDB_INVALID_ADDRESS;
400   return Status();
401 }
402 
SigchldHandler()403 void NativeProcessOpenBSD::SigchldHandler() {
404   Log *log = GetLog(POSIXLog::Process);
405   // Process all pending waitpid notifications.
406   int status;
407   ::pid_t wait_pid =
408       llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
409 
410   if (wait_pid == 0)
411     return; // We are done.
412 
413   if (wait_pid == -1) {
414     Status error(errno, eErrorTypePOSIX);
415     LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
416   }
417 
418   WaitStatus wait_status = WaitStatus::Decode(status);
419   bool exited = wait_status.type == WaitStatus::Exit ||
420                 (wait_status.type == WaitStatus::Signal &&
421                  wait_pid == static_cast<::pid_t>(GetID()));
422 
423   LLDB_LOG(log,
424            "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
425            GetID(), wait_pid, status, exited);
426 
427   if (exited)
428     MonitorExited(wait_pid, wait_status);
429   else {
430     assert(wait_status.type == WaitStatus::Stop);
431     MonitorCallback(wait_pid, wait_status.status);
432   }
433 }
434 
HasThreadNoLock(lldb::tid_t thread_id)435 bool NativeProcessOpenBSD::HasThreadNoLock(lldb::tid_t thread_id) {
436   for (const auto &thread : m_threads) {
437     assert(thread && "thread list should not contain NULL threads");
438     if (thread->GetID() == thread_id) {
439       // We have this thread.
440       return true;
441     }
442   }
443 
444   // We don't have this thread.
445   return false;
446 }
447 
AddThread(lldb::tid_t thread_id)448 NativeThreadOpenBSD &NativeProcessOpenBSD::AddThread(lldb::tid_t thread_id) {
449 
450   Log *log = GetLog(POSIXLog::Thread);
451   LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
452 
453   assert(!HasThreadNoLock(thread_id) &&
454          "attempted to add a thread by id that already exists");
455 
456   // If this is the first thread, save it as the current thread
457   if (m_threads.empty())
458     SetCurrentThreadID(thread_id);
459 
460   m_threads.push_back(std::make_unique<NativeThreadOpenBSD>(*this, thread_id));
461   return static_cast<NativeThreadOpenBSD &>(*m_threads.back());
462 }
463 
Attach()464 Status NativeProcessOpenBSD::Attach() {
465   // Attach to the requested process.
466   // An attach will cause the thread to stop with a SIGSTOP.
467   Status status = PtraceWrapper(PT_ATTACH, m_pid);
468   if (status.Fail())
469     return status;
470 
471   int wstatus;
472   // At this point we should have a thread stopped if waitpid succeeds.
473   if ((wstatus = waitpid(m_pid, NULL, 0)) < 0)
474     return Status(errno, eErrorTypePOSIX);
475 
476   /* Initialize threads */
477   status = ReinitializeThreads();
478   if (status.Fail())
479     return status;
480 
481   for (const auto &thread : m_threads)
482     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
483 
484   // Let our process instance know the thread has stopped.
485   SetState(StateType::eStateStopped);
486   return Status();
487 }
488 
ReadMemory(lldb::addr_t addr,void * buf,size_t size,size_t & bytes_read)489 Status NativeProcessOpenBSD::ReadMemory(lldb::addr_t addr, void *buf,
490                                        size_t size, size_t &bytes_read) {
491   unsigned char *dst = static_cast<unsigned char *>(buf);
492   struct ptrace_io_desc io;
493 
494   Log *log = GetLog(POSIXLog::Memory);
495   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
496 
497   bytes_read = 0;
498   io.piod_op = PIOD_READ_D;
499   io.piod_len = size;
500 
501   do {
502     io.piod_offs = (void *)(addr + bytes_read);
503     io.piod_addr = dst + bytes_read;
504 
505     Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
506     if (error.Fail())
507       return error;
508 
509     bytes_read = io.piod_len;
510     io.piod_len = size - bytes_read;
511   } while (bytes_read < size);
512 
513   return Status();
514 }
515 
WriteMemory(lldb::addr_t addr,const void * buf,size_t size,size_t & bytes_written)516 Status NativeProcessOpenBSD::WriteMemory(lldb::addr_t addr, const void *buf,
517                                         size_t size, size_t &bytes_written) {
518   const unsigned char *src = static_cast<const unsigned char *>(buf);
519   Status error;
520   struct ptrace_io_desc io;
521 
522   Log *log = GetLog(POSIXLog::Memory);
523   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
524 
525   bytes_written = 0;
526   io.piod_op = PIOD_WRITE_D;
527   io.piod_len = size;
528 
529   do {
530     io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
531     io.piod_offs = (void *)(addr + bytes_written);
532 
533     Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
534     if (error.Fail())
535       return error;
536 
537     bytes_written = io.piod_len;
538     io.piod_len = size - bytes_written;
539   } while (bytes_written < size);
540 
541   return error;
542 }
543 
544 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
GetAuxvData() const545 NativeProcessOpenBSD::GetAuxvData() const {
546   size_t auxv_size = 100 * sizeof(AuxInfo);
547 
548   ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
549       llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
550 
551   struct ptrace_io_desc io;
552   io.piod_op = PIOD_READ_AUXV;
553   io.piod_offs = 0;
554   io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
555   io.piod_len = auxv_size;
556 
557   Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
558 
559   if (error.Fail())
560     return std::error_code(error.GetError(), std::generic_category());
561 
562   if (io.piod_len < 1)
563     return std::error_code(ECANCELED, std::generic_category());
564 
565   return std::move(buf);
566 }
567 
ReinitializeThreads()568 Status NativeProcessOpenBSD::ReinitializeThreads() {
569   // Clear old threads
570   m_threads.clear();
571 
572   // Initialize new thread
573   struct ptrace_thread_state info = {};
574   Status error = PtraceWrapper(PT_GET_THREAD_FIRST, GetID(), &info, sizeof(info));
575   if (error.Fail()) {
576     return error;
577   }
578   // Reinitialize from scratch threads and register them in process
579   while (info.pts_tid > 0) {
580     AddThread(info.pts_tid);
581     error = PtraceWrapper(PT_GET_THREAD_NEXT, GetID(), &info, sizeof(info));
582     if (error.Fail() && errno != 0) {
583       return error;
584     }
585   }
586 
587   return error;
588 }
589