brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · cd5e345 Raw
255 lines · cpp
1//===-- NativeProcessAIX.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "NativeProcessAIX.h"10#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"11#include "lldb/Host/Host.h"12#include "lldb/Host/HostInfo.h"13#include "lldb/Host/HostProcess.h"14#include "lldb/Host/ProcessLaunchInfo.h"15#include "lldb/Host/posix/ProcessLauncherPosixFork.h"16#include "lldb/Symbol/ObjectFile.h"17#include "lldb/Utility/Log.h"18#include "lldb/Utility/State.h"19#include "lldb/Utility/Status.h"20#include "llvm/Support/Errno.h"21#include "llvm/Support/Error.h"22#include <cerrno>23#include <cstdint>24#include <cstring>25#include <sstream>26#include <string>27#include <sys/ptrace.h>28#include <unistd.h>29 30using namespace lldb;31using namespace lldb_private;32using namespace lldb_private::process_aix;33using namespace llvm;34 35static constexpr unsigned k_ptrace_word_size = sizeof(void *);36static_assert(sizeof(long) >= k_ptrace_word_size,37              "Size of long must be larger than ptrace word size");38 39// Simple helper function to ensure flags are enabled on the given file40// descriptor.41static llvm::Error SetFDFlags(int fd, int flags) {42  int status = fcntl(fd, F_GETFL);43  if (status == -1)44    return errorCodeToError(errnoAsErrorCode());45  if (fcntl(fd, F_SETFL, status | flags) == -1)46    return errorCodeToError(errnoAsErrorCode());47  return Error::success();48}49 50NativeProcessAIX::Manager::Manager(MainLoop &mainloop)51    : NativeProcessProtocol::Manager(mainloop) {52  Status status;53  m_sigchld_handle = mainloop.RegisterSignal(54      SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);55  assert(m_sigchld_handle && status.Success());56}57 58// Public Static Methods59 60llvm::Expected<std::unique_ptr<NativeProcessProtocol>>61NativeProcessAIX::Manager::Launch(ProcessLaunchInfo &launch_info,62                                  NativeDelegate &native_delegate) {63  Log *log = GetLog(POSIXLog::Process);64 65  Status status;66  ::pid_t pid = ProcessLauncherPosixFork()67                    .LaunchProcess(launch_info, status)68                    .GetProcessId();69  LLDB_LOG(log, "pid = {0:x}", pid);70  if (status.Fail()) {71    LLDB_LOG(log, "failed to launch process: {0}", status);72    return status.ToError();73  }74 75  // Wait for the child process to trap on its call to execve.76  int wstatus = 0;77  ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);78  assert(wpid == pid);79  UNUSED_IF_ASSERT_DISABLED(wpid);80  if (!WIFSTOPPED(wstatus)) {81    LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",82             WaitStatus::Decode(wstatus));83    return llvm::make_error<StringError>("Could not sync with inferior process",84                                         llvm::inconvertibleErrorCode());85  }86  LLDB_LOG(log, "inferior started, now in stopped state");87 88  return std::unique_ptr<NativeProcessAIX>(new NativeProcessAIX(89      pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,90      HostInfo::GetArchitecture(HostInfo::eArchKind64), *this, {pid}));91}92 93llvm::Expected<std::unique_ptr<NativeProcessProtocol>>94NativeProcessAIX::Manager::Attach(95    lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) {96  Log *log = GetLog(POSIXLog::Process);97  LLDB_LOG(log, "pid = {0:x}", pid);98 99  auto tids_or = NativeProcessAIX::Attach(pid);100  if (!tids_or)101    return tids_or.takeError();102 103  return std::unique_ptr<NativeProcessAIX>(new NativeProcessAIX(104      pid, -1, native_delegate,105      HostInfo::GetArchitecture(HostInfo::eArchKind64), *this, *tids_or));106}107 108lldb::addr_t NativeProcessAIX::GetSharedLibraryInfoAddress() {109  return LLDB_INVALID_ADDRESS;110}111 112static std::optional<std::pair<lldb::pid_t, WaitStatus>> WaitPid() {113  Log *log = GetLog(POSIXLog::Process);114 115  int status;116  ::pid_t wait_pid =117      llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status, WNOHANG);118 119  if (wait_pid == 0)120    return std::nullopt;121 122  if (wait_pid == -1) {123    Status error(errno, eErrorTypePOSIX);124    LLDB_LOG(log, "waitpid(-1, &status, _) failed: {0}", error);125    return std::nullopt;126  }127 128  WaitStatus wait_status = WaitStatus::Decode(status);129 130  LLDB_LOG(log, "waitpid(-1, &status, _) = {0}, status = {1}", wait_pid,131           wait_status);132  return std::make_pair(wait_pid, wait_status);133}134 135void NativeProcessAIX::Manager::SigchldHandler() {136  while (true) {137    auto wait_result = WaitPid();138    if (!wait_result)139      return;140  }141}142 143void NativeProcessAIX::Manager::CollectThread(::pid_t tid) {}144 145// Public Instance Methods146 147NativeProcessAIX::NativeProcessAIX(::pid_t pid, int terminal_fd,148                                   NativeDelegate &delegate,149                                   const ArchSpec &arch, Manager &manager,150                                   llvm::ArrayRef<::pid_t> tids)151    : NativeProcessProtocol(pid, terminal_fd, delegate), m_manager(manager),152      m_arch(arch) {153  manager.AddProcess(*this);154  if (m_terminal_fd != -1)155    cantFail(SetFDFlags(m_terminal_fd, O_NONBLOCK));156 157  // Let our process instance know the thread has stopped.158  SetCurrentThreadID(tids[0]);159  SetState(StateType::eStateStopped, false);160}161 162llvm::Expected<std::vector<::pid_t>> NativeProcessAIX::Attach(::pid_t pid) {163  Log *log = GetLog(POSIXLog::Process);164  Status status;165  if (llvm::Error err = PtraceWrapper(PT_ATTACH, pid).takeError())166    return err;167 168  int wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, nullptr, WNOHANG);169  if (wpid <= 0)170    return llvm::errorCodeToError(errnoAsErrorCode());171  LLDB_LOG(log, "adding pid = {0}", pid);172 173  return std::vector<::pid_t>{pid};174}175 176bool NativeProcessAIX::SupportHardwareSingleStepping() const { return false; }177 178Status NativeProcessAIX::Resume(const ResumeActionList &resume_actions) {179  return Status("unsupported");180}181 182Status NativeProcessAIX::Halt() { return Status("unsupported"); }183 184Status NativeProcessAIX::Detach() { return Status("unsupported"); }185 186Status NativeProcessAIX::Signal(int signo) { return Status("unsupported"); }187 188Status NativeProcessAIX::Interrupt() { return Status("unsupported"); }189 190Status NativeProcessAIX::Kill() { return Status("unsupported"); }191 192Status NativeProcessAIX::ReadMemory(lldb::addr_t addr, void *buf, size_t size,193                                    size_t &bytes_read) {194  return Status("unsupported");195}196 197Status NativeProcessAIX::WriteMemory(lldb::addr_t addr, const void *buf,198                                     size_t size, size_t &bytes_written) {199  return Status("unsupported");200}201 202size_t NativeProcessAIX::UpdateThreads() {203  // The NativeProcessAIX monitoring threads are always up to date with204  // respect to thread state and they keep the thread list populated properly.205  // All this method needs to do is return the thread count.206  return m_threads.size();207}208 209Status NativeProcessAIX::GetLoadedModuleFileSpec(const char *module_path,210                                                 FileSpec &file_spec) {211  return Status("unsupported");212}213 214Status NativeProcessAIX::SetBreakpoint(lldb::addr_t addr, uint32_t size,215                                       bool hardware) {216  if (hardware)217    return SetHardwareBreakpoint(addr, size);218  return SetSoftwareBreakpoint(addr, size);219}220 221Status NativeProcessAIX::RemoveBreakpoint(lldb::addr_t addr, bool hardware) {222  if (hardware)223    return RemoveHardwareBreakpoint(addr);224  return NativeProcessProtocol::RemoveBreakpoint(addr);225}226 227llvm::Error NativeProcessAIX::Detach(lldb::tid_t tid) {228  return PtraceWrapper(PT_DETACH, tid).takeError();229}230 231llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,232                                                    void *addr, void *data,233                                                    size_t data_size) {234  int ret;235 236  Log *log = GetLog(POSIXLog::Ptrace);237  switch (req) {238  case PT_ATTACH:239  case PT_DETACH:240    ret = ptrace64(req, pid, 0, 0, nullptr);241    break;242  default:243    llvm_unreachable("PT_ request not supported yet.");244  }245 246  LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,247           data_size, ret);248 249  if (ret == -1) {250    LLDB_LOG(log, "ptrace() failed");251    return llvm::errorCodeToError(errnoAsErrorCode());252  }253  return ret;254}255