1 //===-- source/Host/freebsd/Host.cpp ------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
14 #include <sys/types.h>
16 #include <sys/utsname.h>
17 #include <sys/sysctl.h>
20 #include <sys/ptrace.h>
22 #include <machine/elf.h>
25 // Other libraries and framework 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"
38 #include "lldb/Core/DataBufferHeap.h"
39 #include "lldb/Core/DataExtractor.h"
40 #include "lldb/Utility/CleanUp.h"
42 #include "llvm/Support/Host.h"
46 extern char **environ;
50 using namespace lldb_private;
55 FreeBSDThread(const char *thread_name)
57 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
59 static void PThreadDestructor (void *v)
61 delete (FreeBSDThread*)v;
65 static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
66 static pthread_key_t g_thread_create_key = 0;
71 ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor);
75 Host::ThreadCreated (const char *thread_name)
77 ::pthread_once (&g_thread_create_once, InitThreadCreated);
78 if (g_thread_create_key)
80 ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name));
83 Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16);
87 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
89 std::string thread_name;
94 Host::Backtrace (Stream &strm, uint32_t max_frames)
96 char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX";
97 int backtrace_fd = ::mkstemp (backtrace_path);
98 if (backtrace_fd != -1)
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);
104 const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
106 if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
108 char *buffer = (char *)::malloc (buffer_size);
111 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size);
113 strm.Write(buffer, bytes_read);
117 ::close (backtrace_fd);
118 ::unlink (backtrace_path);
123 Host::GetEnvironment (StringList &env)
126 char **var = environ;
127 for (; var != NULL && *var != NULL; ++var)
129 v = strchr(*var, (int)'-');
134 return env.GetSize();
138 Host::GetOSVersion(uint32_t &major,
144 ::memset(&un, 0, sizeof(utsname));
148 int status = sscanf(un.release, "%u.%u", &major, &minor);
153 Host::GetOSBuildString (std::string &s)
155 int mib[2] = { CTL_KERN, KERN_OSREV };
158 size_t osrev_len = sizeof(osrev);
160 if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
162 ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
163 s.assign (osrev_str);
172 Host::GetOSKernelDescription (std::string &s)
176 ::memset(&un, 0, sizeof(utsname));
182 s.assign (un.version);
188 GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
189 ProcessInstanceInfo &process_info)
191 if (process_info.ProcessIDIsValid())
193 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
196 size_t arg_data_size = sizeof(arg_data);
197 if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
199 DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
200 lldb::offset_t offset = 0;
203 cstr = data.GetCStr (&offset);
206 process_info.GetExecutableFile().SetFile(cstr, false);
208 if (!(match_info_ptr == NULL ||
209 NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
210 match_info_ptr->GetNameMatchType(),
211 match_info_ptr->GetProcessInfo().GetName())))
214 Args &proc_args = process_info.GetArguments();
217 const uint8_t *p = data.PeekData(offset, 1);
218 while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
221 p = data.PeekData(offset, 1);
223 if (p == NULL || offset >= arg_data_size)
226 cstr = data.GetCStr(&offset);
228 proc_args.AppendArgument(cstr);
239 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
241 if (process_info.ProcessIDIsValid())
243 process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
246 process_info.GetArchitecture().Clear();
251 GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
253 struct kinfo_proc proc_kinfo;
254 size_t proc_kinfo_size;
256 if (process_info.ProcessIDIsValid())
258 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
259 (int)process_info.GetProcessID() };
260 proc_kinfo_size = sizeof(struct kinfo_proc);
262 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
264 if (proc_kinfo_size > 0)
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]);
273 process_info.SetEffectiveGroupID (UINT32_MAX);
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);
287 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
289 std::vector<struct kinfo_proc> kinfos;
291 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
293 size_t pid_data_size = 0;
294 if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
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;
300 kinfos.resize (estimated_pid_count);
301 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
303 if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
306 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
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++)
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.
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
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);
338 if (already_registered)
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);
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))
353 GetFreeBSDProcessCPUType (process_info);
354 if (match_info.Matches (process_info))
355 process_infos.Append (process_info);
359 return process_infos.GetSize();
363 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
365 process_info.SetProcessID(pid);
367 if (GetFreeBSDProcessArgs(NULL, process_info))
369 // should use libprocstat instead of going right into sysctl?
370 GetFreeBSDProcessCPUType(process_info);
371 GetFreeBSDProcessUserAndGroup(process_info);
375 process_info.Clear();
380 Host::GetAuxvData(lldb_private::Process *process)
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;
389 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
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");
402 auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
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");
412 memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
413 buf_sp.reset(buf_ap.release());
415 perror("sysctl failed on ps_strings");