1 //===-- 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 <dirent.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <sys/utsname.h>
19 
20 // C++ Includes
21 // Other libraries and framework includes
22 #include "llvm/Support/ScopedPrinter.h"
23 // Project includes
24 #include "lldb/Core/Error.h"
25 #include "lldb/Core/Log.h"
26 #include "lldb/Target/Process.h"
27 
28 #include "lldb/Core/DataBufferHeap.h"
29 #include "lldb/Core/DataExtractor.h"
30 #include "lldb/Host/Host.h"
31 #include "lldb/Host/HostInfo.h"
32 
33 #include "Plugins/Process/Linux/ProcFileReader.h"
34 #include "lldb/Core/ModuleSpec.h"
35 #include "lldb/Symbol/ObjectFile.h"
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 typedef enum ProcessStateFlags {
41   eProcessStateRunning = (1u << 0),  // Running
42   eProcessStateSleeping = (1u << 1), // Sleeping in an interruptible wait
43   eProcessStateWaiting = (1u << 2),  // Waiting in an uninterruptible disk sleep
44   eProcessStateZombie = (1u << 3),   // Zombie
45   eProcessStateTracedOrStopped = (1u << 4), // Traced or stopped (on a signal)
46   eProcessStatePaging = (1u << 5)           // Paging
47 } ProcessStateFlags;
48 
49 typedef struct ProcessStatInfo {
50   lldb::pid_t ppid;       // Parent Process ID
51   uint32_t fProcessState; // ProcessStateFlags
52 } ProcessStatInfo;
53 
54 // Get the process info with additional information from /proc/$PID/stat (like
55 // process state, and tracer pid).
56 static bool GetProcessAndStatInfo(lldb::pid_t pid,
57                                   ProcessInstanceInfo &process_info,
58                                   ProcessStatInfo &stat_info,
59                                   lldb::pid_t &tracerpid);
60 
61 static bool ReadProcPseudoFileStat(lldb::pid_t pid,
62                                    ProcessStatInfo &stat_info) {
63   // Read the /proc/$PID/stat file.
64   lldb::DataBufferSP buf_sp =
65       process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "stat");
66 
67   // The filename of the executable is stored in parenthesis right after the
68   // pid. We look for the closing
69   // parenthesis for the filename and work from there in case the name has
70   // something funky like ')' in it.
71   const char *filename_end = strrchr((const char *)buf_sp->GetBytes(), ')');
72   if (filename_end) {
73     char state = '\0';
74     int ppid = LLDB_INVALID_PROCESS_ID;
75 
76     // Read state and ppid.
77     sscanf(filename_end + 1, " %c %d", &state, &ppid);
78 
79     stat_info.ppid = ppid;
80 
81     switch (state) {
82     case 'R':
83       stat_info.fProcessState |= eProcessStateRunning;
84       break;
85     case 'S':
86       stat_info.fProcessState |= eProcessStateSleeping;
87       break;
88     case 'D':
89       stat_info.fProcessState |= eProcessStateWaiting;
90       break;
91     case 'Z':
92       stat_info.fProcessState |= eProcessStateZombie;
93       break;
94     case 'T':
95       stat_info.fProcessState |= eProcessStateTracedOrStopped;
96       break;
97     case 'W':
98       stat_info.fProcessState |= eProcessStatePaging;
99       break;
100     }
101 
102     return true;
103   }
104 
105   return false;
106 }
107 
108 static void GetLinuxProcessUserAndGroup(lldb::pid_t pid,
109                                         ProcessInstanceInfo &process_info,
110                                         lldb::pid_t &tracerpid) {
111   tracerpid = 0;
112   uint32_t rUid = UINT32_MAX; // Real User ID
113   uint32_t eUid = UINT32_MAX; // Effective User ID
114   uint32_t rGid = UINT32_MAX; // Real Group ID
115   uint32_t eGid = UINT32_MAX; // Effective Group ID
116 
117   // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid:
118   // fields.
119   lldb::DataBufferSP buf_sp =
120       process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "status");
121 
122   static const char uid_token[] = "Uid:";
123   char *buf_uid = strstr((char *)buf_sp->GetBytes(), uid_token);
124   if (buf_uid) {
125     // Real, effective, saved set, and file system UIDs. Read the first two.
126     buf_uid += sizeof(uid_token);
127     rUid = strtol(buf_uid, &buf_uid, 10);
128     eUid = strtol(buf_uid, &buf_uid, 10);
129   }
130 
131   static const char gid_token[] = "Gid:";
132   char *buf_gid = strstr((char *)buf_sp->GetBytes(), gid_token);
133   if (buf_gid) {
134     // Real, effective, saved set, and file system GIDs. Read the first two.
135     buf_gid += sizeof(gid_token);
136     rGid = strtol(buf_gid, &buf_gid, 10);
137     eGid = strtol(buf_gid, &buf_gid, 10);
138   }
139 
140   static const char tracerpid_token[] = "TracerPid:";
141   char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token);
142   if (buf_tracerpid) {
143     // Tracer PID. 0 if we're not being debugged.
144     buf_tracerpid += sizeof(tracerpid_token);
145     tracerpid = strtol(buf_tracerpid, &buf_tracerpid, 10);
146   }
147 
148   process_info.SetUserID(rUid);
149   process_info.SetEffectiveUserID(eUid);
150   process_info.SetGroupID(rGid);
151   process_info.SetEffectiveGroupID(eGid);
152 }
153 
154 lldb::DataBufferSP Host::GetAuxvData(lldb_private::Process *process) {
155   return process_linux::ProcFileReader::ReadIntoDataBuffer(process->GetID(),
156                                                            "auxv");
157 }
158 
159 lldb::DataBufferSP Host::GetAuxvData(lldb::pid_t pid) {
160   return process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "auxv");
161 }
162 
163 static bool IsDirNumeric(const char *dname) {
164   for (; *dname; dname++) {
165     if (!isdigit(*dname))
166       return false;
167   }
168   return true;
169 }
170 
171 uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
172                              ProcessInstanceInfoList &process_infos) {
173   static const char procdir[] = "/proc/";
174 
175   DIR *dirproc = opendir(procdir);
176   if (dirproc) {
177     struct dirent *direntry = NULL;
178     const uid_t our_uid = getuid();
179     const lldb::pid_t our_pid = getpid();
180     bool all_users = match_info.GetMatchAllUsers();
181 
182     while ((direntry = readdir(dirproc)) != NULL) {
183       if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name))
184         continue;
185 
186       lldb::pid_t pid = atoi(direntry->d_name);
187 
188       // Skip this process.
189       if (pid == our_pid)
190         continue;
191 
192       lldb::pid_t tracerpid;
193       ProcessStatInfo stat_info;
194       ProcessInstanceInfo process_info;
195 
196       if (!GetProcessAndStatInfo(pid, process_info, stat_info, tracerpid))
197         continue;
198 
199       // Skip if process is being debugged.
200       if (tracerpid != 0)
201         continue;
202 
203       // Skip zombies.
204       if (stat_info.fProcessState & eProcessStateZombie)
205         continue;
206 
207       // Check for user match if we're not matching all users and not running as
208       // root.
209       if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
210         continue;
211 
212       if (match_info.Matches(process_info)) {
213         process_infos.Append(process_info);
214       }
215     }
216 
217     closedir(dirproc);
218   }
219 
220   return process_infos.GetSize();
221 }
222 
223 bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) {
224   bool tids_changed = false;
225   static const char procdir[] = "/proc/";
226   static const char taskdir[] = "/task/";
227   std::string process_task_dir = procdir + llvm::to_string(pid) + taskdir;
228   DIR *dirproc = opendir(process_task_dir.c_str());
229 
230   if (dirproc) {
231     struct dirent *direntry = NULL;
232     while ((direntry = readdir(dirproc)) != NULL) {
233       if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name))
234         continue;
235 
236       lldb::tid_t tid = atoi(direntry->d_name);
237       TidMap::iterator it = tids_to_attach.find(tid);
238       if (it == tids_to_attach.end()) {
239         tids_to_attach.insert(TidPair(tid, false));
240         tids_changed = true;
241       }
242     }
243     closedir(dirproc);
244   }
245 
246   return tids_changed;
247 }
248 
249 static bool GetELFProcessCPUType(const char *exe_path,
250                                  ProcessInstanceInfo &process_info) {
251   // Clear the architecture.
252   process_info.GetArchitecture().Clear();
253 
254   ModuleSpecList specs;
255   FileSpec filespec(exe_path, false);
256   const size_t num_specs =
257       ObjectFile::GetModuleSpecifications(filespec, 0, 0, specs);
258   // GetModuleSpecifications() could fail if the executable has been deleted or
259   // is locked.
260   // But it shouldn't return more than 1 architecture.
261   assert(num_specs <= 1 && "Linux plugin supports only a single architecture");
262   if (num_specs == 1) {
263     ModuleSpec module_spec;
264     if (specs.GetModuleSpecAtIndex(0, module_spec) &&
265         module_spec.GetArchitecture().IsValid()) {
266       process_info.GetArchitecture() = module_spec.GetArchitecture();
267       return true;
268     }
269   }
270   return false;
271 }
272 
273 static bool GetProcessAndStatInfo(lldb::pid_t pid,
274                                   ProcessInstanceInfo &process_info,
275                                   ProcessStatInfo &stat_info,
276                                   lldb::pid_t &tracerpid) {
277   tracerpid = 0;
278   process_info.Clear();
279   ::memset(&stat_info, 0, sizeof(stat_info));
280   stat_info.ppid = LLDB_INVALID_PROCESS_ID;
281 
282   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
283 
284   // Use special code here because proc/[pid]/exe is a symbolic link.
285   char link_path[PATH_MAX];
286   char exe_path[PATH_MAX] = "";
287   if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0) {
288     if (log)
289       log->Printf("%s: failed to sprintf pid %" PRIu64, __FUNCTION__, pid);
290     return false;
291   }
292 
293   ssize_t len = readlink(link_path, exe_path, sizeof(exe_path) - 1);
294   if (len <= 0) {
295     if (log)
296       log->Printf("%s: failed to read link %s: %s", __FUNCTION__, link_path,
297                   strerror(errno));
298     return false;
299   }
300 
301   // readlink does not append a null byte.
302   exe_path[len] = 0;
303 
304   // If the binary has been deleted, the link name has " (deleted)" appended.
305   //  Remove if there.
306   static const ssize_t deleted_len = strlen(" (deleted)");
307   if (len > deleted_len &&
308       !strcmp(exe_path + len - deleted_len, " (deleted)")) {
309     exe_path[len - deleted_len] = 0;
310   } else {
311     GetELFProcessCPUType(exe_path, process_info);
312   }
313 
314   process_info.SetProcessID(pid);
315   process_info.GetExecutableFile().SetFile(exe_path, false);
316   process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture());
317 
318   lldb::DataBufferSP buf_sp;
319 
320   // Get the process environment.
321   buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "environ");
322   Args &info_env = process_info.GetEnvironmentEntries();
323   char *next_var = (char *)buf_sp->GetBytes();
324   char *end_buf = next_var + buf_sp->GetByteSize();
325   while (next_var < end_buf && 0 != *next_var) {
326     info_env.AppendArgument(llvm::StringRef(next_var));
327     next_var += strlen(next_var) + 1;
328   }
329 
330   // Get the command line used to start the process.
331   buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "cmdline");
332 
333   // Grab Arg0 first, if there is one.
334   char *cmd = (char *)buf_sp->GetBytes();
335   if (cmd) {
336     process_info.SetArg0(cmd);
337 
338     // Now process any remaining arguments.
339     Args &info_args = process_info.GetArguments();
340     char *next_arg = cmd + strlen(cmd) + 1;
341     end_buf = cmd + buf_sp->GetByteSize();
342     while (next_arg < end_buf && 0 != *next_arg) {
343       info_args.AppendArgument(llvm::StringRef(next_arg));
344       next_arg += strlen(next_arg) + 1;
345     }
346   }
347 
348   // Read /proc/$PID/stat to get our parent pid.
349   if (ReadProcPseudoFileStat(pid, stat_info)) {
350     process_info.SetParentProcessID(stat_info.ppid);
351   }
352 
353   // Get User and Group IDs and get tracer pid.
354   GetLinuxProcessUserAndGroup(pid, process_info, tracerpid);
355 
356   return true;
357 }
358 
359 bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
360   lldb::pid_t tracerpid;
361   ProcessStatInfo stat_info;
362 
363   return GetProcessAndStatInfo(pid, process_info, stat_info, tracerpid);
364 }
365 
366 size_t Host::GetEnvironment(StringList &env) {
367   char **host_env = environ;
368   char *env_entry;
369   size_t i;
370   for (i = 0; (env_entry = host_env[i]) != NULL; ++i)
371     env.AppendString(env_entry);
372   return i;
373 }
374 
375 Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
376   return Error("unimplemented");
377 }
378