Hemang Gadhavi d1bb8d6a5c
[lldb][AIX] get host info for AIX (#134354)
This PR is in reference to porting LLDB on AIX.

Link to discussions on llvm discourse and github:

1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640
2. https://github.com/llvm/llvm-project/issues/101657
The complete changes for porting are present in this draft PR:
https://github.com/llvm/llvm-project/pull/102601

- Added changes to make the common host support functions under
`Host/posix` for unix-like system.
Also, created the `unittests/Host/posix/` to test the hostInfo & support
functions for unix-like system.
- Added changes to get the host information for AIX. (GetProcessInfo()) 
(Information like : executable path, arch, process status etc.)
2025-04-29 11:23:03 +05:30

147 lines
4.5 KiB
C++

//===-- source/Host/aix/Host.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Host/Host.h"
#include "lldb/Host/posix/Support.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/Status.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include <sys/proc.h>
#include <sys/procfs.h>
using namespace lldb;
using namespace lldb_private;
namespace {
enum class ProcessState {
Unknown,
Dead,
DiskSleep,
Idle,
Paging,
Parked,
Running,
Sleeping,
TracedOrStopped,
Zombie,
};
}
static ProcessInstanceInfo::timespec convert(pr_timestruc64_t t) {
ProcessInstanceInfo::timespec ts;
ts.tv_sec = t.tv_sec;
ts.tv_usec = t.tv_nsec / 1000; // nanos to micros
return ts;
}
static bool GetStatusInfo(::pid_t pid, ProcessInstanceInfo &processInfo,
ProcessState &State) {
struct pstatus pstatusData;
auto BufferOrError = getProcFile(pid, "status");
if (!BufferOrError)
return false;
std::unique_ptr<llvm::MemoryBuffer> StatusBuffer = std::move(*BufferOrError);
// Ensure there's enough data for psinfoData
if (StatusBuffer->getBufferSize() < sizeof(pstatusData))
return false;
std::memcpy(&pstatusData, StatusBuffer->getBufferStart(),
sizeof(pstatusData));
switch (pstatusData.pr_stat) {
case SIDL:
State = ProcessState::Idle;
break;
case SACTIVE:
State = ProcessState::Running;
break;
case SSTOP:
State = ProcessState::TracedOrStopped;
break;
case SZOMB:
State = ProcessState::Zombie;
break;
default:
State = ProcessState::Unknown;
break;
}
processInfo.SetIsZombie(State == ProcessState::Zombie);
processInfo.SetUserTime(convert(pstatusData.pr_utime));
processInfo.SetSystemTime(convert(pstatusData.pr_stime));
processInfo.SetCumulativeUserTime(convert(pstatusData.pr_cutime));
processInfo.SetCumulativeSystemTime(convert(pstatusData.pr_cstime));
return true;
}
static bool GetExePathAndIds(::pid_t pid, ProcessInstanceInfo &process_info) {
struct psinfo psinfoData;
auto BufferOrError = getProcFile(pid, "psinfo");
if (!BufferOrError)
return false;
std::unique_ptr<llvm::MemoryBuffer> PsinfoBuffer = std::move(*BufferOrError);
// Ensure there's enough data for psinfoData
if (PsinfoBuffer->getBufferSize() < sizeof(psinfoData))
return false;
std::memcpy(&psinfoData, PsinfoBuffer->getBufferStart(), sizeof(psinfoData));
llvm::StringRef PathRef(
psinfoData.pr_psargs,
strnlen(psinfoData.pr_psargs, sizeof(psinfoData.pr_psargs)));
if (PathRef.empty())
return false;
process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
ArchSpec arch_spec = ArchSpec();
arch_spec.SetArchitecture(eArchTypeXCOFF, llvm::XCOFF::TCPU_PPC64,
LLDB_INVALID_CPUTYPE, llvm::Triple::AIX);
process_info.SetArchitecture(arch_spec);
process_info.SetParentProcessID(psinfoData.pr_ppid);
process_info.SetGroupID(psinfoData.pr_gid);
process_info.SetEffectiveGroupID(psinfoData.pr_egid);
process_info.SetUserID(psinfoData.pr_uid);
process_info.SetEffectiveUserID(psinfoData.pr_euid);
process_info.SetProcessGroupID(psinfoData.pr_pgid);
process_info.SetProcessSessionID(psinfoData.pr_sid);
return true;
}
static bool GetProcessAndStatInfo(::pid_t pid,
ProcessInstanceInfo &process_info,
ProcessState &State) {
process_info.Clear();
process_info.SetProcessID(pid);
if (pid == LLDB_INVALID_PROCESS_ID)
return false;
// Get Executable path/Arch and Get User and Group IDs.
if (!GetExePathAndIds(pid, process_info))
return false;
// Get process status and timing info.
if (!GetStatusInfo(pid, process_info, State))
return false;
return true;
}
uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfoList &process_infos) {
return 0;
}
bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
ProcessState State;
return GetProcessAndStatInfo(pid, process_info, State);
}
Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
return Status("unimplemented");
}