xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.cpp (revision 24bb5fcea3ed904bc467217bdaadb5dfc618d5bf)
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.
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>>
66 NativeProcessOpenBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
67                                      NativeDelegate &native_delegate,
68                                      MainLoop &mainloop) const {
69   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_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>>
120 NativeProcessOpenBSD::Factory::Attach(
121     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
122     MainLoop &mainloop) const {
123 
124   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_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 // -----------------------------------------------------------------------------
145 // Public Instance Methods
146 // -----------------------------------------------------------------------------
147 
148 NativeProcessOpenBSD::NativeProcessOpenBSD(::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 }
163 
164 // Handles all waitpid events from the inferior process.
165 void NativeProcessOpenBSD::MonitorCallback(lldb::pid_t pid, int signal) {
166   switch (signal) {
167     case SIGTRAP:
168       return MonitorSIGTRAP(pid);
169     default:
170       return MonitorSignal(pid, signal);
171   }
172 }
173 
174 void NativeProcessOpenBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
175   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
176 
177   LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
178 
179   /* Stop Tracking All Threads attached to Process */
180   m_threads.clear();
181 
182   SetExitStatus(status, true);
183 
184   // Notify delegate that our process has exited.
185   SetState(StateType::eStateExited, true);
186 }
187 
188 void NativeProcessOpenBSD::MonitorSIGTRAP(lldb::pid_t pid) {
189   for (const auto &thread : m_threads) {
190     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedByBreakpoint();
191     FixupBreakpointPCAsNeeded(static_cast<NativeThreadOpenBSD &>(*thread));
192   }
193   SetState(StateType::eStateStopped, true);
194 }
195 
196 
197 void NativeProcessOpenBSD::MonitorSignal(lldb::pid_t pid, int signal) {
198   for (const auto &thread : m_threads) {
199     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(signal);
200   }
201   SetState(StateType::eStateStopped, true);
202 }
203 
204 Status NativeProcessOpenBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
205                                           int data, int *result) {
206   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
207   Status error;
208   int ret;
209 
210   errno = 0;
211   ret = ptrace(req, static_cast<::pid_t>(pid), (caddr_t)addr, data);
212 
213   if (ret == -1)
214     error.SetErrorToErrno();
215 
216   if (result)
217     *result = ret;
218 
219   LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
220 
221   if (error.Fail())
222     LLDB_LOG(log, "ptrace() failed: {0}", error);
223 
224   return error;
225 }
226 
227 Status NativeProcessOpenBSD::Resume(const ResumeActionList &resume_actions) {
228   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
229   LLDB_LOG(log, "pid {0}", GetID());
230 
231   const auto &thread = m_threads[0];
232   const ResumeAction *const action =
233       resume_actions.GetActionForThread(thread->GetID(), true);
234 
235   if (action == nullptr) {
236     LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
237              thread->GetID());
238     return Status();
239   }
240 
241   Status error;
242   int signal = action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
243 
244   switch (action->state) {
245   case eStateRunning: {
246     // Run the thread, possibly feeding it the signal.
247     error = NativeProcessOpenBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
248                                                signal);
249     if (!error.Success())
250       return error;
251     for (const auto &thread : m_threads)
252       static_cast<NativeThreadOpenBSD &>(*thread).SetRunning();
253     SetState(eStateRunning, true);
254     break;
255   }
256   case eStateStepping:
257 #ifdef PT_STEP
258     // Run the thread, possibly feeding it the signal.
259     error = NativeProcessOpenBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
260                                                signal);
261     if (!error.Success())
262       return error;
263     for (const auto &thread : m_threads)
264       static_cast<NativeThreadOpenBSD &>(*thread).SetStepping();
265     SetState(eStateStepping, true);
266     break;
267 #else
268     return Status("NativeProcessOpenBSD stepping not supported on this platform");
269 #endif
270 
271   case eStateSuspended:
272   case eStateStopped:
273     llvm_unreachable("Unexpected state");
274 
275   default:
276     return Status("NativeProcessOpenBSD::%s (): unexpected state %s specified "
277                   "for pid %" PRIu64 ", tid %" PRIu64,
278                   __FUNCTION__, StateAsCString(action->state), GetID(),
279                   thread->GetID());
280   }
281 
282   return Status();
283 }
284 
285 Status NativeProcessOpenBSD::Halt() {
286   Status error;
287 
288   if (kill(GetID(), SIGSTOP) != 0)
289     error.SetErrorToErrno();
290 
291   return error;
292 }
293 
294 Status NativeProcessOpenBSD::Detach() {
295   Status error;
296 
297   // Stop monitoring the inferior.
298   m_sigchld_handle.reset();
299 
300   // Tell ptrace to detach from the process.
301   if (GetID() == LLDB_INVALID_PROCESS_ID)
302     return error;
303 
304   return PtraceWrapper(PT_DETACH, GetID());
305 }
306 
307 Status NativeProcessOpenBSD::Signal(int signo) {
308   Status error;
309 
310   if (kill(GetID(), signo))
311     error.SetErrorToErrno();
312 
313   return error;
314 }
315 
316 Status NativeProcessOpenBSD::Kill() {
317   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
318   LLDB_LOG(log, "pid {0}", GetID());
319 
320   Status error;
321 
322   switch (m_state) {
323   case StateType::eStateInvalid:
324   case StateType::eStateExited:
325   case StateType::eStateCrashed:
326   case StateType::eStateDetached:
327   case StateType::eStateUnloaded:
328     // Nothing to do - the process is already dead.
329     LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
330              StateAsCString(m_state));
331     return error;
332 
333   case StateType::eStateConnected:
334   case StateType::eStateAttaching:
335   case StateType::eStateLaunching:
336   case StateType::eStateStopped:
337   case StateType::eStateRunning:
338   case StateType::eStateStepping:
339   case StateType::eStateSuspended:
340     // We can try to kill a process in these states.
341     break;
342   }
343 
344   if (kill(GetID(), SIGKILL) != 0) {
345     error.SetErrorToErrno();
346     return error;
347   }
348 
349   return error;
350 }
351 
352 Status NativeProcessOpenBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
353                                                 MemoryRegionInfo &range_info) {
354   return Status("Unimplemented");
355 }
356 
357 Status NativeProcessOpenBSD::PopulateMemoryRegionCache() {
358   return Status("Unimplemented");
359 }
360 
361 Status NativeProcessOpenBSD::AllocateMemory(size_t size, uint32_t permissions,
362                                            lldb::addr_t &addr) {
363   return Status("Unimplemented");
364 }
365 
366 Status NativeProcessOpenBSD::DeallocateMemory(lldb::addr_t addr) {
367   return Status("Unimplemented");
368 }
369 
370 lldb::addr_t NativeProcessOpenBSD::GetSharedLibraryInfoAddress() {
371   // punt on this for now
372   return LLDB_INVALID_ADDRESS;
373 }
374 
375 size_t NativeProcessOpenBSD::UpdateThreads() { return m_threads.size(); }
376 
377 Status NativeProcessOpenBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
378                                           bool hardware) {
379   if (hardware)
380     return Status("NativeProcessOpenBSD does not support hardware breakpoints");
381   else
382     return SetSoftwareBreakpoint(addr, size);
383 }
384 
385 Status NativeProcessOpenBSD::GetLoadedModuleFileSpec(const char *module_path,
386                                                     FileSpec &file_spec) {
387   return Status("Unimplemented");
388 }
389 
390 Status NativeProcessOpenBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
391                                                lldb::addr_t &load_addr) {
392   load_addr = LLDB_INVALID_ADDRESS;
393   return Status();
394 }
395 
396 void NativeProcessOpenBSD::SigchldHandler() {
397   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
398   // Process all pending waitpid notifications.
399   int status;
400   ::pid_t wait_pid =
401       llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
402 
403   if (wait_pid == 0)
404     return; // We are done.
405 
406   if (wait_pid == -1) {
407     Status error(errno, eErrorTypePOSIX);
408     LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
409   }
410 
411   WaitStatus wait_status = WaitStatus::Decode(status);
412   bool exited = wait_status.type == WaitStatus::Exit ||
413                 (wait_status.type == WaitStatus::Signal &&
414                  wait_pid == static_cast<::pid_t>(GetID()));
415 
416   LLDB_LOG(log,
417            "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
418            GetID(), wait_pid, status, exited);
419 
420   if (exited)
421     MonitorExited(wait_pid, wait_status);
422   else {
423     assert(wait_status.type == WaitStatus::Stop);
424     MonitorCallback(wait_pid, wait_status.status);
425   }
426 }
427 
428 bool NativeProcessOpenBSD::HasThreadNoLock(lldb::tid_t thread_id) {
429   for (const auto &thread : m_threads) {
430     assert(thread && "thread list should not contain NULL threads");
431     if (thread->GetID() == thread_id) {
432       // We have this thread.
433       return true;
434     }
435   }
436 
437   // We don't have this thread.
438   return false;
439 }
440 
441 NativeThreadOpenBSD &NativeProcessOpenBSD::AddThread(lldb::tid_t thread_id) {
442 
443   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
444   LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
445 
446   assert(!HasThreadNoLock(thread_id) &&
447          "attempted to add a thread by id that already exists");
448 
449   // If this is the first thread, save it as the current thread
450   if (m_threads.empty())
451     SetCurrentThreadID(thread_id);
452 
453   m_threads.push_back(std::make_unique<NativeThreadOpenBSD>(*this, thread_id));
454   return static_cast<NativeThreadOpenBSD &>(*m_threads.back());
455 }
456 
457 Status NativeProcessOpenBSD::Attach() {
458   // Attach to the requested process.
459   // An attach will cause the thread to stop with a SIGSTOP.
460   Status status = PtraceWrapper(PT_ATTACH, m_pid);
461   if (status.Fail())
462     return status;
463 
464   int wstatus;
465   // At this point we should have a thread stopped if waitpid succeeds.
466   if ((wstatus = waitpid(m_pid, NULL, 0)) < 0)
467     return Status(errno, eErrorTypePOSIX);
468 
469   /* Initialize threads */
470   status = ReinitializeThreads();
471   if (status.Fail())
472     return status;
473 
474   for (const auto &thread : m_threads)
475     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
476 
477   // Let our process instance know the thread has stopped.
478   SetState(StateType::eStateStopped);
479   return Status();
480 }
481 
482 Status NativeProcessOpenBSD::ReadMemory(lldb::addr_t addr, void *buf,
483                                        size_t size, size_t &bytes_read) {
484   unsigned char *dst = static_cast<unsigned char *>(buf);
485   struct ptrace_io_desc io;
486 
487   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
488   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
489 
490   bytes_read = 0;
491   io.piod_op = PIOD_READ_D;
492   io.piod_len = size;
493 
494   do {
495     io.piod_offs = (void *)(addr + bytes_read);
496     io.piod_addr = dst + bytes_read;
497 
498     Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
499     if (error.Fail())
500       return error;
501 
502     bytes_read = io.piod_len;
503     io.piod_len = size - bytes_read;
504   } while (bytes_read < size);
505 
506   return Status();
507 }
508 
509 Status NativeProcessOpenBSD::WriteMemory(lldb::addr_t addr, const void *buf,
510                                         size_t size, size_t &bytes_written) {
511   const unsigned char *src = static_cast<const unsigned char *>(buf);
512   Status error;
513   struct ptrace_io_desc io;
514 
515   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
516   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
517 
518   bytes_written = 0;
519   io.piod_op = PIOD_WRITE_D;
520   io.piod_len = size;
521 
522   do {
523     io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
524     io.piod_offs = (void *)(addr + bytes_written);
525 
526     Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
527     if (error.Fail())
528       return error;
529 
530     bytes_written = io.piod_len;
531     io.piod_len = size - bytes_written;
532   } while (bytes_written < size);
533 
534   return error;
535 }
536 
537 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
538 NativeProcessOpenBSD::GetAuxvData() const {
539   size_t auxv_size = 100 * sizeof(AuxInfo);
540 
541   ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
542       llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
543 
544   struct ptrace_io_desc io;
545   io.piod_op = PIOD_READ_AUXV;
546   io.piod_offs = 0;
547   io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
548   io.piod_len = auxv_size;
549 
550   Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
551 
552   if (error.Fail())
553     return std::error_code(error.GetError(), std::generic_category());
554 
555   if (io.piod_len < 1)
556     return std::error_code(ECANCELED, std::generic_category());
557 
558   return std::move(buf);
559 }
560 
561 Status NativeProcessOpenBSD::ReinitializeThreads() {
562   // Clear old threads
563   m_threads.clear();
564 
565   // Initialize new thread
566   struct ptrace_thread_state info = {};
567   Status error = PtraceWrapper(PT_GET_THREAD_FIRST, GetID(), &info, sizeof(info));
568   if (error.Fail()) {
569     return error;
570   }
571   // Reinitialize from scratch threads and register them in process
572   while (info.pts_tid > 0) {
573     AddThread(info.pts_tid);
574     error = PtraceWrapper(PT_GET_THREAD_NEXT, GetID(), &info, sizeof(info));
575     if (error.Fail() && errno != 0) {
576       return error;
577     }
578   }
579 
580   return error;
581 }
582