1 //===-- source/Host/freebsd/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 <dlfcn.h>
13 #include <execinfo.h>
14 #include <sys/types.h>
15 #include <sys/user.h>
16 #include <sys/utsname.h>
17 #include <sys/sysctl.h>
18 #include <sys/proc.h>
19 
20 #include <sys/ptrace.h>
21 #include <sys/exec.h>
22 #include <machine/elf.h>
23 
24 // C++ Includes
25 // Other libraries and framework includes
26 // Project includes
27 #include "lldb/Core/Error.h"
28 #include "lldb/Host/Endian.h"
29 #include "lldb/Host/Host.h"
30 #include "lldb/Core/Module.h"
31 #include "lldb/Core/DataExtractor.h"
32 #include "lldb/Core/StreamFile.h"
33 #include "lldb/Core/StreamString.h"
34 #include "lldb/Core/Log.h"
35 #include "lldb/Target/Process.h"
36 #include "lldb/Target/Platform.h"
37 
38 #include "lldb/Core/DataBufferHeap.h"
39 #include "lldb/Core/DataExtractor.h"
40 #include "lldb/Utility/CleanUp.h"
41 
42 #include "llvm/Support/Host.h"
43 
44 
45 extern "C" {
46     extern char **environ;
47 }
48 
49 using namespace lldb;
50 using namespace lldb_private;
51 
52 class FreeBSDThread
53 {
54 public:
55     FreeBSDThread(const char *thread_name)
56     {
57         Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
58     }
59     static void PThreadDestructor (void *v)
60     {
61         delete (FreeBSDThread*)v;
62     }
63 };
64 
65 static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
66 static pthread_key_t g_thread_create_key = 0;
67 
68 static void
69 InitThreadCreated()
70 {
71     ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor);
72 }
73 
74 void
75 Host::ThreadCreated (const char *thread_name)
76 {
77     ::pthread_once (&g_thread_create_once, InitThreadCreated);
78     if (g_thread_create_key)
79     {
80         ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name));
81     }
82 
83     Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16);
84 }
85 
86 std::string
87 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
88 {
89     struct kinfo_proc *kp = nullptr, *nkp;
90     size_t len = 0;
91     int error;
92     int name[4] = {
93         CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)pid
94     };
95 
96     while (1) {
97         error = sysctl(name, 4, kp, &len, nullptr, 0);
98         if (kp == nullptr || (error != 0 && errno == ENOMEM)) {
99             // Add extra space in case threads are added before next call.
100             len += sizeof(*kp) + len / 10;
101             nkp = (struct kinfo_proc *)realloc(kp, len);
102             if (nkp == nullptr)
103             {
104                 free(kp);
105                 return std::string();
106             }
107             kp = nkp;
108             continue;
109         }
110         if (error != 0)
111             len = 0;
112         break;
113     }
114 
115     std::string thread_name;
116     for (size_t i = 0; i < len / sizeof(*kp); i++) {
117         if (kp[i].ki_tid == (int)tid) {
118             thread_name = kp[i].ki_tdname;
119             break;
120         }
121     }
122     free(kp);
123     return thread_name;
124 }
125 
126 void
127 Host::Backtrace (Stream &strm, uint32_t max_frames)
128 {
129     char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX";
130     int backtrace_fd = ::mkstemp (backtrace_path);
131     if (backtrace_fd != -1)
132     {
133         std::vector<void *> frame_buffer (max_frames, NULL);
134         int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
135         ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
136 
137         const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
138 
139         if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
140         {
141             char *buffer = (char *)::malloc (buffer_size);
142             if (buffer)
143             {
144                 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size);
145                 if (bytes_read > 0)
146                     strm.Write(buffer, bytes_read);
147                 ::free (buffer);
148             }
149         }
150         ::close (backtrace_fd);
151         ::unlink (backtrace_path);
152     }
153 }
154 
155 size_t
156 Host::GetEnvironment (StringList &env)
157 {
158     char *v;
159     char **var = environ;
160     for (; var != NULL && *var != NULL; ++var)
161     {
162         v = strchr(*var, (int)'-');
163         if (v == NULL)
164             continue;
165         env.AppendString(v);
166     }
167     return env.GetSize();
168 }
169 
170 bool
171 Host::GetOSVersion(uint32_t &major,
172                    uint32_t &minor,
173                    uint32_t &update)
174 {
175     struct utsname un;
176 
177     ::memset(&un, 0, sizeof(utsname));
178     if (uname(&un) < 0)
179         return false;
180 
181     int status = sscanf(un.release, "%u.%u", &major, &minor);
182     return status == 2;
183 }
184 
185 bool
186 Host::GetOSBuildString (std::string &s)
187 {
188     int mib[2] = { CTL_KERN, KERN_OSREV };
189     char osrev_str[12];
190     uint32_t osrev = 0;
191     size_t osrev_len = sizeof(osrev);
192 
193     if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
194     {
195         ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
196         s.assign (osrev_str);
197         return true;
198     }
199 
200     s.clear();
201     return false;
202 }
203 
204 bool
205 Host::GetOSKernelDescription (std::string &s)
206 {
207     struct utsname un;
208 
209     ::memset(&un, 0, sizeof(utsname));
210     s.clear();
211 
212     if (uname(&un) < 0)
213     return false;
214 
215     s.assign (un.version);
216 
217     return true;
218 }
219 
220 static bool
221 GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
222                       ProcessInstanceInfo &process_info)
223 {
224     if (process_info.ProcessIDIsValid())
225     {
226         int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
227 
228         char arg_data[8192];
229         size_t arg_data_size = sizeof(arg_data);
230         if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
231         {
232             DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
233             lldb::offset_t offset = 0;
234             const char *cstr;
235 
236             cstr = data.GetCStr (&offset);
237             if (cstr)
238             {
239                 process_info.GetExecutableFile().SetFile(cstr, false);
240 
241                 if (!(match_info_ptr == NULL ||
242                     NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
243                                  match_info_ptr->GetNameMatchType(),
244                                  match_info_ptr->GetProcessInfo().GetName())))
245                     return false;
246 
247                 Args &proc_args = process_info.GetArguments();
248                 while (1)
249                 {
250                     const uint8_t *p = data.PeekData(offset, 1);
251                     while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
252                     {
253                         ++offset;
254                         p = data.PeekData(offset, 1);
255                     }
256                     if (p == NULL || offset >= arg_data_size)
257                         return true;
258 
259                     cstr = data.GetCStr(&offset);
260                     if (cstr)
261                         proc_args.AppendArgument(cstr);
262                     else
263                         return true;
264                 }
265             }
266         }
267     }
268     return false;
269 }
270 
271 static bool
272 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
273 {
274     if (process_info.ProcessIDIsValid())
275     {
276         process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
277         return true;
278     }
279     process_info.GetArchitecture().Clear();
280     return false;
281 }
282 
283 static bool
284 GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
285 {
286     struct kinfo_proc proc_kinfo;
287     size_t proc_kinfo_size;
288 
289     if (process_info.ProcessIDIsValid())
290     {
291         int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
292             (int)process_info.GetProcessID() };
293         proc_kinfo_size = sizeof(struct kinfo_proc);
294 
295         if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
296         {
297             if (proc_kinfo_size > 0)
298             {
299                 process_info.SetParentProcessID (proc_kinfo.ki_ppid);
300                 process_info.SetUserID (proc_kinfo.ki_ruid);
301                 process_info.SetGroupID (proc_kinfo.ki_rgid);
302                 process_info.SetEffectiveUserID (proc_kinfo.ki_uid);
303                 if (proc_kinfo.ki_ngroups > 0)
304                     process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]);
305                 else
306                     process_info.SetEffectiveGroupID (UINT32_MAX);
307                 return true;
308             }
309         }
310     }
311     process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
312     process_info.SetUserID (UINT32_MAX);
313     process_info.SetGroupID (UINT32_MAX);
314     process_info.SetEffectiveUserID (UINT32_MAX);
315     process_info.SetEffectiveGroupID (UINT32_MAX);
316     return false;
317 }
318 
319 uint32_t
320 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
321 {
322     std::vector<struct kinfo_proc> kinfos;
323 
324     int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
325 
326     size_t pid_data_size = 0;
327     if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
328         return 0;
329 
330     // Add a few extra in case a few more show up
331     const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10;
332 
333     kinfos.resize (estimated_pid_count);
334     pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
335 
336     if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
337         return 0;
338 
339     const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
340 
341     bool all_users = match_info.GetMatchAllUsers();
342     const ::pid_t our_pid = getpid();
343     const uid_t our_uid = getuid();
344     for (size_t i = 0; i < actual_pid_count; i++)
345     {
346         const struct kinfo_proc &kinfo = kinfos[i];
347         const bool kinfo_user_matches = (all_users ||
348                                          (kinfo.ki_ruid == our_uid) ||
349                                          // Special case, if lldb is being run as root we can attach to anything.
350                                          (our_uid == 0)
351                                          );
352 
353         if (kinfo_user_matches == false      || // Make sure the user is acceptable
354             kinfo.ki_pid == our_pid          || // Skip this process
355             kinfo.ki_pid == 0                || // Skip kernel (kernel pid is zero)
356             kinfo.ki_stat == SZOMB    || // Zombies are bad, they like brains...
357             kinfo.ki_flag & P_TRACED  || // Being debugged?
358             kinfo.ki_flag & P_WEXIT)     // Working on exiting
359             continue;
360 
361         // Every thread is a process in FreeBSD, but all the threads of a single process
362         // have the same pid. Do not store the process info in the result list if a process
363         // with given identifier is already registered there.
364         bool already_registered = false;
365         for (uint32_t pi = 0;
366              !already_registered &&
367              (const int)kinfo.ki_numthreads > 1 &&
368              pi < (const uint32_t)process_infos.GetSize(); pi++)
369             already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid);
370 
371         if (already_registered)
372             continue;
373 
374         ProcessInstanceInfo process_info;
375         process_info.SetProcessID (kinfo.ki_pid);
376         process_info.SetParentProcessID (kinfo.ki_ppid);
377         process_info.SetUserID (kinfo.ki_ruid);
378         process_info.SetGroupID (kinfo.ki_rgid);
379         process_info.SetEffectiveUserID (kinfo.ki_svuid);
380         process_info.SetEffectiveGroupID (kinfo.ki_svgid);
381 
382         // Make sure our info matches before we go fetch the name and cpu type
383         if (match_info.Matches (process_info) &&
384             GetFreeBSDProcessArgs (&match_info, process_info))
385         {
386             GetFreeBSDProcessCPUType (process_info);
387             if (match_info.Matches (process_info))
388                 process_infos.Append (process_info);
389         }
390     }
391 
392     return process_infos.GetSize();
393 }
394 
395 bool
396 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
397 {
398     process_info.SetProcessID(pid);
399 
400     if (GetFreeBSDProcessArgs(NULL, process_info))
401     {
402         // should use libprocstat instead of going right into sysctl?
403         GetFreeBSDProcessCPUType(process_info);
404         GetFreeBSDProcessUserAndGroup(process_info);
405         return true;
406     }
407 
408     process_info.Clear();
409     return false;
410 }
411 
412 lldb::DataBufferSP
413 Host::GetAuxvData(lldb_private::Process *process)
414 {
415    int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
416    void *ps_strings_addr, *auxv_addr;
417    size_t ps_strings_size = sizeof(void *);
418    Elf_Auxinfo aux_info[AT_COUNT];
419    struct ps_strings ps_strings;
420    struct ptrace_io_desc pid;
421    DataBufferSP buf_sp;
422    std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
423 
424    if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
425            pid.piod_op = PIOD_READ_D;
426            pid.piod_addr = &ps_strings;
427            pid.piod_offs = ps_strings_addr;
428            pid.piod_len = sizeof(ps_strings);
429            if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
430                    perror("failed to fetch ps_strings");
431                    buf_ap.release();
432                    goto done;
433            }
434 
435            auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
436 
437            pid.piod_addr = aux_info;
438            pid.piod_offs = auxv_addr;
439            pid.piod_len = sizeof(aux_info);
440            if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
441                    perror("failed to fetch aux_info");
442                    buf_ap.release();
443                    goto done;
444            }
445            memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
446            buf_sp.reset(buf_ap.release());
447    } else {
448            perror("sysctl failed on ps_strings");
449    }
450 
451    done:
452    return buf_sp;
453 }
454