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