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