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 19 #include <sys/ptrace.h> 20 #include <sys/exec.h> 21 #include <machine/elf.h> 22 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/DataExtractor.h" 31 #include "lldb/Core/StreamFile.h" 32 #include "lldb/Core/StreamString.h" 33 #include "lldb/Target/Process.h" 34 35 #include "lldb/Core/DataBufferHeap.h" 36 #include "lldb/Core/DataExtractor.h" 37 #include "llvm/Support/Host.h" 38 39 40 extern "C" { 41 extern char **environ; 42 } 43 44 using namespace lldb; 45 using namespace lldb_private; 46 47 48 class FreeBSDThread 49 { 50 public: 51 FreeBSDThread(const char *thread_name) 52 { 53 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name); 54 } 55 static void PThreadDestructor (void *v) 56 { 57 delete (FreeBSDThread*)v; 58 } 59 }; 60 61 static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; 62 static pthread_key_t g_thread_create_key = 0; 63 64 static void 65 InitThreadCreated() 66 { 67 ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor); 68 } 69 70 void 71 Host::ThreadCreated (const char *thread_name) 72 { 73 ::pthread_once (&g_thread_create_once, InitThreadCreated); 74 if (g_thread_create_key) 75 { 76 ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name)); 77 } 78 79 Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16); 80 } 81 82 std::string 83 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) 84 { 85 std::string thread_name; 86 return thread_name; 87 } 88 89 void 90 Host::Backtrace (Stream &strm, uint32_t max_frames) 91 { 92 char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX"; 93 int backtrace_fd = ::mkstemp (backtrace_path); 94 if (backtrace_fd != -1) 95 { 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); 99 100 const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); 101 102 if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) 103 { 104 char *buffer = (char *)::malloc (buffer_size); 105 if (buffer) 106 { 107 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size); 108 if (bytes_read > 0) 109 strm.Write(buffer, bytes_read); 110 ::free (buffer); 111 } 112 } 113 ::close (backtrace_fd); 114 ::unlink (backtrace_path); 115 } 116 } 117 118 size_t 119 Host::GetEnvironment (StringList &env) 120 { 121 char *v; 122 char **var = environ; 123 for (; var != NULL && *var != NULL; ++var) { 124 v = strchr(*var, (int)'-'); 125 if (v == NULL) 126 continue; 127 env.AppendString(v); 128 } 129 return env.GetSize(); 130 } 131 132 bool 133 Host::GetOSVersion(uint32_t &major, 134 uint32_t &minor, 135 uint32_t &update) 136 { 137 struct utsname un; 138 int status; 139 140 if (uname(&un) < 0) 141 return false; 142 143 status = sscanf(un.release, "%u.%u", &major, &minor); 144 return status == 2; 145 } 146 147 Error 148 Host::LaunchProcess (ProcessLaunchInfo &launch_info) 149 { 150 Error error; 151 assert(!"Not implemented yet!!!"); 152 return error; 153 } 154 155 bool 156 Host::GetOSBuildString (std::string &s) 157 { 158 int mib[2] = { CTL_KERN, KERN_OSREV }; 159 char cstr[PATH_MAX]; 160 size_t cstr_len = sizeof(cstr); 161 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) 162 { 163 s.assign (cstr, cstr_len); 164 return true; 165 } 166 s.clear(); 167 return false; 168 } 169 170 bool 171 Host::GetOSKernelDescription (std::string &s) 172 { 173 int mib[2] = { CTL_KERN, KERN_VERSION }; 174 char cstr[PATH_MAX]; 175 size_t cstr_len = sizeof(cstr); 176 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) 177 { 178 s.assign (cstr, cstr_len); 179 return true; 180 } 181 s.clear(); 182 return false; 183 } 184 185 static bool 186 GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, 187 ProcessInstanceInfo &process_info) 188 { 189 if (process_info.ProcessIDIsValid()) { 190 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() }; 191 192 char arg_data[8192]; 193 size_t arg_data_size = sizeof(arg_data); 194 if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) 195 { 196 DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); 197 lldb::offset_t offset = 0; 198 const char *cstr; 199 200 cstr = data.GetCStr (&offset); 201 if (cstr) 202 { 203 process_info.GetExecutableFile().SetFile(cstr, false); 204 205 if (!(match_info_ptr == NULL || 206 NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), 207 match_info_ptr->GetNameMatchType(), 208 match_info_ptr->GetProcessInfo().GetName()))) 209 return false; 210 211 Args &proc_args = process_info.GetArguments(); 212 while (1) 213 { 214 const uint8_t *p = data.PeekData(offset, 1); 215 while ((p != NULL) && (*p == '\0') && offset < arg_data_size) 216 { 217 ++offset; 218 p = data.PeekData(offset, 1); 219 } 220 if (p == NULL || offset >= arg_data_size) 221 return true; 222 223 cstr = data.GetCStr(&offset); 224 if (cstr) 225 proc_args.AppendArgument(cstr); 226 else 227 return true; 228 } 229 } 230 } 231 } 232 return false; 233 } 234 235 static bool 236 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) 237 { 238 if (process_info.ProcessIDIsValid()) { 239 process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); 240 return true; 241 } 242 process_info.GetArchitecture().Clear(); 243 return false; 244 } 245 246 static bool 247 GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) 248 { 249 struct kinfo_proc proc_kinfo; 250 size_t proc_kinfo_size; 251 252 if (process_info.ProcessIDIsValid()) 253 { 254 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 255 (int)process_info.GetProcessID() }; 256 proc_kinfo_size = sizeof(struct kinfo_proc); 257 258 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) 259 { 260 if (proc_kinfo_size > 0) 261 { 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]); 268 else 269 process_info.SetEffectiveGroupID (UINT32_MAX); 270 return true; 271 } 272 } 273 } 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); 279 return false; 280 } 281 282 bool 283 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 284 { 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); 290 return true; 291 } 292 process_info.Clear(); 293 return false; 294 } 295 296 lldb::DataBufferSP 297 Host::GetAuxvData(lldb_private::Process *process) 298 { 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; 305 DataBufferSP buf_sp; 306 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); 307 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"); 315 buf_ap.release(); 316 goto done; 317 } 318 319 auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; 320 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"); 326 buf_ap.release(); 327 goto done; 328 } 329 memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); 330 buf_sp.reset(buf_ap.release()); 331 } else { 332 perror("sysctl failed on ps_strings"); 333 } 334 335 done: 336 return buf_sp; 337 } 338