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