blob: cdcff1f3d7525e00c9a8277c7fb38e1c00544370 [file] [log] [blame]
Stephen Wilson76fd5dd2011-03-23 01:58:26 +00001//===-- source/Host/linux/Host.cpp ------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <stdio.h>
12#include <sys/utsname.h>
Johnny Chen7e996472012-01-05 19:17:38 +000013#include <sys/types.h>
14#include <sys/stat.h>
Daniel Malea9b4c5482013-05-15 17:54:07 +000015#include <dirent.h>
Johnny Chen7e996472012-01-05 19:17:38 +000016#include <fcntl.h>
Michael Sartain0bbfea62013-07-17 00:26:30 +000017#include <execinfo.h>
Johnny Chen7e996472012-01-05 19:17:38 +000018
Stephen Wilson76fd5dd2011-03-23 01:58:26 +000019// C++ Includes
20// Other libraries and framework includes
21// Project includes
Johnny Chen527b2b92011-05-19 23:07:19 +000022#include "lldb/Core/Error.h"
Johnny Chen7e996472012-01-05 19:17:38 +000023#include "lldb/Target/Process.h"
24
Stephen Wilson76fd5dd2011-03-23 01:58:26 +000025#include "lldb/Host/Host.h"
Johnny Chen7e996472012-01-05 19:17:38 +000026#include "lldb/Core/DataBufferHeap.h"
27#include "lldb/Core/DataExtractor.h"
Stephen Wilson76fd5dd2011-03-23 01:58:26 +000028
Michael Sartain0be9b3b2013-05-23 20:57:03 +000029#include "lldb/Core/ModuleSpec.h"
30#include "lldb/Symbol/ObjectFile.h"
31
Stephen Wilson76fd5dd2011-03-23 01:58:26 +000032using namespace lldb;
33using namespace lldb_private;
34
Daniel Malea9b4c5482013-05-15 17:54:07 +000035typedef enum ProcessStateFlags
36{
37 eProcessStateRunning = (1u << 0), // Running
38 eProcessStateSleeping = (1u << 1), // Sleeping in an interruptible wait
39 eProcessStateWaiting = (1u << 2), // Waiting in an uninterruptible disk sleep
40 eProcessStateZombie = (1u << 3), // Zombie
41 eProcessStateTracedOrStopped = (1u << 4), // Traced or stopped (on a signal)
42 eProcessStatePaging = (1u << 5) // Paging
43} ProcessStateFlags;
44
45typedef struct ProcessStatInfo
46{
47 lldb::pid_t ppid; // Parent Process ID
48 uint32_t fProcessState; // ProcessStateFlags
49} ProcessStatInfo;
50
51// Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid).
52static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid);
53
Michael Sartain519bc3c2013-05-17 00:08:09 +000054
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +000055namespace
Stephen Wilson76fd5dd2011-03-23 01:58:26 +000056{
Johnny Chen527b2b92011-05-19 23:07:19 +000057
Johnny Chen7e996472012-01-05 19:17:38 +000058lldb::DataBufferSP
Daniel Malea9b4c5482013-05-15 17:54:07 +000059ReadProcPseudoFile (lldb::pid_t pid, const char *name)
Johnny Chen7e996472012-01-05 19:17:38 +000060{
Johnny Chen7e996472012-01-05 19:17:38 +000061 int fd;
Daniel Malea9b4c5482013-05-15 17:54:07 +000062 char path[PATH_MAX];
63
64 // Make sure we've got a nil terminated buffer for all the folks calling
65 // GetBytes() directly off our returned DataBufferSP if we hit an error.
66 lldb::DataBufferSP buf_sp (new DataBufferHeap(1, 0));
Johnny Chen7e996472012-01-05 19:17:38 +000067
68 // Ideally, we would simply create a FileSpec and call ReadFileContents.
69 // However, files in procfs have zero size (since they are, in general,
70 // dynamically generated by the kernel) which is incompatible with the
Daniel Malea9b4c5482013-05-15 17:54:07 +000071 // current ReadFileContents implementation. Therefore we simply stream the
Johnny Chen7e996472012-01-05 19:17:38 +000072 // data into a DataBuffer ourselves.
Daniel Malea9b4c5482013-05-15 17:54:07 +000073 if (snprintf (path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0)
Johnny Chen7e996472012-01-05 19:17:38 +000074 {
Daniel Malea9b4c5482013-05-15 17:54:07 +000075 if ((fd = open (path, O_RDONLY, 0)) >= 0)
Johnny Chen7e996472012-01-05 19:17:38 +000076 {
Daniel Malea9b4c5482013-05-15 17:54:07 +000077 size_t bytes_read = 0;
78 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
Johnny Chen7e996472012-01-05 19:17:38 +000079
Daniel Malea9b4c5482013-05-15 17:54:07 +000080 for (;;)
81 {
82 size_t avail = buf_ap->GetByteSize() - bytes_read;
83 ssize_t status = read (fd, buf_ap->GetBytes() + bytes_read, avail);
84
85 if (status < 0)
86 break;
87
88 if (status == 0)
89 {
90 buf_ap->SetByteSize (bytes_read);
91 buf_sp.reset (buf_ap.release());
92 break;
93 }
94
95 bytes_read += status;
96
97 if (avail - status == 0)
98 buf_ap->SetByteSize (2 * buf_ap->GetByteSize());
99 }
100
101 close (fd);
102 }
Johnny Chen7e996472012-01-05 19:17:38 +0000103 }
104
105 return buf_sp;
106}
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000107
Matt Kopec0ba75482013-07-10 20:53:11 +0000108lldb::DataBufferSP
109ReadProcPseudoFile (lldb::pid_t pid, lldb::tid_t tid, const char *name)
110{
111 std::string process_thread_pseudo_file = "task/" + std::to_string(tid) + "/" + name;
112 return ReadProcPseudoFile(pid, process_thread_pseudo_file.c_str());
113}
114
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000115} // anonymous namespace
116
Daniel Malea9b4c5482013-05-15 17:54:07 +0000117static bool
118ReadProcPseudoFileStat (lldb::pid_t pid, ProcessStatInfo& stat_info)
119{
120 // Read the /proc/$PID/stat file.
121 lldb::DataBufferSP buf_sp = ReadProcPseudoFile (pid, "stat");
122
123 // The filename of the executable is stored in parenthesis right after the pid. We look for the closing
124 // parenthesis for the filename and work from there in case the name has something funky like ')' in it.
125 const char *filename_end = strrchr ((const char *)buf_sp->GetBytes(), ')');
126 if (filename_end)
127 {
128 char state = '\0';
129 int ppid = LLDB_INVALID_PROCESS_ID;
130
131 // Read state and ppid.
132 sscanf (filename_end + 1, " %c %d", &state, &ppid);
133
134 stat_info.ppid = ppid;
135
136 switch (state)
137 {
138 case 'R':
139 stat_info.fProcessState |= eProcessStateRunning;
140 break;
141 case 'S':
142 stat_info.fProcessState |= eProcessStateSleeping;
143 break;
144 case 'D':
145 stat_info.fProcessState |= eProcessStateWaiting;
146 break;
147 case 'Z':
148 stat_info.fProcessState |= eProcessStateZombie;
149 break;
150 case 'T':
151 stat_info.fProcessState |= eProcessStateTracedOrStopped;
152 break;
153 case 'W':
154 stat_info.fProcessState |= eProcessStatePaging;
155 break;
156 }
157
158 return true;
159 }
160
161 return false;
162}
163
164static void
165GetLinuxProcessUserAndGroup (lldb::pid_t pid, ProcessInstanceInfo &process_info, lldb::pid_t &tracerpid)
166{
167 tracerpid = 0;
168 uint32_t rUid = UINT32_MAX; // Real User ID
169 uint32_t eUid = UINT32_MAX; // Effective User ID
170 uint32_t rGid = UINT32_MAX; // Real Group ID
171 uint32_t eGid = UINT32_MAX; // Effective Group ID
172
173 // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: fields.
174 lldb::DataBufferSP buf_sp = ReadProcPseudoFile (pid, "status");
175
176 static const char uid_token[] = "Uid:";
177 char *buf_uid = strstr ((char *)buf_sp->GetBytes(), uid_token);
178 if (buf_uid)
179 {
180 // Real, effective, saved set, and file system UIDs. Read the first two.
181 buf_uid += sizeof(uid_token);
182 rUid = strtol (buf_uid, &buf_uid, 10);
183 eUid = strtol (buf_uid, &buf_uid, 10);
184 }
185
186 static const char gid_token[] = "Gid:";
187 char *buf_gid = strstr ((char *)buf_sp->GetBytes(), gid_token);
188 if (buf_gid)
189 {
190 // Real, effective, saved set, and file system GIDs. Read the first two.
191 buf_gid += sizeof(gid_token);
192 rGid = strtol (buf_gid, &buf_gid, 10);
193 eGid = strtol (buf_gid, &buf_gid, 10);
194 }
195
196 static const char tracerpid_token[] = "TracerPid:";
197 char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token);
198 if (buf_tracerpid)
199 {
200 // Tracer PID. 0 if we're not being debugged.
201 buf_tracerpid += sizeof(tracerpid_token);
202 tracerpid = strtol (buf_tracerpid, &buf_tracerpid, 10);
203 }
204
205 process_info.SetUserID (rUid);
206 process_info.SetEffectiveUserID (eUid);
207 process_info.SetGroupID (rGid);
208 process_info.SetEffectiveGroupID (eGid);
209}
210
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000211bool
212Host::GetOSVersion(uint32_t &major,
213 uint32_t &minor,
214 uint32_t &update)
215{
216 struct utsname un;
217 int status;
218
219 if (uname(&un))
220 return false;
221
222 status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update);
223 return status == 3;
224}
225
226Error
227Host::LaunchProcess (ProcessLaunchInfo &launch_info)
228{
229 Error error;
230 assert(!"Not implemented yet!!!");
231 return error;
232}
233
234lldb::DataBufferSP
235Host::GetAuxvData(lldb_private::Process *process)
236{
237 return ReadProcPseudoFile(process->GetID(), "auxv");
238}
239
Daniel Malea9b4c5482013-05-15 17:54:07 +0000240static bool
241IsDirNumeric(const char *dname)
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000242{
Daniel Malea9b4c5482013-05-15 17:54:07 +0000243 for (; *dname; dname++)
244 {
245 if (!isdigit (*dname))
246 return false;
247 }
248 return true;
249}
250
251uint32_t
252Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
253{
254 static const char procdir[] = "/proc/";
255
256 DIR *dirproc = opendir (procdir);
257 if (dirproc)
258 {
259 struct dirent *direntry = NULL;
260 const uid_t our_uid = getuid();
261 const lldb::pid_t our_pid = getpid();
262 bool all_users = match_info.GetMatchAllUsers();
263
264 while ((direntry = readdir (dirproc)) != NULL)
265 {
266 if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
267 continue;
268
269 lldb::pid_t pid = atoi (direntry->d_name);
270
271 // Skip this process.
272 if (pid == our_pid)
273 continue;
274
275 lldb::pid_t tracerpid;
276 ProcessStatInfo stat_info;
277 ProcessInstanceInfo process_info;
278
279 if (!GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid))
280 continue;
281
282 // Skip if process is being debugged.
283 if (tracerpid != 0)
284 continue;
285
286 // Skip zombies.
287 if (stat_info.fProcessState & eProcessStateZombie)
288 continue;
289
290 // Check for user match if we're not matching all users and not running as root.
291 if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
292 continue;
293
294 if (match_info.Matches (process_info))
295 {
296 process_infos.Append (process_info);
297 }
298 }
299
300 closedir (dirproc);
301 }
302
303 return process_infos.GetSize();
304}
305
Matt Kopecc350e132013-05-31 22:00:07 +0000306bool
307Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
308{
309 bool tids_changed = false;
310 static const char procdir[] = "/proc/";
311 static const char taskdir[] = "/task/";
312 std::string process_task_dir = procdir + std::to_string(pid) + taskdir;
313 DIR *dirproc = opendir (process_task_dir.c_str());
314
315 if (dirproc)
316 {
317 struct dirent *direntry = NULL;
318 while ((direntry = readdir (dirproc)) != NULL)
319 {
320 if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
321 continue;
322
323 lldb::tid_t tid = atoi(direntry->d_name);
324 TidMap::iterator it = tids_to_attach.find(tid);
325 if (it == tids_to_attach.end())
326 {
327 tids_to_attach.insert(TidPair(tid, false));
328 tids_changed = true;
329 }
330 }
331 closedir (dirproc);
332 }
333
334 return tids_changed;
335}
336
Daniel Malea9b4c5482013-05-15 17:54:07 +0000337static bool
Michael Sartain0be9b3b2013-05-23 20:57:03 +0000338GetELFProcessCPUType (const char *exe_path, ProcessInstanceInfo &process_info)
339{
340 // Clear the architecture.
341 process_info.GetArchitecture().Clear();
342
343 ModuleSpecList specs;
344 FileSpec filespec (exe_path, false);
Jason Molenda9671f052013-07-15 03:25:21 +0000345 const size_t num_specs = ObjectFile::GetModuleSpecifications (filespec, 0, 0, specs);
Michael Sartain0be9b3b2013-05-23 20:57:03 +0000346 // GetModuleSpecifications() could fail if the executable has been deleted or is locked.
347 // But it shouldn't return more than 1 architecture.
348 assert(num_specs <= 1 && "Linux plugin supports only a single architecture");
349 if (num_specs == 1)
350 {
351 ModuleSpec module_spec;
352 if (specs.GetModuleSpecAtIndex (0, module_spec) && module_spec.GetArchitecture().IsValid())
353 {
354 process_info.GetArchitecture () = module_spec.GetArchitecture();
355 return true;
356 }
357 }
358 return false;
359}
360
361static bool
Daniel Malea9b4c5482013-05-15 17:54:07 +0000362GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid)
363{
364 tracerpid = 0;
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000365 process_info.Clear();
Daniel Malea9b4c5482013-05-15 17:54:07 +0000366 ::memset (&stat_info, 0, sizeof(stat_info));
367 stat_info.ppid = LLDB_INVALID_PROCESS_ID;
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000368
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000369 // Use special code here because proc/[pid]/exe is a symbolic link.
370 char link_path[PATH_MAX];
371 char exe_path[PATH_MAX] = "";
Daniel Malea9b4c5482013-05-15 17:54:07 +0000372 if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0)
373 return false;
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000374
Daniel Malea9b4c5482013-05-15 17:54:07 +0000375 ssize_t len = readlink (link_path, exe_path, sizeof(exe_path) - 1);
376 if (len <= 0)
377 return false;
378
379 // readlink does not append a null byte.
380 exe_path[len] = 0;
381
382 // If the binary has been deleted, the link name has " (deleted)" appended.
383 // Remove if there.
384 static const ssize_t deleted_len = strlen(" (deleted)");
385 if (len > deleted_len &&
386 !strcmp(exe_path + len - deleted_len, " (deleted)"))
387 {
388 exe_path[len - deleted_len] = 0;
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000389 }
Michael Sartain0be9b3b2013-05-23 20:57:03 +0000390 else
391 {
392 GetELFProcessCPUType (exe_path, process_info);
393 }
Daniel Malea9b4c5482013-05-15 17:54:07 +0000394
395 process_info.SetProcessID(pid);
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000396 process_info.GetExecutableFile().SetFile(exe_path, false);
397
398 lldb::DataBufferSP buf_sp;
399
400 // Get the process environment.
401 buf_sp = ReadProcPseudoFile(pid, "environ");
402 Args &info_env = process_info.GetEnvironmentEntries();
403 char *next_var = (char *)buf_sp->GetBytes();
404 char *end_buf = next_var + buf_sp->GetByteSize();
405 while (next_var < end_buf && 0 != *next_var)
406 {
407 info_env.AppendArgument(next_var);
408 next_var += strlen(next_var) + 1;
409 }
410
411 // Get the commond line used to start the process.
412 buf_sp = ReadProcPseudoFile(pid, "cmdline");
413
414 // Grab Arg0 first.
415 char *cmd = (char *)buf_sp->GetBytes();
416 process_info.SetArg0(cmd);
417
418 // Now process any remaining arguments.
419 Args &info_args = process_info.GetArguments();
420 char *next_arg = cmd + strlen(cmd) + 1;
421 end_buf = cmd + buf_sp->GetByteSize();
422 while (next_arg < end_buf && 0 != *next_arg)
423 {
424 info_args.AppendArgument(next_arg);
425 next_arg += strlen(next_arg) + 1;
426 }
427
Daniel Malea9b4c5482013-05-15 17:54:07 +0000428 // Read /proc/$PID/stat to get our parent pid.
429 if (ReadProcPseudoFileStat (pid, stat_info))
430 {
431 process_info.SetParentProcessID (stat_info.ppid);
432 }
433
434 // Get User and Group IDs and get tracer pid.
435 GetLinuxProcessUserAndGroup (pid, process_info, tracerpid);
Andrew Kaylor6c1a8cf2013-05-07 22:46:38 +0000436
437 return true;
Matt Kopec02449772013-05-13 19:33:58 +0000438}
439
Daniel Malea9b4c5482013-05-15 17:54:07 +0000440bool
441Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
442{
443 lldb::pid_t tracerpid;
444 ProcessStatInfo stat_info;
445
446 return GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid);
447}
448
Matt Kopec02449772013-05-13 19:33:58 +0000449void
450Host::ThreadCreated (const char *thread_name)
451{
452 if (!Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name))
453 {
Ed Mastef4765922013-07-25 19:10:32 +0000454 Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16);
Matt Kopec02449772013-05-13 19:33:58 +0000455 }
456}
457
Matt Kopec0ba75482013-07-10 20:53:11 +0000458std::string
459Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
460{
461 const size_t thread_name_max_size = 16;
462 char pthread_name[thread_name_max_size];
463 std::string thread_name;
464 // Read the /proc/$PID/stat file.
465 lldb::DataBufferSP buf_sp = ReadProcPseudoFile (pid, tid, "stat");
466
467 // The file/thread name of the executable is stored in parenthesis. Search for the first
468 // '(' and last ')' and copy everything in between.
469 const char *filename_start = ::strchr ((const char *)buf_sp->GetBytes(), '(');
470 const char *filename_end = ::strrchr ((const char *)buf_sp->GetBytes(), ')');
471
472 if (filename_start && filename_end)
473 {
474 ++filename_start;
475 size_t length = filename_end - filename_start;
476 if (length > thread_name_max_size)
477 length = thread_name_max_size;
478 strncpy(pthread_name, filename_start, length);
479 thread_name = std::string(pthread_name, length);
480 }
481
482 return thread_name;
483}
484
Matt Kopec02449772013-05-13 19:33:58 +0000485void
486Host::Backtrace (Stream &strm, uint32_t max_frames)
487{
Michael Sartain0bbfea62013-07-17 00:26:30 +0000488 if (max_frames > 0)
489 {
490 std::vector<void *> frame_buffer (max_frames, NULL);
491 int num_frames = ::backtrace (&frame_buffer[0], frame_buffer.size());
492 char** strs = ::backtrace_symbols (&frame_buffer[0], num_frames);
493 if (strs)
494 {
495 // Start at 1 to skip the "Host::Backtrace" frame
496 for (int i = 1; i < num_frames; ++i)
497 strm.Printf("%s\n", strs[i]);
498 ::free (strs);
499 }
500 }
Matt Kopec02449772013-05-13 19:33:58 +0000501}
502
503size_t
504Host::GetEnvironment (StringList &env)
505{
Michael Sartain0bbfea62013-07-17 00:26:30 +0000506 char **host_env = environ;
507 char *env_entry;
508 size_t i;
509 for (i=0; (env_entry = host_env[i]) != NULL; ++i)
510 env.AppendString(env_entry);
511 return i;
Matt Kopec02449772013-05-13 19:33:58 +0000512}