Path: blob/main/contrib/llvm-project/lldb/source/Host/aix/Host.cpp
213799 views
//===-- source/Host/aix/Host.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 "lldb/Host/Host.h"9#include "lldb/Host/posix/Support.h"10#include "lldb/Utility/LLDBLog.h"11#include "lldb/Utility/Log.h"12#include "lldb/Utility/ProcessInfo.h"13#include "lldb/Utility/Status.h"14#include "llvm/BinaryFormat/XCOFF.h"15#include <dirent.h>16#include <sys/proc.h>17#include <sys/procfs.h>1819using namespace lldb;20using namespace lldb_private;2122namespace {23enum class ProcessState {24Unknown,25Dead,26DiskSleep,27Idle,28Paging,29Parked,30Running,31Sleeping,32TracedOrStopped,33Zombie,34};35}3637static ProcessInstanceInfo::timespec convert(pr_timestruc64_t t) {38ProcessInstanceInfo::timespec ts;39ts.tv_sec = t.tv_sec;40ts.tv_usec = t.tv_nsec / 1000; // nanos to micros41return ts;42}4344static bool GetStatusInfo(::pid_t pid, ProcessInstanceInfo &processInfo,45ProcessState &State) {46struct pstatus pstatusData;47auto BufferOrError = getProcFile(pid, "status");48if (!BufferOrError)49return false;5051std::unique_ptr<llvm::MemoryBuffer> StatusBuffer = std::move(*BufferOrError);52// Ensure there's enough data for psinfoData53if (StatusBuffer->getBufferSize() < sizeof(pstatusData))54return false;5556std::memcpy(&pstatusData, StatusBuffer->getBufferStart(),57sizeof(pstatusData));58switch (pstatusData.pr_stat) {59case SIDL:60State = ProcessState::Idle;61break;62case SACTIVE:63State = ProcessState::Running;64break;65case SSTOP:66State = ProcessState::TracedOrStopped;67break;68case SZOMB:69State = ProcessState::Zombie;70break;71default:72State = ProcessState::Unknown;73break;74}75processInfo.SetIsZombie(State == ProcessState::Zombie);76processInfo.SetUserTime(convert(pstatusData.pr_utime));77processInfo.SetSystemTime(convert(pstatusData.pr_stime));78processInfo.SetCumulativeUserTime(convert(pstatusData.pr_cutime));79processInfo.SetCumulativeSystemTime(convert(pstatusData.pr_cstime));80return true;81}8283static bool GetExePathAndIds(::pid_t pid, ProcessInstanceInfo &process_info) {84struct psinfo psinfoData;85auto BufferOrError = getProcFile(pid, "psinfo");86if (!BufferOrError)87return false;8889std::unique_ptr<llvm::MemoryBuffer> PsinfoBuffer = std::move(*BufferOrError);90// Ensure there's enough data for psinfoData91if (PsinfoBuffer->getBufferSize() < sizeof(psinfoData))92return false;9394std::memcpy(&psinfoData, PsinfoBuffer->getBufferStart(), sizeof(psinfoData));95llvm::StringRef PathRef(96psinfoData.pr_psargs,97strnlen(psinfoData.pr_psargs, sizeof(psinfoData.pr_psargs)));98if (PathRef.empty())99return false;100101process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);102ArchSpec arch_spec = ArchSpec();103arch_spec.SetArchitecture(eArchTypeXCOFF, llvm::XCOFF::TCPU_PPC64,104LLDB_INVALID_CPUTYPE, llvm::Triple::AIX);105process_info.SetArchitecture(arch_spec);106process_info.SetParentProcessID(psinfoData.pr_ppid);107process_info.SetGroupID(psinfoData.pr_gid);108process_info.SetEffectiveGroupID(psinfoData.pr_egid);109process_info.SetUserID(psinfoData.pr_uid);110process_info.SetEffectiveUserID(psinfoData.pr_euid);111process_info.SetProcessGroupID(psinfoData.pr_pgid);112process_info.SetProcessSessionID(psinfoData.pr_sid);113return true;114}115116static bool GetProcessAndStatInfo(::pid_t pid,117ProcessInstanceInfo &process_info,118ProcessState &State) {119process_info.Clear();120process_info.SetProcessID(pid);121122if (pid == LLDB_INVALID_PROCESS_ID)123return false;124// Get Executable path/Arch and Get User and Group IDs.125if (!GetExePathAndIds(pid, process_info))126return false;127// Get process status and timing info.128if (!GetStatusInfo(pid, process_info, State))129return false;130131return true;132}133134uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,135ProcessInstanceInfoList &process_infos) {136static const char procdir[] = "/proc/";137138DIR *dirproc = opendir(procdir);139if (dirproc) {140struct dirent *direntry = nullptr;141const uid_t our_uid = getuid();142const lldb::pid_t our_pid = getpid();143bool all_users = match_info.GetMatchAllUsers();144145while ((direntry = readdir(dirproc)) != nullptr) {146lldb::pid_t pid;147// Skip non-numeric name directories148if (!llvm::to_integer(direntry->d_name, pid))149continue;150// Skip this process.151if (pid == our_pid)152continue;153154ProcessState State;155ProcessInstanceInfo process_info;156if (!GetProcessAndStatInfo(pid, process_info, State))157continue;158159if (State == ProcessState::Zombie ||160State == ProcessState::TracedOrStopped)161continue;162163// Check for user match if we're not matching all users and not running164// as root.165if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))166continue;167168if (match_info.Matches(process_info))169process_infos.push_back(process_info);170}171closedir(dirproc);172}173return process_infos.size();174}175176bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {177ProcessState State;178return GetProcessAndStatInfo(pid, process_info, State);179}180181Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {182return Status("unimplemented");183}184185186