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