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:
FreeBSDThread(const char * thread_name)55 FreeBSDThread(const char *thread_name)
56 {
57 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
58 }
PThreadDestructor(void * v)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
InitThreadCreated()69 InitThreadCreated()
70 {
71 ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor);
72 }
73
74 void
ThreadCreated(const char * thread_name)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
GetThreadName(lldb::pid_t pid,lldb::tid_t tid)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
Backtrace(Stream & strm,uint32_t max_frames)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
GetEnvironment(StringList & env)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
GetOSVersion(uint32_t & major,uint32_t & minor,uint32_t & update)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
GetOSBuildString(std::string & s)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
GetOSKernelDescription(std::string & s)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
GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch * match_info_ptr,ProcessInstanceInfo & process_info)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
GetFreeBSDProcessCPUType(ProcessInstanceInfo & process_info)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
GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo & process_info)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
FindProcesses(const ProcessInstanceInfoMatch & match_info,ProcessInstanceInfoList & process_infos)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
GetProcessInfo(lldb::pid_t pid,ProcessInstanceInfo & process_info)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
GetAuxvData(lldb_private::Process * process)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 }
421