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>
19 #include <sys/ptrace.h>
21 #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/DataExtractor.h"
31 #include "lldb/Core/StreamFile.h"
32 #include "lldb/Core/StreamString.h"
33 #include "lldb/Target/Process.h"
35 #include "lldb/Core/DataBufferHeap.h"
36 #include "lldb/Core/DataExtractor.h"
37 #include "llvm/Support/Host.h"
41 extern char **environ;
45 using namespace lldb_private;
51 FreeBSDThread(const char *thread_name)
53 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
55 static void PThreadDestructor (void *v)
57 delete (FreeBSDThread*)v;
61 static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
62 static pthread_key_t g_thread_create_key = 0;
67 ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor);
71 Host::ThreadCreated (const char *thread_name)
73 ::pthread_once (&g_thread_create_once, InitThreadCreated);
74 if (g_thread_create_key)
76 ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name));
79 Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16);
83 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
85 std::string thread_name;
90 Host::Backtrace (Stream &strm, uint32_t max_frames)
92 char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX";
93 int backtrace_fd = ::mkstemp (backtrace_path);
94 if (backtrace_fd != -1)
96 std::vector<void *> frame_buffer (max_frames, NULL);
97 int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
98 ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
100 const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
102 if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
104 char *buffer = (char *)::malloc (buffer_size);
107 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size);
109 strm.Write(buffer, bytes_read);
113 ::close (backtrace_fd);
114 ::unlink (backtrace_path);
119 Host::GetEnvironment (StringList &env)
122 char **var = environ;
123 for (; var != NULL && *var != NULL; ++var) {
124 v = strchr(*var, (int)'-');
129 return env.GetSize();
133 Host::GetOSVersion(uint32_t &major,
143 status = sscanf(un.release, "%u.%u", &major, &minor);
148 Host::LaunchProcess (ProcessLaunchInfo &launch_info)
151 assert(!"Not implemented yet!!!");
156 Host::GetOSBuildString (std::string &s)
158 int mib[2] = { CTL_KERN, KERN_OSREV };
160 size_t cstr_len = sizeof(cstr);
161 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
163 s.assign (cstr, cstr_len);
171 Host::GetOSKernelDescription (std::string &s)
173 int mib[2] = { CTL_KERN, KERN_VERSION };
175 size_t cstr_len = sizeof(cstr);
176 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
178 s.assign (cstr, cstr_len);
186 GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
187 ProcessInstanceInfo &process_info)
189 if (process_info.ProcessIDIsValid()) {
190 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
193 size_t arg_data_size = sizeof(arg_data);
194 if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
196 DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
197 lldb::offset_t offset = 0;
200 cstr = data.GetCStr (&offset);
203 process_info.GetExecutableFile().SetFile(cstr, false);
205 if (!(match_info_ptr == NULL ||
206 NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
207 match_info_ptr->GetNameMatchType(),
208 match_info_ptr->GetProcessInfo().GetName())))
211 Args &proc_args = process_info.GetArguments();
214 const uint8_t *p = data.PeekData(offset, 1);
215 while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
218 p = data.PeekData(offset, 1);
220 if (p == NULL || offset >= arg_data_size)
223 cstr = data.GetCStr(&offset);
225 proc_args.AppendArgument(cstr);
236 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
238 if (process_info.ProcessIDIsValid()) {
239 process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
242 process_info.GetArchitecture().Clear();
247 GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
249 struct kinfo_proc proc_kinfo;
250 size_t proc_kinfo_size;
252 if (process_info.ProcessIDIsValid())
254 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
255 (int)process_info.GetProcessID() };
256 proc_kinfo_size = sizeof(struct kinfo_proc);
258 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
260 if (proc_kinfo_size > 0)
262 process_info.SetParentProcessID (proc_kinfo.ki_ppid);
263 process_info.SetUserID (proc_kinfo.ki_ruid);
264 process_info.SetGroupID (proc_kinfo.ki_rgid);
265 process_info.SetEffectiveUserID (proc_kinfo.ki_uid);
266 if (proc_kinfo.ki_ngroups > 0)
267 process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]);
269 process_info.SetEffectiveGroupID (UINT32_MAX);
274 process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
275 process_info.SetUserID (UINT32_MAX);
276 process_info.SetGroupID (UINT32_MAX);
277 process_info.SetEffectiveUserID (UINT32_MAX);
278 process_info.SetEffectiveGroupID (UINT32_MAX);
283 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
285 process_info.SetProcessID(pid);
286 if (GetFreeBSDProcessArgs(NULL, process_info)) {
287 // should use libprocstat instead of going right into sysctl?
288 GetFreeBSDProcessCPUType(process_info);
289 GetFreeBSDProcessUserAndGroup(process_info);
292 process_info.Clear();
297 Host::GetAuxvData(lldb_private::Process *process)
299 int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
300 void *ps_strings_addr, *auxv_addr;
301 size_t ps_strings_size = sizeof(void *);
302 Elf_Auxinfo aux_info[AT_COUNT];
303 struct ps_strings ps_strings;
304 struct ptrace_io_desc pid;
306 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
308 if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
309 pid.piod_op = PIOD_READ_D;
310 pid.piod_addr = &ps_strings;
311 pid.piod_offs = ps_strings_addr;
312 pid.piod_len = sizeof(ps_strings);
313 if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
314 perror("failed to fetch ps_strings");
319 auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
321 pid.piod_addr = aux_info;
322 pid.piod_offs = auxv_addr;
323 pid.piod_len = sizeof(aux_info);
324 if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
325 perror("failed to fetch aux_info");
329 memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
330 buf_sp.reset(buf_ap.release());
332 perror("sysctl failed on ps_strings");