brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · b5572b9 Raw
185 lines · cpp
1//===-- source/Host/aix/Host.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 "lldb/Host/Host.h"10#include "lldb/Host/posix/Support.h"11#include "lldb/Utility/LLDBLog.h"12#include "lldb/Utility/Log.h"13#include "lldb/Utility/ProcessInfo.h"14#include "lldb/Utility/Status.h"15#include "llvm/BinaryFormat/XCOFF.h"16#include <dirent.h>17#include <sys/proc.h>18#include <sys/procfs.h>19 20using namespace lldb;21using namespace lldb_private;22 23namespace {24enum class ProcessState {25  Unknown,26  Dead,27  DiskSleep,28  Idle,29  Paging,30  Parked,31  Running,32  Sleeping,33  TracedOrStopped,34  Zombie,35};36}37 38static ProcessInstanceInfo::timespec convert(pr_timestruc64_t t) {39  ProcessInstanceInfo::timespec ts;40  ts.tv_sec = t.tv_sec;41  ts.tv_usec = t.tv_nsec / 1000; // nanos to micros42  return ts;43}44 45static bool GetStatusInfo(::pid_t pid, ProcessInstanceInfo &processInfo,46                          ProcessState &State) {47  struct pstatus pstatusData;48  auto BufferOrError = getProcFile(pid, "status");49  if (!BufferOrError)50    return false;51 52  std::unique_ptr<llvm::MemoryBuffer> StatusBuffer = std::move(*BufferOrError);53  // Ensure there's enough data for psinfoData54  if (StatusBuffer->getBufferSize() < sizeof(pstatusData))55    return false;56 57  std::memcpy(&pstatusData, StatusBuffer->getBufferStart(),58              sizeof(pstatusData));59  switch (pstatusData.pr_stat) {60  case SIDL:61    State = ProcessState::Idle;62    break;63  case SACTIVE:64    State = ProcessState::Running;65    break;66  case SSTOP:67    State = ProcessState::TracedOrStopped;68    break;69  case SZOMB:70    State = ProcessState::Zombie;71    break;72  default:73    State = ProcessState::Unknown;74    break;75  }76  processInfo.SetIsZombie(State == ProcessState::Zombie);77  processInfo.SetUserTime(convert(pstatusData.pr_utime));78  processInfo.SetSystemTime(convert(pstatusData.pr_stime));79  processInfo.SetCumulativeUserTime(convert(pstatusData.pr_cutime));80  processInfo.SetCumulativeSystemTime(convert(pstatusData.pr_cstime));81  return true;82}83 84static bool GetExePathAndIds(::pid_t pid, ProcessInstanceInfo &process_info) {85  struct psinfo psinfoData;86  auto BufferOrError = getProcFile(pid, "psinfo");87  if (!BufferOrError)88    return false;89 90  std::unique_ptr<llvm::MemoryBuffer> PsinfoBuffer = std::move(*BufferOrError);91  // Ensure there's enough data for psinfoData92  if (PsinfoBuffer->getBufferSize() < sizeof(psinfoData))93    return false;94 95  std::memcpy(&psinfoData, PsinfoBuffer->getBufferStart(), sizeof(psinfoData));96  llvm::StringRef PathRef(97      psinfoData.pr_psargs,98      strnlen(psinfoData.pr_psargs, sizeof(psinfoData.pr_psargs)));99  if (PathRef.empty())100    return false;101 102  process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);103  ArchSpec arch_spec = ArchSpec();104  arch_spec.SetArchitecture(eArchTypeXCOFF, llvm::XCOFF::TCPU_PPC64,105                            LLDB_INVALID_CPUTYPE, llvm::Triple::AIX);106  process_info.SetArchitecture(arch_spec);107  process_info.SetParentProcessID(psinfoData.pr_ppid);108  process_info.SetGroupID(psinfoData.pr_gid);109  process_info.SetEffectiveGroupID(psinfoData.pr_egid);110  process_info.SetUserID(psinfoData.pr_uid);111  process_info.SetEffectiveUserID(psinfoData.pr_euid);112  process_info.SetProcessGroupID(psinfoData.pr_pgid);113  process_info.SetProcessSessionID(psinfoData.pr_sid);114  return true;115}116 117static bool GetProcessAndStatInfo(::pid_t pid,118                                  ProcessInstanceInfo &process_info,119                                  ProcessState &State) {120  process_info.Clear();121  process_info.SetProcessID(pid);122 123  if (pid == LLDB_INVALID_PROCESS_ID)124    return false;125  // Get Executable path/Arch and Get User and Group IDs.126  if (!GetExePathAndIds(pid, process_info))127    return false;128  // Get process status and timing info.129  if (!GetStatusInfo(pid, process_info, State))130    return false;131 132  return true;133}134 135uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,136                                 ProcessInstanceInfoList &process_infos) {137  static const char procdir[] = "/proc/";138 139  DIR *dirproc = opendir(procdir);140  if (dirproc) {141    struct dirent *direntry = nullptr;142    const uid_t our_uid = getuid();143    const lldb::pid_t our_pid = getpid();144    bool all_users = match_info.GetMatchAllUsers();145 146    while ((direntry = readdir(dirproc)) != nullptr) {147      lldb::pid_t pid;148      // Skip non-numeric name directories149      if (!llvm::to_integer(direntry->d_name, pid))150        continue;151      // Skip this process.152      if (pid == our_pid)153        continue;154 155      ProcessState State;156      ProcessInstanceInfo process_info;157      if (!GetProcessAndStatInfo(pid, process_info, State))158        continue;159 160      if (State == ProcessState::Zombie ||161          State == ProcessState::TracedOrStopped)162        continue;163 164      // Check for user match if we're not matching all users and not running165      // as root.166      if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))167        continue;168 169      if (match_info.Matches(process_info))170        process_infos.push_back(process_info);171    }172    closedir(dirproc);173  }174  return process_infos.size();175}176 177bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {178  ProcessState State;179  return GetProcessAndStatInfo(pid, process_info, State);180}181 182Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {183  return Status("unimplemented");184}185