Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
213845 views
//===-- NativeProcessAIX.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "NativeProcessAIX.h"9#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"10#include "lldb/Host/Host.h"11#include "lldb/Host/HostInfo.h"12#include "lldb/Host/HostProcess.h"13#include "lldb/Host/ProcessLaunchInfo.h"14#include "lldb/Host/posix/ProcessLauncherPosixFork.h"15#include "lldb/Symbol/ObjectFile.h"16#include "lldb/Utility/Log.h"17#include "lldb/Utility/State.h"18#include "lldb/Utility/Status.h"19#include "llvm/Support/Errno.h"20#include "llvm/Support/Error.h"21#include <cerrno>22#include <cstdint>23#include <cstring>24#include <sstream>25#include <string>26#include <sys/ptrace.h>27#include <unistd.h>2829using namespace lldb;30using namespace lldb_private;31using namespace lldb_private::process_aix;32using namespace llvm;3334static constexpr unsigned k_ptrace_word_size = sizeof(void *);35static_assert(sizeof(long) >= k_ptrace_word_size,36"Size of long must be larger than ptrace word size");3738// Simple helper function to ensure flags are enabled on the given file39// descriptor.40static llvm::Error SetFDFlags(int fd, int flags) {41int status = fcntl(fd, F_GETFL);42if (status == -1)43return errorCodeToError(errnoAsErrorCode());44if (fcntl(fd, F_SETFL, status | flags) == -1)45return errorCodeToError(errnoAsErrorCode());46return Error::success();47}4849NativeProcessAIX::Manager::Manager(MainLoop &mainloop)50: NativeProcessProtocol::Manager(mainloop) {51Status status;52m_sigchld_handle = mainloop.RegisterSignal(53SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);54assert(m_sigchld_handle && status.Success());55}5657// Public Static Methods5859llvm::Expected<std::unique_ptr<NativeProcessProtocol>>60NativeProcessAIX::Manager::Launch(ProcessLaunchInfo &launch_info,61NativeDelegate &native_delegate) {62Log *log = GetLog(POSIXLog::Process);6364Status status;65::pid_t pid = ProcessLauncherPosixFork()66.LaunchProcess(launch_info, status)67.GetProcessId();68LLDB_LOG(log, "pid = {0:x}", pid);69if (status.Fail()) {70LLDB_LOG(log, "failed to launch process: {0}", status);71return status.ToError();72}7374// Wait for the child process to trap on its call to execve.75int wstatus = 0;76::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);77assert(wpid == pid);78UNUSED_IF_ASSERT_DISABLED(wpid);79if (!WIFSTOPPED(wstatus)) {80LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",81WaitStatus::Decode(wstatus));82return llvm::make_error<StringError>("Could not sync with inferior process",83llvm::inconvertibleErrorCode());84}85LLDB_LOG(log, "inferior started, now in stopped state");8687return std::unique_ptr<NativeProcessAIX>(new NativeProcessAIX(88pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,89HostInfo::GetArchitecture(HostInfo::eArchKind64), *this, {pid}));90}9192llvm::Expected<std::unique_ptr<NativeProcessProtocol>>93NativeProcessAIX::Manager::Attach(94lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) {95Log *log = GetLog(POSIXLog::Process);96LLDB_LOG(log, "pid = {0:x}", pid);9798auto tids_or = NativeProcessAIX::Attach(pid);99if (!tids_or)100return tids_or.takeError();101102return std::unique_ptr<NativeProcessAIX>(new NativeProcessAIX(103pid, -1, native_delegate,104HostInfo::GetArchitecture(HostInfo::eArchKind64), *this, *tids_or));105}106107lldb::addr_t NativeProcessAIX::GetSharedLibraryInfoAddress() {108return LLDB_INVALID_ADDRESS;109}110111static std::optional<std::pair<lldb::pid_t, WaitStatus>> WaitPid() {112Log *log = GetLog(POSIXLog::Process);113114int status;115::pid_t wait_pid =116llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status, WNOHANG);117118if (wait_pid == 0)119return std::nullopt;120121if (wait_pid == -1) {122Status error(errno, eErrorTypePOSIX);123LLDB_LOG(log, "waitpid(-1, &status, _) failed: {0}", error);124return std::nullopt;125}126127WaitStatus wait_status = WaitStatus::Decode(status);128129LLDB_LOG(log, "waitpid(-1, &status, _) = {0}, status = {1}", wait_pid,130wait_status);131return std::make_pair(wait_pid, wait_status);132}133134void NativeProcessAIX::Manager::SigchldHandler() {135while (true) {136auto wait_result = WaitPid();137if (!wait_result)138return;139}140}141142void NativeProcessAIX::Manager::CollectThread(::pid_t tid) {}143144// Public Instance Methods145146NativeProcessAIX::NativeProcessAIX(::pid_t pid, int terminal_fd,147NativeDelegate &delegate,148const ArchSpec &arch, Manager &manager,149llvm::ArrayRef<::pid_t> tids)150: NativeProcessProtocol(pid, terminal_fd, delegate), m_manager(manager),151m_arch(arch) {152manager.AddProcess(*this);153if (m_terminal_fd != -1)154cantFail(SetFDFlags(m_terminal_fd, O_NONBLOCK));155156// Let our process instance know the thread has stopped.157SetCurrentThreadID(tids[0]);158SetState(StateType::eStateStopped, false);159}160161llvm::Expected<std::vector<::pid_t>> NativeProcessAIX::Attach(::pid_t pid) {162Log *log = GetLog(POSIXLog::Process);163Status status;164if (llvm::Error err = PtraceWrapper(PT_ATTACH, pid).takeError())165return err;166167int wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, nullptr, WNOHANG);168if (wpid <= 0)169return llvm::errorCodeToError(errnoAsErrorCode());170LLDB_LOG(log, "adding pid = {0}", pid);171172return std::vector<::pid_t>{pid};173}174175bool NativeProcessAIX::SupportHardwareSingleStepping() const { return false; }176177Status NativeProcessAIX::Resume(const ResumeActionList &resume_actions) {178return Status("unsupported");179}180181Status NativeProcessAIX::Halt() { return Status("unsupported"); }182183Status NativeProcessAIX::Detach() { return Status("unsupported"); }184185Status NativeProcessAIX::Signal(int signo) { return Status("unsupported"); }186187Status NativeProcessAIX::Interrupt() { return Status("unsupported"); }188189Status NativeProcessAIX::Kill() { return Status("unsupported"); }190191Status NativeProcessAIX::ReadMemory(lldb::addr_t addr, void *buf, size_t size,192size_t &bytes_read) {193return Status("unsupported");194}195196Status NativeProcessAIX::WriteMemory(lldb::addr_t addr, const void *buf,197size_t size, size_t &bytes_written) {198return Status("unsupported");199}200201size_t NativeProcessAIX::UpdateThreads() {202// The NativeProcessAIX monitoring threads are always up to date with203// respect to thread state and they keep the thread list populated properly.204// All this method needs to do is return the thread count.205return m_threads.size();206}207208Status NativeProcessAIX::GetLoadedModuleFileSpec(const char *module_path,209FileSpec &file_spec) {210return Status("unsupported");211}212213Status NativeProcessAIX::SetBreakpoint(lldb::addr_t addr, uint32_t size,214bool hardware) {215if (hardware)216return SetHardwareBreakpoint(addr, size);217return SetSoftwareBreakpoint(addr, size);218}219220Status NativeProcessAIX::RemoveBreakpoint(lldb::addr_t addr, bool hardware) {221if (hardware)222return RemoveHardwareBreakpoint(addr);223return NativeProcessProtocol::RemoveBreakpoint(addr);224}225226llvm::Error NativeProcessAIX::Detach(lldb::tid_t tid) {227return PtraceWrapper(PT_DETACH, tid).takeError();228}229230llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,231void *addr, void *data,232size_t data_size) {233int ret;234235Log *log = GetLog(POSIXLog::Ptrace);236switch (req) {237case PT_ATTACH:238case PT_DETACH:239ret = ptrace64(req, pid, 0, 0, nullptr);240break;241default:242llvm_unreachable("PT_ request not supported yet.");243}244245LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,246data_size, ret);247248if (ret == -1) {249LLDB_LOG(log, "ptrace() failed");250return llvm::errorCodeToError(errnoAsErrorCode());251}252return ret;253}254255256