Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Host/aix/Host.cpp
213799 views
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/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
20
using namespace lldb;
21
using namespace lldb_private;
22
23
namespace {
24
enum 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
38
static 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 micros
42
return ts;
43
}
44
45
static 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 psinfoData
54
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
84
static 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 psinfoData
92
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
117
static 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
135
uint32_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 directories
149
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 running
165
// 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
177
bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
178
ProcessState State;
179
return GetProcessAndStatInfo(pid, process_info, State);
180
}
181
182
Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
183
return Status("unimplemented");
184
}
185
186