Skip to content

Commit 9b8ec4d

Browse files
committed
adds additional information to the ProcessInfo object for elf processes
1 parent c6e0162 commit 9b8ec4d

File tree

3 files changed

+182
-20
lines changed

3 files changed

+182
-20
lines changed

lldb/include/lldb/Utility/ProcessInfo.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ class ProcessInfo {
139139
// to that process.
140140
class ProcessInstanceInfo : public ProcessInfo {
141141
public:
142+
struct timespec {
143+
time_t tv_sec = 0;
144+
long int tv_usec = 0;
145+
};
146+
142147
ProcessInstanceInfo() = default;
143148

144149
ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid)
@@ -172,6 +177,66 @@ class ProcessInstanceInfo : public ProcessInfo {
172177
return m_parent_pid != LLDB_INVALID_PROCESS_ID;
173178
}
174179

180+
lldb::pid_t GetProcessGroupID() const { return m_process_group_id; }
181+
182+
void SetProcessGroupID(lldb::pid_t pgrp) { m_process_group_id = pgrp; }
183+
184+
bool ProcessGroupIDIsValid() const {
185+
return m_process_group_id != LLDB_INVALID_PROCESS_ID;
186+
}
187+
188+
lldb::pid_t GetProcessSessionID() const { return m_process_session_id; }
189+
190+
void SetProcessSessionID(lldb::pid_t session) {
191+
m_process_session_id = session;
192+
}
193+
194+
bool ProcessSessionIDIsValid() const {
195+
return m_process_session_id != LLDB_INVALID_PROCESS_ID;
196+
}
197+
198+
struct timespec GetUserTime() const { return m_user_time; }
199+
200+
void SetUserTime(struct timespec utime) { m_user_time = utime; }
201+
202+
bool UserTimeIsValid() const {
203+
return m_user_time.tv_sec > 0 || m_user_time.tv_usec > 0;
204+
}
205+
206+
struct timespec GetSystemTime() const { return m_system_time; }
207+
208+
void SetSystemTime(struct timespec stime) { m_system_time = stime; }
209+
210+
bool SystemTimeIsValid() const {
211+
return m_system_time.tv_sec > 0 || m_system_time.tv_usec > 0;
212+
}
213+
214+
struct timespec GetCumulativeUserTime() const {
215+
return m_cumulative_user_time;
216+
}
217+
218+
void SetCumulativeUserTime(struct timespec cutime) {
219+
m_cumulative_user_time = cutime;
220+
}
221+
222+
bool CumulativeUserTimeIsValid() const {
223+
return m_cumulative_user_time.tv_sec > 0 ||
224+
m_cumulative_user_time.tv_usec > 0;
225+
}
226+
227+
struct timespec GetCumulativeSystemTime() const {
228+
return m_cumulative_system_time;
229+
}
230+
231+
void SetCumulativeSystemTime(struct timespec cstime) {
232+
m_cumulative_system_time = cstime;
233+
}
234+
235+
bool CumulativeSystemTimeIsValid() const {
236+
return m_cumulative_system_time.tv_sec > 0 ||
237+
m_cumulative_system_time.tv_sec > 0;
238+
}
239+
175240
void Dump(Stream &s, UserIDResolver &resolver) const;
176241

177242
static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
@@ -183,6 +248,12 @@ class ProcessInstanceInfo : public ProcessInfo {
183248
uint32_t m_euid = UINT32_MAX;
184249
uint32_t m_egid = UINT32_MAX;
185250
lldb::pid_t m_parent_pid = LLDB_INVALID_PROCESS_ID;
251+
lldb::pid_t m_process_group_id = LLDB_INVALID_PROCESS_ID;
252+
lldb::pid_t m_process_session_id = LLDB_INVALID_PROCESS_ID;
253+
struct timespec m_user_time {};
254+
struct timespec m_system_time {};
255+
struct timespec m_cumulative_user_time {};
256+
struct timespec m_cumulative_system_time {};
186257
};
187258

188259
typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;

lldb/source/Host/linux/Host.cpp

Lines changed: 105 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,29 @@ enum class ProcessState {
4949
TracedOrStopped,
5050
Zombie,
5151
};
52+
53+
constexpr int task_comm_len = 16;
54+
55+
struct StatFields {
56+
::pid_t pid = LLDB_INVALID_PROCESS_ID;
57+
char comm[task_comm_len];
58+
char state;
59+
::pid_t ppid = LLDB_INVALID_PROCESS_ID;
60+
::pid_t pgrp = LLDB_INVALID_PROCESS_ID;
61+
::pid_t session = LLDB_INVALID_PROCESS_ID;
62+
int tty_nr;
63+
int tpgid;
64+
unsigned flags;
65+
long unsigned minflt;
66+
long unsigned cminflt;
67+
long unsigned majflt;
68+
long unsigned cmajflt;
69+
long unsigned utime;
70+
long unsigned stime;
71+
long cutime;
72+
long cstime;
73+
// .... other things. We don't need them below
74+
};
5275
}
5376

5477
namespace lldb_private {
@@ -60,11 +83,92 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
6083
::pid_t &Tgid) {
6184
Log *log = GetLog(LLDBLog::Host);
6285

63-
auto BufferOrError = getProcFile(Pid, "status");
86+
auto BufferOrError = getProcFile(Pid, "stat");
6487
if (!BufferOrError)
6588
return false;
6689

6790
llvm::StringRef Rest = BufferOrError.get()->getBuffer();
91+
if (Rest.empty())
92+
return false;
93+
StatFields stat_fields;
94+
if (sscanf(Rest.data(),
95+
"%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld",
96+
&stat_fields.pid, stat_fields.comm, &stat_fields.state,
97+
&stat_fields.ppid, &stat_fields.pgrp, &stat_fields.session,
98+
&stat_fields.tty_nr, &stat_fields.tpgid, &stat_fields.flags,
99+
&stat_fields.minflt, &stat_fields.cminflt, &stat_fields.majflt,
100+
&stat_fields.cmajflt, &stat_fields.utime, &stat_fields.stime,
101+
&stat_fields.cutime, &stat_fields.cstime) < 0) {
102+
return false;
103+
}
104+
105+
auto convert = [sc_clk_ticks = sysconf(_SC_CLK_TCK)](auto time_in_ticks) {
106+
ProcessInstanceInfo::timespec ts;
107+
if (sc_clk_ticks <= 0) {
108+
return ts;
109+
}
110+
ts.tv_sec = time_in_ticks / sc_clk_ticks;
111+
double remainder =
112+
(static_cast<double>(time_in_ticks) / sc_clk_ticks) - ts.tv_sec;
113+
ts.tv_usec =
114+
std::chrono::microseconds{std::lround(1e+6 * remainder)}.count();
115+
return ts;
116+
};
117+
118+
ProcessInfo.SetParentProcessID(stat_fields.ppid);
119+
ProcessInfo.SetProcessGroupID(stat_fields.pgrp);
120+
ProcessInfo.SetProcessSessionID(stat_fields.session);
121+
ProcessInfo.SetUserTime(convert(stat_fields.utime));
122+
ProcessInfo.SetSystemTime(convert(stat_fields.stime));
123+
ProcessInfo.SetCumulativeUserTime(convert(stat_fields.cutime));
124+
ProcessInfo.SetCumulativeSystemTime(convert(stat_fields.cstime));
125+
switch (stat_fields.state) {
126+
case 'R':
127+
State = ProcessState::Running;
128+
break;
129+
case 'S':
130+
State = ProcessState::Sleeping;
131+
break;
132+
case 'D':
133+
State = ProcessState::DiskSleep;
134+
break;
135+
case 'Z':
136+
State = ProcessState::Zombie;
137+
break;
138+
case 'X':
139+
State = ProcessState::Dead;
140+
break;
141+
case 'P':
142+
State = ProcessState::Parked;
143+
break;
144+
case 'W':
145+
State = ProcessState::Paging;
146+
break;
147+
case 'I':
148+
State = ProcessState::Idle;
149+
break;
150+
case 'T': // Stopped on a signal or (before Linux 2.6.33) trace stopped
151+
[[fallthrough]];
152+
case 't':
153+
State = ProcessState::TracedOrStopped;
154+
break;
155+
default:
156+
State = ProcessState::Unknown;
157+
break;
158+
}
159+
160+
if (State == ProcessState::Unknown) {
161+
LLDB_LOG(log, "Unknown process state {0}", stat_fields.state);
162+
}
163+
164+
BufferOrError = getProcFile(Pid, "status");
165+
if (!BufferOrError)
166+
return false;
167+
168+
Rest = BufferOrError.get()->getBuffer();
169+
if (Rest.empty())
170+
return false;
171+
68172
while (!Rest.empty()) {
69173
llvm::StringRef Line;
70174
std::tie(Line, Rest) = Rest.split('\n');
@@ -89,25 +193,6 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
89193

90194
ProcessInfo.SetUserID(RUid);
91195
ProcessInfo.SetEffectiveUserID(EUid);
92-
} else if (Line.consume_front("PPid:")) {
93-
::pid_t PPid;
94-
Line.ltrim().consumeInteger(10, PPid);
95-
ProcessInfo.SetParentProcessID(PPid);
96-
} else if (Line.consume_front("State:")) {
97-
State = llvm::StringSwitch<ProcessState>(Line.ltrim().take_front(1))
98-
.Case("D", ProcessState::DiskSleep)
99-
.Case("I", ProcessState::Idle)
100-
.Case("R", ProcessState::Running)
101-
.Case("S", ProcessState::Sleeping)
102-
.CaseLower("T", ProcessState::TracedOrStopped)
103-
.Case("W", ProcessState::Paging)
104-
.Case("P", ProcessState::Parked)
105-
.Case("X", ProcessState::Dead)
106-
.Case("Z", ProcessState::Zombie)
107-
.Default(ProcessState::Unknown);
108-
if (State == ProcessState::Unknown) {
109-
LLDB_LOG(log, "Unknown process state {0}", Line);
110-
}
111196
} else if (Line.consume_front("TracerPid:")) {
112197
Line = Line.ltrim();
113198
Line.consumeInteger(10, TracerPid);

lldb/unittests/Host/linux/HostTest.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ TEST_F(HostTest, GetProcessInfo) {
4040
ASSERT_TRUE(Info.ParentProcessIDIsValid());
4141
EXPECT_EQ(lldb::pid_t(getppid()), Info.GetParentProcessID());
4242

43+
ASSERT_TRUE(Info.ProcessGroupIDIsValid());
44+
EXPECT_EQ(lldb::pid_t(getpgrp()), Info.GetProcessGroupID());
45+
46+
ASSERT_TRUE(Info.ProcessSessionIDIsValid());
47+
EXPECT_EQ(lldb::pid_t(getsid(getpid())), Info.GetProcessSessionID());
48+
4349
ASSERT_TRUE(Info.EffectiveUserIDIsValid());
4450
EXPECT_EQ(geteuid(), Info.GetEffectiveUserID());
4551

0 commit comments

Comments
 (0)