LLDB mainline
aix/Host.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Host/Host.h"
10#include "lldb/Host/HostInfo.h"
13#include "lldb/Utility/Log.h"
15#include "lldb/Utility/Status.h"
16#include "llvm/BinaryFormat/XCOFF.h"
17#include "llvm/Object/XCOFFObjectFile.h"
18#include "llvm/Support/MemoryBuffer.h"
19#include <dirent.h>
20#include <sys/proc.h>
21#include <sys/procfs.h>
22
23using namespace lldb;
24using namespace lldb_private;
25
26namespace {
27enum class ProcessState {
28 Unknown,
29 Dead,
30 DiskSleep,
31 Idle,
32 Paging,
33 Parked,
34 Running,
35 Sleeping,
36 TracedOrStopped,
37 Zombie,
38};
39}
40
41static ProcessInstanceInfo::timespec convert(pr_timestruc64_t t) {
43 ts.tv_sec = t.tv_sec;
44 ts.tv_usec = t.tv_nsec / 1000; // nanos to micros
45 return ts;
46}
47
48static bool GetStatusInfo(::pid_t pid, ProcessInstanceInfo &processInfo,
49 ProcessState &State) {
50 struct pstatus pstatusData;
51 auto BufferOrError = getProcFile(pid, "status");
52 if (!BufferOrError)
53 return false;
54
55 std::unique_ptr<llvm::MemoryBuffer> StatusBuffer = std::move(*BufferOrError);
56 // Ensure there's enough data for psinfoData
57 if (StatusBuffer->getBufferSize() < sizeof(pstatusData))
58 return false;
59
60 std::memcpy(&pstatusData, StatusBuffer->getBufferStart(),
61 sizeof(pstatusData));
62 switch (pstatusData.pr_stat) {
63 case SIDL:
64 State = ProcessState::Idle;
65 break;
66 case SACTIVE:
67 State = ProcessState::Running;
68 break;
69 case SSTOP:
70 State = ProcessState::TracedOrStopped;
71 break;
72 case SZOMB:
73 State = ProcessState::Zombie;
74 break;
75 default:
76 State = ProcessState::Unknown;
77 break;
78 }
79 processInfo.SetIsZombie(State == ProcessState::Zombie);
80 processInfo.SetUserTime(convert(pstatusData.pr_utime));
81 processInfo.SetSystemTime(convert(pstatusData.pr_stime));
82 processInfo.SetCumulativeUserTime(convert(pstatusData.pr_cutime));
83 processInfo.SetCumulativeSystemTime(convert(pstatusData.pr_cstime));
84 return true;
85}
86
87static ArchSpec GetXCOFFProcessCPUType(llvm::StringRef exe_path) {
88 Log *log = GetLog(LLDBLog::Host);
89
90 auto file_buffer = llvm::MemoryBuffer::getFile(exe_path);
91 if (!file_buffer)
92 return ArchSpec();
93
94 llvm::Expected<std::unique_ptr<llvm::object::ObjectFile>> obj_or_err =
95 llvm::object::ObjectFile::createObjectFile(
96 (*file_buffer)->getMemBufferRef());
97
98 if (!obj_or_err) {
99 LLDB_LOG(log, "failed to create ObjectFile from buffer");
100 return ArchSpec();
101 }
102
103 llvm::object::ObjectFile *obj = obj_or_err->get();
104
105 const llvm::object::XCOFFObjectFile *xcoff_obj =
106 llvm::dyn_cast<llvm::object::XCOFFObjectFile>(obj);
107 if (!xcoff_obj) {
108 LLDB_LOG(log, "Not an valid XCOFF object file: {0}", exe_path);
109 return ArchSpec();
110 }
111
112 if (xcoff_obj->is64Bit())
113 return HostInfo::GetArchitecture(HostInfo::eArchKind64);
114
115 return HostInfo::GetArchitecture(HostInfo::eArchKind32);
116}
117
118static bool GetExePathAndIds(::pid_t pid, ProcessInstanceInfo &process_info) {
119 struct psinfo psinfoData;
120 auto BufferOrError = getProcFile(pid, "psinfo");
121 if (!BufferOrError)
122 return false;
123
124 std::unique_ptr<llvm::MemoryBuffer> PsinfoBuffer = std::move(*BufferOrError);
125 // Ensure there's enough data for psinfoData
126 if (PsinfoBuffer->getBufferSize() < sizeof(psinfoData))
127 return false;
128
129 std::memcpy(&psinfoData, PsinfoBuffer->getBufferStart(), sizeof(psinfoData));
130 llvm::StringRef PathRef(
131 psinfoData.pr_psargs,
132 strnlen(psinfoData.pr_psargs, sizeof(psinfoData.pr_psargs)));
133 if (PathRef.empty())
134 return false;
135
136 process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
137 ArchSpec arch_spec = GetXCOFFProcessCPUType(PathRef);
138 if (!arch_spec)
139 return false;
140 process_info.SetArchitecture(arch_spec);
141 process_info.SetParentProcessID(psinfoData.pr_ppid);
142 process_info.SetGroupID(psinfoData.pr_gid);
143 process_info.SetEffectiveGroupID(psinfoData.pr_egid);
144 process_info.SetUserID(psinfoData.pr_uid);
145 process_info.SetEffectiveUserID(psinfoData.pr_euid);
146 process_info.SetProcessGroupID(psinfoData.pr_pgid);
147 process_info.SetProcessSessionID(psinfoData.pr_sid);
148 return true;
149}
150
152 ProcessInstanceInfo &process_info,
153 ProcessState &State) {
154 process_info.Clear();
155 process_info.SetProcessID(pid);
156
157 if (pid == LLDB_INVALID_PROCESS_ID)
158 return false;
159 // Get Executable path/Arch and Get User and Group IDs.
160 if (!GetExePathAndIds(pid, process_info))
161 return false;
162 // Get process status and timing info.
163 if (!GetStatusInfo(pid, process_info, State))
164 return false;
165
166 return true;
167}
168
170 ProcessInstanceInfoList &process_infos) {
171 static const char procdir[] = "/proc/";
172
173 DIR *dirproc = opendir(procdir);
174 if (dirproc) {
175 struct dirent *direntry = nullptr;
176 const uid_t our_uid = getuid();
177 const lldb::pid_t our_pid = getpid();
178 bool all_users = match_info.GetMatchAllUsers();
179
180 while ((direntry = readdir(dirproc)) != nullptr) {
181 lldb::pid_t pid;
182 // Skip non-numeric name directories
183 if (!llvm::to_integer(direntry->d_name, pid))
184 continue;
185 // Skip this process.
186 if (pid == our_pid)
187 continue;
188
189 ProcessState State;
190 ProcessInstanceInfo process_info;
191 if (!GetProcessAndStatInfo(pid, process_info, State))
192 continue;
193
194 if (State == ProcessState::Zombie ||
195 State == ProcessState::TracedOrStopped)
196 continue;
197
198 // Check for user match if we're not matching all users and not running
199 // as root.
200 if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
201 continue;
202
203 if (match_info.Matches(process_info))
204 process_infos.push_back(process_info);
205 }
206 closedir(dirproc);
207 }
208 return process_infos.size();
209}
210
212 ProcessState State;
213 return GetProcessAndStatInfo(pid, process_info, State);
214}
215
217 return Status("unimplemented");
218}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:364
static ProcessInstanceInfo::timespec convert(pr_timestruc64_t t)
Definition aix/Host.cpp:41
static bool GetExePathAndIds(::pid_t pid, ProcessInstanceInfo &process_info)
Definition aix/Host.cpp:118
static bool GetStatusInfo(::pid_t pid, ProcessInstanceInfo &processInfo, ProcessState &State)
Definition aix/Host.cpp:48
static ArchSpec GetXCOFFProcessCPUType(llvm::StringRef exe_path)
Definition aix/Host.cpp:87
static bool GetProcessAndStatInfo(::pid_t pid, ProcessInstanceInfo &process_info, ProcessState &State)
Definition aix/Host.cpp:151
An architecture specification class.
Definition ArchSpec.h:32
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition FileSpec.cpp:174
static Status ShellExpandArguments(ProcessLaunchInfo &launch_info)
Perform expansion of the command-line for this launch info This can potentially involve wildcard expa...
Definition aix/Host.cpp:216
static uint32_t FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &proc_infos)
Definition aix/Host.cpp:169
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
Definition aix/Host.cpp:211
void SetGroupID(uint32_t gid)
Definition ProcessInfo.h:60
void SetArchitecture(const ArchSpec &arch)
Definition ProcessInfo.h:66
void SetProcessID(lldb::pid_t pid)
Definition ProcessInfo.h:70
FileSpec & GetExecutableFile()
Definition ProcessInfo.h:43
uint32_t GetUserID() const
Definition ProcessInfo.h:50
void SetUserID(uint32_t uid)
Definition ProcessInfo.h:58
bool Matches(const ProcessInstanceInfo &proc_info) const
void SetUserTime(struct timespec utime)
void SetEffectiveGroupID(uint32_t gid)
void SetIsZombie(bool is_zombie)
void SetCumulativeUserTime(struct timespec cutime)
void SetProcessGroupID(lldb::pid_t pgrp)
void SetProcessSessionID(lldb::pid_t session)
void SetCumulativeSystemTime(struct timespec cstime)
void SetSystemTime(struct timespec stime)
void SetParentProcessID(lldb::pid_t pid)
void SetEffectiveUserID(uint32_t uid)
An error handling class.
Definition Status.h:118
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file)
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition Host.h:32
uint64_t pid_t
Definition lldb-types.h:83