6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
9
- #include < cerrno>
10
- #include < cstdio>
11
- #include < cstring>
12
- #include < dirent.h>
13
- #include < fcntl.h>
14
- #include < sys/stat.h>
15
- #include < sys/types.h>
16
- #include < sys/utsname.h>
17
- #include < unistd.h>
18
-
19
- #include " llvm/ADT/StringSwitch.h"
20
- #include " llvm/Object/ELF.h"
21
- #include " llvm/Support/ScopedPrinter.h"
22
-
9
+ #include " lldb/Host/Host.h"
10
+ #include " lldb/Host/posix/Support.h"
23
11
#include " lldb/Utility/LLDBLog.h"
24
12
#include " lldb/Utility/Log.h"
25
13
#include " lldb/Utility/ProcessInfo.h"
26
14
#include " lldb/Utility/Status.h"
27
-
28
- #include " lldb/Host/FileSystem.h"
29
- #include " lldb/Host/Host.h"
30
- #include " lldb/Host/HostInfo.h"
31
- #include " lldb/Host/aix/Host.h"
32
- #include " lldb/Host/posix/Support.h"
33
- #include " lldb/Utility/DataExtractor.h"
34
15
#include " llvm/BinaryFormat/XCOFF.h"
35
16
#include < dirent.h>
36
17
#include < sys/proc.h>
37
18
#include < sys/procfs.h>
38
19
39
- using namespace llvm ;
40
20
using namespace lldb ;
41
21
using namespace lldb_private ;
42
22
@@ -55,173 +35,98 @@ enum class ProcessState {
55
35
};
56
36
}
57
37
58
- namespace lldb_private {
59
- class ProcessLaunchInfo ;
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;
60
43
}
61
44
62
- static bool GetStatusInfo (::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
63
- ProcessState &State, ::pid_t &TracerPid,
64
- ::pid_t &Tgid) {
65
- Log *log = GetLog (LLDBLog::Host);
66
-
67
- auto BufferOrError = getProcFile (Pid, " status" );
45
+ static bool GetStatusInfo (::pid_t pid, ProcessInstanceInfo &processInfo,
46
+ ProcessState &State) {
47
+ struct pstatus pstatusData;
48
+ auto BufferOrError = getProcFile (pid, " status" );
68
49
if (!BufferOrError)
69
50
return false ;
70
51
71
- llvm::StringRef Rest = BufferOrError.get ()->getBuffer ();
72
- while (!Rest.empty ()) {
73
- llvm::StringRef Line;
74
- std::tie (Line, Rest) = Rest.split (' \n ' );
75
-
76
- if (Line.consume_front (" Gid:" )) {
77
- // Real, effective, saved set, and file system GIDs. Read the first two.
78
- Line = Line.ltrim ();
79
- uint32_t RGid, EGid;
80
- Line.consumeInteger (10 , RGid);
81
- Line = Line.ltrim ();
82
- Line.consumeInteger (10 , EGid);
83
-
84
- ProcessInfo.SetGroupID (RGid);
85
- ProcessInfo.SetEffectiveGroupID (EGid);
86
- } else if (Line.consume_front (" Uid:" )) {
87
- // Real, effective, saved set, and file system UIDs. Read the first two.
88
- Line = Line.ltrim ();
89
- uint32_t RUid, EUid;
90
- Line.consumeInteger (10 , RUid);
91
- Line = Line.ltrim ();
92
- Line.consumeInteger (10 , EUid);
93
-
94
- ProcessInfo.SetUserID (RUid);
95
- ProcessInfo.SetEffectiveUserID (EUid);
96
- } else if (Line.consume_front (" PPid:" )) {
97
- ::pid_t PPid;
98
- Line.ltrim ().consumeInteger (10 , PPid);
99
- ProcessInfo.SetParentProcessID (PPid);
100
- } else if (Line.consume_front (" State:" )) {
101
- State = llvm::StringSwitch<ProcessState>(Line.ltrim ().take_front (1 ))
102
- .Case (" D" , ProcessState::DiskSleep)
103
- .Case (" I" , ProcessState::Idle)
104
- .Case (" R" , ProcessState::Running)
105
- .Case (" S" , ProcessState::Sleeping)
106
- .CaseLower (" T" , ProcessState::TracedOrStopped)
107
- .Case (" W" , ProcessState::Paging)
108
- .Case (" P" , ProcessState::Parked)
109
- .Case (" X" , ProcessState::Dead)
110
- .Case (" Z" , ProcessState::Zombie)
111
- .Default (ProcessState::Unknown);
112
- if (State == ProcessState::Unknown) {
113
- LLDB_LOG (log, " Unknown process state {0}" , Line);
114
- }
115
- } else if (Line.consume_front (" TracerPid:" )) {
116
- Line = Line.ltrim ();
117
- Line.consumeInteger (10 , TracerPid);
118
- } else if (Line.consume_front (" Tgid:" )) {
119
- Line = Line.ltrim ();
120
- Line.consumeInteger (10 , Tgid);
121
- }
122
- }
123
- return true ;
124
- }
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 ;
125
56
126
- static bool IsDirNumeric (const char *dname) {
127
- for (; *dname; dname++) {
128
- if (!isdigit (*dname))
129
- return false ;
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 ;
130
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 ));
131
81
return true ;
132
82
}
133
83
134
- static void GetProcessArgs (::pid_t pid, ProcessInstanceInfo &process_info) {
135
- auto BufferOrError = getProcFile (pid, " cmdline" );
136
- if (!BufferOrError)
137
- return ;
138
- std::unique_ptr<llvm::MemoryBuffer> Cmdline = std::move (*BufferOrError);
139
-
140
- llvm::StringRef Arg0, Rest;
141
- std::tie (Arg0, Rest) = Cmdline->getBuffer ().split (' \0 ' );
142
- process_info.SetArg0 (Arg0);
143
- while (!Rest.empty ()) {
144
- llvm::StringRef Arg;
145
- std::tie (Arg, Rest) = Rest.split (' \0 ' );
146
- process_info.GetArguments ().AppendArgument (Arg);
147
- }
148
- }
149
-
150
- static void GetExePathAndArch (::pid_t pid, ProcessInstanceInfo &process_info) {
151
- Log *log = GetLog (LLDBLog::Process);
152
- std::string ExePath (PATH_MAX, ' \0 ' );
153
- std::string Basename (PATH_MAX, ' \0 ' );
84
+ static bool GetExePathAndIds (::pid_t pid, ProcessInstanceInfo &process_info) {
154
85
struct psinfo psinfoData;
86
+ auto BufferOrError = getProcFile (pid, " psinfo" );
87
+ if (!BufferOrError)
88
+ return false ;
155
89
156
- // We can't use getProcFile here because proc/[pid]/exe is a symbolic link.
157
- llvm::SmallString<64 > ProcExe;
158
- (llvm::Twine (" /proc/" ) + llvm::Twine (pid) + " /cwd" ).toVector (ProcExe);
159
-
160
- ssize_t len = readlink (ProcExe.c_str (), &ExePath[0 ], PATH_MAX);
161
- if (len > 0 ) {
162
- ExePath.resize (len);
163
-
164
- // FIXME: hack to get basename
165
- struct stat statData;
166
-
167
- std::ostringstream oss;
168
-
169
- oss << " /proc/" << std::dec << pid << " /psinfo" ;
170
- assert (stat (oss.str ().c_str (), &statData) == 0 );
171
-
172
- const int fd = open (oss.str ().c_str (), O_RDONLY);
173
- assert (fd >= 0 );
174
-
175
- ssize_t readNum = read (fd, &psinfoData, sizeof (psinfoData));
176
- assert (readNum >= 0 );
177
-
178
- close (fd);
179
- } else {
180
- LLDB_LOG (log, " failed to read link exe link for {0}: {1}" , pid,
181
- Status (errno, eErrorTypePOSIX));
182
- ExePath.resize (0 );
183
- }
184
-
185
- llvm::StringRef PathRef = std::string (&(psinfoData.pr_psargs [0 ]));
186
-
187
- if (!PathRef.empty ()) {
188
- process_info.GetExecutableFile ().SetFile (PathRef, FileSpec::Style::native);
189
- ArchSpec arch_spec = ArchSpec ();
190
- arch_spec.SetArchitecture (eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE, llvm::Triple::AIX);
191
- process_info.SetArchitecture (arch_spec);
192
- }
193
- }
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 ;
194
94
195
- static void GetProcessEnviron (::pid_t pid, ProcessInstanceInfo &process_info) {
196
- // Get the process environment.
197
- auto BufferOrError = getProcFile (pid, " environ" );
198
- if (!BufferOrError)
199
- return ;
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 ;
200
101
201
- std::unique_ptr<llvm::MemoryBuffer> Environ = std::move (*BufferOrError);
202
- llvm::StringRef Rest = Environ->getBuffer ();
203
- while (!Rest.empty ()) {
204
- llvm::StringRef Var;
205
- std::tie (Var, Rest) = Rest.split (' \0 ' );
206
- process_info.GetEnvironment ().insert (Var);
207
- }
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 ;
208
115
}
209
116
210
117
static bool GetProcessAndStatInfo (::pid_t pid,
211
118
ProcessInstanceInfo &process_info,
212
- ProcessState &State, ::pid_t &tracerpid) {
213
- ::pid_t tgid;
214
- tracerpid = 0 ;
119
+ ProcessState &State) {
215
120
process_info.Clear ();
216
-
217
121
process_info.SetProcessID (pid);
218
122
219
- GetExePathAndArch (pid, process_info);
220
- GetProcessArgs (pid, process_info);
221
- GetProcessEnviron (pid, process_info);
222
-
223
- // Get User and Group IDs and get tracer pid.
224
- if (!GetStatusInfo (pid, process_info, State, tracerpid, tgid))
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))
225
130
return false ;
226
131
227
132
return true ;
@@ -270,24 +175,10 @@ uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
270
175
}
271
176
272
177
bool Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) {
273
- ::pid_t tracerpid;
274
178
ProcessState State;
275
- return GetProcessAndStatInfo (pid, process_info, State, tracerpid );
179
+ return GetProcessAndStatInfo (pid, process_info, State);
276
180
}
277
181
278
- Environment Host::GetEnvironment () { return Environment (environ); }
279
-
280
182
Status Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) {
281
183
return Status (" unimplemented" );
282
184
}
283
-
284
- std::optional<lldb::pid_t > lldb_private::getPIDForTID (lldb::pid_t tid) {
285
- ::pid_t tracerpid, tgid = LLDB_INVALID_PROCESS_ID;
286
- ProcessInstanceInfo process_info;
287
- ProcessState state;
288
-
289
- if (!GetStatusInfo (tid, process_info, state, tracerpid, tgid) ||
290
- tgid == LLDB_INVALID_PROCESS_ID)
291
- return std::nullopt;
292
- return tgid;
293
- }
0 commit comments