]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / source / Host / freebsd / Host.cpp
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     std::string thread_name;
90     return thread_name;
91 }
92
93 void
94 Host::Backtrace (Stream &strm, uint32_t max_frames)
95 {
96     char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX";
97     int backtrace_fd = ::mkstemp (backtrace_path);
98     if (backtrace_fd != -1)
99     {
100         std::vector<void *> frame_buffer (max_frames, NULL);
101         int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
102         ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
103
104         const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
105
106         if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
107         {
108             char *buffer = (char *)::malloc (buffer_size);
109             if (buffer)
110             {
111                 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size);
112                 if (bytes_read > 0)
113                     strm.Write(buffer, bytes_read);
114                 ::free (buffer);
115             }
116         }
117         ::close (backtrace_fd);
118         ::unlink (backtrace_path);
119     }
120 }
121
122 size_t
123 Host::GetEnvironment (StringList &env)
124 {
125     char *v;
126     char **var = environ;
127     for (; var != NULL && *var != NULL; ++var)
128     {
129         v = strchr(*var, (int)'-');
130         if (v == NULL)
131             continue;
132         env.AppendString(v);
133     }
134     return env.GetSize();
135 }
136
137 bool
138 Host::GetOSVersion(uint32_t &major,
139                    uint32_t &minor,
140                    uint32_t &update)
141 {
142     struct utsname un;
143
144     ::memset(&un, 0, sizeof(utsname));
145     if (uname(&un) < 0)
146         return false;
147
148     int status = sscanf(un.release, "%u.%u", &major, &minor);
149     return status == 2;
150 }
151
152 bool
153 Host::GetOSBuildString (std::string &s)
154 {
155     int mib[2] = { CTL_KERN, KERN_OSREV };
156     char osrev_str[12];
157     uint32_t osrev = 0;
158     size_t osrev_len = sizeof(osrev);
159
160     if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
161     {
162         ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
163         s.assign (osrev_str);
164         return true;
165     }
166
167     s.clear();
168     return false;
169 }
170
171 bool
172 Host::GetOSKernelDescription (std::string &s)
173 {
174     struct utsname un;
175
176     ::memset(&un, 0, sizeof(utsname));
177     s.clear();
178
179     if (uname(&un) < 0)
180     return false;
181
182     s.assign (un.version);
183
184     return true;
185 }
186
187 static bool
188 GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
189                       ProcessInstanceInfo &process_info)
190 {
191     if (process_info.ProcessIDIsValid())
192     {
193         int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
194
195         char arg_data[8192];
196         size_t arg_data_size = sizeof(arg_data);
197         if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
198         {
199             DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
200             lldb::offset_t offset = 0;
201             const char *cstr;
202
203             cstr = data.GetCStr (&offset);
204             if (cstr)
205             {
206                 process_info.GetExecutableFile().SetFile(cstr, false);
207
208                 if (!(match_info_ptr == NULL ||
209                     NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
210                                  match_info_ptr->GetNameMatchType(),
211                                  match_info_ptr->GetProcessInfo().GetName())))
212                     return false;
213
214                 Args &proc_args = process_info.GetArguments();
215                 while (1)
216                 {
217                     const uint8_t *p = data.PeekData(offset, 1);
218                     while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
219                     {
220                         ++offset;
221                         p = data.PeekData(offset, 1);
222                     }
223                     if (p == NULL || offset >= arg_data_size)
224                         return true;
225
226                     cstr = data.GetCStr(&offset);
227                     if (cstr)
228                         proc_args.AppendArgument(cstr);
229                     else
230                         return true;
231                 }
232             }
233         }
234     }
235     return false;
236 }
237
238 static bool
239 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
240 {
241     if (process_info.ProcessIDIsValid())
242     {
243         process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
244         return true;
245     }
246     process_info.GetArchitecture().Clear();
247     return false;
248 }
249
250 static bool
251 GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
252 {
253     struct kinfo_proc proc_kinfo;
254     size_t proc_kinfo_size;
255
256     if (process_info.ProcessIDIsValid())
257     {
258         int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
259             (int)process_info.GetProcessID() };
260         proc_kinfo_size = sizeof(struct kinfo_proc);
261
262         if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
263         {
264             if (proc_kinfo_size > 0)
265             {
266                 process_info.SetParentProcessID (proc_kinfo.ki_ppid);
267                 process_info.SetUserID (proc_kinfo.ki_ruid);
268                 process_info.SetGroupID (proc_kinfo.ki_rgid);
269                 process_info.SetEffectiveUserID (proc_kinfo.ki_uid);
270                 if (proc_kinfo.ki_ngroups > 0)
271                     process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]);
272                 else
273                     process_info.SetEffectiveGroupID (UINT32_MAX);
274                 return true;
275             }
276         }
277     }
278     process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
279     process_info.SetUserID (UINT32_MAX);
280     process_info.SetGroupID (UINT32_MAX);
281     process_info.SetEffectiveUserID (UINT32_MAX);
282     process_info.SetEffectiveGroupID (UINT32_MAX);
283     return false;
284 }
285
286 uint32_t
287 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
288 {
289     std::vector<struct kinfo_proc> kinfos;
290
291     int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
292
293     size_t pid_data_size = 0;
294     if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
295         return 0;
296
297     // Add a few extra in case a few more show up
298     const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10;
299
300     kinfos.resize (estimated_pid_count);
301     pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
302
303     if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
304         return 0;
305
306     const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
307
308     bool all_users = match_info.GetMatchAllUsers();
309     const lldb::pid_t our_pid = getpid();
310     const uid_t our_uid = getuid();
311     for (int i = 0; i < actual_pid_count; i++)
312     {
313         const struct kinfo_proc &kinfo = kinfos[i];
314         const bool kinfo_user_matches = (all_users ||
315                                          (kinfo.ki_ruid == our_uid) ||
316                                          // Special case, if lldb is being run as root we can attach to anything.
317                                          (our_uid == 0)
318                                          );
319
320         if (kinfo_user_matches == false      || // Make sure the user is acceptable
321             kinfo.ki_pid == our_pid          || // Skip this process
322             kinfo.ki_pid == 0                || // Skip kernel (kernel pid is zero)
323             kinfo.ki_stat == SZOMB    || // Zombies are bad, they like brains...
324             kinfo.ki_flag & P_TRACED  || // Being debugged?
325             kinfo.ki_flag & P_WEXIT)     // Working on exiting
326             continue;
327
328         // Every thread is a process in FreeBSD, but all the threads of a single process
329         // have the same pid. Do not store the process info in the result list if a process
330         // with given identifier is already registered there.
331         bool already_registered = false;
332         for (uint32_t pi = 0;
333              !already_registered &&
334              (const int)kinfo.ki_numthreads > 1 &&
335              pi < (const uint32_t)process_infos.GetSize(); pi++)
336             already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid);
337
338         if (already_registered)
339             continue;
340
341         ProcessInstanceInfo process_info;
342         process_info.SetProcessID (kinfo.ki_pid);
343         process_info.SetParentProcessID (kinfo.ki_ppid);
344         process_info.SetUserID (kinfo.ki_ruid);
345         process_info.SetGroupID (kinfo.ki_rgid);
346         process_info.SetEffectiveUserID (kinfo.ki_svuid);
347         process_info.SetEffectiveGroupID (kinfo.ki_svgid);
348
349         // Make sure our info matches before we go fetch the name and cpu type
350         if (match_info.Matches (process_info) &&
351             GetFreeBSDProcessArgs (&match_info, process_info))
352         {
353             GetFreeBSDProcessCPUType (process_info);
354             if (match_info.Matches (process_info))
355                 process_infos.Append (process_info);
356         }
357     }
358
359     return process_infos.GetSize();
360 }
361
362 bool
363 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
364 {
365     process_info.SetProcessID(pid);
366
367     if (GetFreeBSDProcessArgs(NULL, process_info))
368     {
369         // should use libprocstat instead of going right into sysctl?
370         GetFreeBSDProcessCPUType(process_info);
371         GetFreeBSDProcessUserAndGroup(process_info);
372         return true;
373     }
374
375     process_info.Clear();
376     return false;
377 }
378
379 lldb::DataBufferSP
380 Host::GetAuxvData(lldb_private::Process *process)
381 {
382    int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
383    void *ps_strings_addr, *auxv_addr;
384    size_t ps_strings_size = sizeof(void *);
385    Elf_Auxinfo aux_info[AT_COUNT];
386    struct ps_strings ps_strings;
387    struct ptrace_io_desc pid;
388    DataBufferSP buf_sp;
389    std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
390
391    if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
392            pid.piod_op = PIOD_READ_D;
393            pid.piod_addr = &ps_strings;
394            pid.piod_offs = ps_strings_addr;
395            pid.piod_len = sizeof(ps_strings);
396            if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
397                    perror("failed to fetch ps_strings");
398                    buf_ap.release();
399                    goto done;
400            }
401
402            auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
403
404            pid.piod_addr = aux_info;
405            pid.piod_offs = auxv_addr;
406            pid.piod_len = sizeof(aux_info);
407            if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
408                    perror("failed to fetch aux_info");
409                    buf_ap.release();
410                    goto done;
411            }
412            memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
413            buf_sp.reset(buf_ap.release());
414    } else {
415            perror("sysctl failed on ps_strings");
416    }
417
418    done:
419    return buf_sp;
420 }