Host.cpp revision de9eadc2e60fe8b5df20e9cf93af5c9290c08099
1//===-- 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#include "lldb/Host/Host.h" 11#include "lldb/Core/ArchSpec.h" 12#include "lldb/Core/ConstString.h" 13#include "lldb/Core/Error.h" 14#include "lldb/Core/Log.h" 15#include "lldb/Core/StreamString.h" 16#include "lldb/Host/Config.h" 17#include "lldb/Host/Endian.h" 18#include "lldb/Host/FileSpec.h" 19#include "lldb/Host/Mutex.h" 20#include "lldb/Target/Process.h" 21 22#include "llvm/Support/Host.h" 23#include "llvm/Support/MachO.h" 24 25#include <dlfcn.h> 26#include <errno.h> 27#include <grp.h> 28#include <limits.h> 29#include <netdb.h> 30#include <pwd.h> 31#include <sys/types.h> 32 33 34#if defined (__APPLE__) 35 36#include <dispatch/dispatch.h> 37#include <libproc.h> 38#include <mach-o/dyld.h> 39#include <sys/sysctl.h> 40 41 42#elif defined (__linux__) 43 44#include <sys/wait.h> 45 46#endif 47 48using namespace lldb; 49using namespace lldb_private; 50 51struct MonitorInfo 52{ 53 lldb::pid_t pid; // The process ID to monitor 54 Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals 55 void *callback_baton; // The callback baton for the callback function 56 bool monitor_signals; // If true, call the callback when "pid" gets signaled. 57}; 58 59static void * 60MonitorChildProcessThreadFunction (void *arg); 61 62lldb::thread_t 63Host::StartMonitoringChildProcess 64( 65 Host::MonitorChildProcessCallback callback, 66 void *callback_baton, 67 lldb::pid_t pid, 68 bool monitor_signals 69) 70{ 71 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; 72 if (callback) 73 { 74 std::auto_ptr<MonitorInfo> info_ap(new MonitorInfo); 75 76 info_ap->pid = pid; 77 info_ap->callback = callback; 78 info_ap->callback_baton = callback_baton; 79 info_ap->monitor_signals = monitor_signals; 80 81 char thread_name[256]; 82 ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid); 83 thread = ThreadCreate (thread_name, 84 MonitorChildProcessThreadFunction, 85 info_ap.get(), 86 NULL); 87 88 if (IS_VALID_LLDB_HOST_THREAD(thread)) 89 info_ap.release(); 90 } 91 return thread; 92} 93 94//------------------------------------------------------------------ 95// Scoped class that will disable thread canceling when it is 96// constructed, and exception safely restore the previous value it 97// when it goes out of scope. 98//------------------------------------------------------------------ 99class ScopedPThreadCancelDisabler 100{ 101public: 102 ScopedPThreadCancelDisabler() 103 { 104 // Disable the ability for this thread to be cancelled 105 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state); 106 if (err != 0) 107 m_old_state = -1; 108 109 } 110 111 ~ScopedPThreadCancelDisabler() 112 { 113 // Restore the ability for this thread to be cancelled to what it 114 // previously was. 115 if (m_old_state != -1) 116 ::pthread_setcancelstate (m_old_state, 0); 117 } 118private: 119 int m_old_state; // Save the old cancelability state. 120}; 121 122static void * 123MonitorChildProcessThreadFunction (void *arg) 124{ 125 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 126 const char *function = __FUNCTION__; 127 if (log) 128 log->Printf ("%s (arg = %p) thread starting...", function, arg); 129 130 MonitorInfo *info = (MonitorInfo *)arg; 131 132 const Host::MonitorChildProcessCallback callback = info->callback; 133 void * const callback_baton = info->callback_baton; 134 const lldb::pid_t pid = info->pid; 135 const bool monitor_signals = info->monitor_signals; 136 137 delete info; 138 139 int status = -1; 140 const int options = 0; 141 struct rusage *rusage = NULL; 142 while (1) 143 { 144 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 145 if (log) 146 log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, pid, options, rusage); 147 148 // Wait for all child processes 149 ::pthread_testcancel (); 150 const lldb::pid_t wait_pid = ::wait4 (pid, &status, options, rusage); 151 ::pthread_testcancel (); 152 153 if (wait_pid == -1) 154 { 155 if (errno == EINTR) 156 continue; 157 else 158 break; 159 } 160 else if (wait_pid == pid) 161 { 162 bool exited = false; 163 int signal = 0; 164 int exit_status = 0; 165 const char *status_cstr = NULL; 166 if (WIFSTOPPED(status)) 167 { 168 signal = WSTOPSIG(status); 169 status_cstr = "STOPPED"; 170 } 171 else if (WIFEXITED(status)) 172 { 173 exit_status = WEXITSTATUS(status); 174 status_cstr = "EXITED"; 175 exited = true; 176 } 177 else if (WIFSIGNALED(status)) 178 { 179 signal = WTERMSIG(status); 180 status_cstr = "SIGNALED"; 181 exited = true; 182 exit_status = -1; 183 } 184 else 185 { 186 status_cstr = "(???)"; 187 } 188 189 // Scope for pthread_cancel_disabler 190 { 191 ScopedPThreadCancelDisabler pthread_cancel_disabler; 192 193 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 194 if (log) 195 log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i", 196 function, 197 wait_pid, 198 options, 199 rusage, 200 pid, 201 status, 202 status_cstr, 203 signal, 204 exit_status); 205 206 if (exited || (signal != 0 && monitor_signals)) 207 { 208 bool callback_return = callback (callback_baton, pid, signal, exit_status); 209 210 // If our process exited, then this thread should exit 211 if (exited) 212 break; 213 // If the callback returns true, it means this process should 214 // exit 215 if (callback_return) 216 break; 217 } 218 } 219 } 220 } 221 222 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 223 if (log) 224 log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg); 225 226 return NULL; 227} 228 229size_t 230Host::GetPageSize() 231{ 232 return ::getpagesize(); 233} 234 235const ArchSpec & 236Host::GetArchitecture (SystemDefaultArchitecture arch_kind) 237{ 238 static bool g_supports_32 = false; 239 static bool g_supports_64 = false; 240 static ArchSpec g_host_arch_32; 241 static ArchSpec g_host_arch_64; 242 243#if defined (__APPLE__) 244 245 // Apple is different in that it can support both 32 and 64 bit executables 246 // in the same operating system running concurrently. Here we detect the 247 // correct host architectures for both 32 and 64 bit including if 64 bit 248 // executables are supported on the system. 249 250 if (g_supports_32 == false && g_supports_64 == false) 251 { 252 // All apple systems support 32 bit execution. 253 g_supports_32 = true; 254 uint32_t cputype, cpusubtype; 255 uint32_t is_64_bit_capable = false; 256 size_t len = sizeof(cputype); 257 ArchSpec host_arch; 258 // These will tell us about the kernel architecture, which even on a 64 259 // bit machine can be 32 bit... 260 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) 261 { 262 len = sizeof (cpusubtype); 263 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0) 264 cpusubtype = CPU_TYPE_ANY; 265 266 len = sizeof (is_64_bit_capable); 267 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) 268 { 269 if (is_64_bit_capable) 270 g_supports_64 = true; 271 } 272 273 if (is_64_bit_capable) 274 { 275#if defined (__i386__) || defined (__x86_64__) 276 if (cpusubtype == CPU_SUBTYPE_486) 277 cpusubtype = CPU_SUBTYPE_I386_ALL; 278#endif 279 if (cputype & CPU_ARCH_ABI64) 280 { 281 // We have a 64 bit kernel on a 64 bit system 282 g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype); 283 g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 284 } 285 else 286 { 287 // We have a 32 bit kernel on a 64 bit system 288 g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 289 cputype |= CPU_ARCH_ABI64; 290 g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 291 } 292 } 293 else 294 { 295 g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 296 g_host_arch_64.Clear(); 297 } 298 } 299 } 300 301#else // #if defined (__APPLE__) 302 303 if (g_supports_32 == false && g_supports_64 == false) 304 { 305 llvm::Triple triple(llvm::sys::getHostTriple()); 306 307 g_host_arch_32.Clear(); 308 g_host_arch_64.Clear(); 309 310 switch (triple.getArch()) 311 { 312 default: 313 g_host_arch_32.SetTriple(triple); 314 g_supports_32 = true; 315 break; 316 317 case llvm::Triple::alpha: 318 case llvm::Triple::x86_64: 319 case llvm::Triple::sparcv9: 320 case llvm::Triple::ppc64: 321 case llvm::Triple::systemz: 322 case llvm::Triple::cellspu: 323 g_host_arch_64.SetTriple(triple); 324 g_supports_64 = true; 325 break; 326 } 327 328 g_supports_32 = g_host_arch_32.IsValid(); 329 g_supports_64 = g_host_arch_64.IsValid(); 330 } 331 332#endif // #else for #if defined (__APPLE__) 333 334 if (arch_kind == eSystemDefaultArchitecture32) 335 return g_host_arch_32; 336 else if (arch_kind == eSystemDefaultArchitecture64) 337 return g_host_arch_64; 338 339 if (g_supports_64) 340 return g_host_arch_64; 341 342 return g_host_arch_32; 343} 344 345const ConstString & 346Host::GetVendorString() 347{ 348 static ConstString g_vendor; 349 if (!g_vendor) 350 { 351#if defined (__APPLE__) 352 char ostype[64]; 353 size_t len = sizeof(ostype); 354 if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0) 355 g_vendor.SetCString (ostype); 356 else 357 g_vendor.SetCString("apple"); 358#elif defined (__linux__) 359 g_vendor.SetCString("gnu"); 360#endif 361 } 362 return g_vendor; 363} 364 365const ConstString & 366Host::GetOSString() 367{ 368 static ConstString g_os_string; 369 if (!g_os_string) 370 { 371#if defined (__APPLE__) 372 g_os_string.SetCString("darwin"); 373#elif defined (__linux__) 374 g_os_string.SetCString("linux"); 375#endif 376 } 377 return g_os_string; 378} 379 380const ConstString & 381Host::GetTargetTriple() 382{ 383 static ConstString g_host_triple; 384 if (!(g_host_triple)) 385 { 386 StreamString triple; 387 triple.Printf("%s-%s-%s", 388 GetArchitecture().GetArchitectureName(), 389 GetVendorString().AsCString(), 390 GetOSString().AsCString()); 391 392 std::transform (triple.GetString().begin(), 393 triple.GetString().end(), 394 triple.GetString().begin(), 395 ::tolower); 396 397 g_host_triple.SetCString(triple.GetString().c_str()); 398 } 399 return g_host_triple; 400} 401 402lldb::pid_t 403Host::GetCurrentProcessID() 404{ 405 return ::getpid(); 406} 407 408lldb::tid_t 409Host::GetCurrentThreadID() 410{ 411#if defined (__APPLE__) 412 return ::mach_thread_self(); 413#else 414 return lldb::tid_t(pthread_self()); 415#endif 416} 417 418const char * 419Host::GetSignalAsCString (int signo) 420{ 421 switch (signo) 422 { 423 case SIGHUP: return "SIGHUP"; // 1 hangup 424 case SIGINT: return "SIGINT"; // 2 interrupt 425 case SIGQUIT: return "SIGQUIT"; // 3 quit 426 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught) 427 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught) 428 case SIGABRT: return "SIGABRT"; // 6 abort() 429#if defined(_POSIX_C_SOURCE) 430 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) 431#else // !_POSIX_C_SOURCE 432 case SIGEMT: return "SIGEMT"; // 7 EMT instruction 433#endif // !_POSIX_C_SOURCE 434 case SIGFPE: return "SIGFPE"; // 8 floating point exception 435 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored) 436 case SIGBUS: return "SIGBUS"; // 10 bus error 437 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation 438 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call 439 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it 440 case SIGALRM: return "SIGALRM"; // 14 alarm clock 441 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill 442 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel 443 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty 444 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty 445 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process 446 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit 447 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read 448 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) 449#if !defined(_POSIX_C_SOURCE) 450 case SIGIO: return "SIGIO"; // 23 input/output possible signal 451#endif 452 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit 453 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit 454 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm 455 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm 456#if !defined(_POSIX_C_SOURCE) 457 case SIGWINCH: return "SIGWINCH"; // 28 window size changes 458 case SIGINFO: return "SIGINFO"; // 29 information request 459#endif 460 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1 461 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2 462 default: 463 break; 464 } 465 return NULL; 466} 467 468void 469Host::WillTerminate () 470{ 471} 472 473#if !defined (__APPLE__) // see macosx/Host.mm 474void 475Host::ThreadCreated (const char *thread_name) 476{ 477} 478 479void 480Host::Backtrace (Stream &strm, uint32_t max_frames) 481{ 482 // TODO: Is there a way to backtrace the current process on linux? Other systems? 483} 484 485 486size_t 487Host::GetEnvironment (StringList &env) 488{ 489 // TODO: Is there a way to the host environment for this process on linux? Other systems? 490 return 0; 491} 492 493#endif 494 495struct HostThreadCreateInfo 496{ 497 std::string thread_name; 498 thread_func_t thread_fptr; 499 thread_arg_t thread_arg; 500 501 HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) : 502 thread_name (name ? name : ""), 503 thread_fptr (fptr), 504 thread_arg (arg) 505 { 506 } 507}; 508 509static thread_result_t 510ThreadCreateTrampoline (thread_arg_t arg) 511{ 512 HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg; 513 Host::ThreadCreated (info->thread_name.c_str()); 514 thread_func_t thread_fptr = info->thread_fptr; 515 thread_arg_t thread_arg = info->thread_arg; 516 517 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 518 if (log) 519 log->Printf("thread created"); 520 521 delete info; 522 return thread_fptr (thread_arg); 523} 524 525lldb::thread_t 526Host::ThreadCreate 527( 528 const char *thread_name, 529 thread_func_t thread_fptr, 530 thread_arg_t thread_arg, 531 Error *error 532) 533{ 534 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; 535 536 // Host::ThreadCreateTrampoline will delete this pointer for us. 537 HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg); 538 539 int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr); 540 if (err == 0) 541 { 542 if (error) 543 error->Clear(); 544 return thread; 545 } 546 547 if (error) 548 error->SetError (err, eErrorTypePOSIX); 549 550 return LLDB_INVALID_HOST_THREAD; 551} 552 553bool 554Host::ThreadCancel (lldb::thread_t thread, Error *error) 555{ 556 int err = ::pthread_cancel (thread); 557 if (error) 558 error->SetError(err, eErrorTypePOSIX); 559 return err == 0; 560} 561 562bool 563Host::ThreadDetach (lldb::thread_t thread, Error *error) 564{ 565 int err = ::pthread_detach (thread); 566 if (error) 567 error->SetError(err, eErrorTypePOSIX); 568 return err == 0; 569} 570 571bool 572Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error) 573{ 574 int err = ::pthread_join (thread, thread_result_ptr); 575 if (error) 576 error->SetError(err, eErrorTypePOSIX); 577 return err == 0; 578} 579 580//------------------------------------------------------------------ 581// Control access to a static file thread name map using a single 582// static function to avoid a static constructor. 583//------------------------------------------------------------------ 584static const char * 585ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name) 586{ 587 uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid; 588 589 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 590 Mutex::Locker locker(&g_mutex); 591 592 typedef std::map<uint64_t, std::string> thread_name_map; 593 // rdar://problem/8153284 594 // Fixed a crasher where during shutdown, loggings attempted to access the 595 // thread name but the static map instance had already been destructed. 596 // Another approach is to introduce a static guard object which monitors its 597 // own destruction and raises a flag, but this incurs more overhead. 598 static thread_name_map *g_thread_names_ptr = new thread_name_map(); 599 thread_name_map &g_thread_names = *g_thread_names_ptr; 600 601 if (get) 602 { 603 // See if the thread name exists in our thread name pool 604 thread_name_map::iterator pos = g_thread_names.find(pid_tid); 605 if (pos != g_thread_names.end()) 606 return pos->second.c_str(); 607 } 608 else 609 { 610 // Set the thread name 611 g_thread_names[pid_tid] = name; 612 } 613 return NULL; 614} 615 616const char * 617Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) 618{ 619 const char *name = ThreadNameAccessor (true, pid, tid, NULL); 620 if (name == NULL) 621 { 622#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 623 // We currently can only get the name of a thread in the current process. 624 if (pid == Host::GetCurrentProcessID()) 625 { 626 char pthread_name[1024]; 627 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0) 628 { 629 if (pthread_name[0]) 630 { 631 // Set the thread in our string pool 632 ThreadNameAccessor (false, pid, tid, pthread_name); 633 // Get our copy of the thread name string 634 name = ThreadNameAccessor (true, pid, tid, NULL); 635 } 636 } 637 638 if (name == NULL) 639 { 640 dispatch_queue_t current_queue = ::dispatch_get_current_queue (); 641 if (current_queue != NULL) 642 name = dispatch_queue_get_label (current_queue); 643 } 644 } 645#endif 646 } 647 return name; 648} 649 650void 651Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name) 652{ 653 lldb::pid_t curr_pid = Host::GetCurrentProcessID(); 654 lldb::tid_t curr_tid = Host::GetCurrentThreadID(); 655 if (pid == LLDB_INVALID_PROCESS_ID) 656 pid = curr_pid; 657 658 if (tid == LLDB_INVALID_THREAD_ID) 659 tid = curr_tid; 660 661#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 662 // Set the pthread name if possible 663 if (pid == curr_pid && tid == curr_tid) 664 { 665 ::pthread_setname_np (name); 666 } 667#endif 668 ThreadNameAccessor (false, pid, tid, name); 669} 670 671FileSpec 672Host::GetProgramFileSpec () 673{ 674 static FileSpec g_program_filespec; 675 if (!g_program_filespec) 676 { 677#if defined (__APPLE__) 678 char program_fullpath[PATH_MAX]; 679 // If DST is NULL, then return the number of bytes needed. 680 uint32_t len = sizeof(program_fullpath); 681 int err = _NSGetExecutablePath (program_fullpath, &len); 682 if (err == 0) 683 g_program_filespec.SetFile (program_fullpath, false); 684 else if (err == -1) 685 { 686 char *large_program_fullpath = (char *)::malloc (len + 1); 687 688 err = _NSGetExecutablePath (large_program_fullpath, &len); 689 if (err == 0) 690 g_program_filespec.SetFile (large_program_fullpath, false); 691 692 ::free (large_program_fullpath); 693 } 694#elif defined (__linux__) 695 char exe_path[PATH_MAX]; 696 ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); 697 if (len > 0) { 698 exe_path[len] = 0; 699 g_program_filespec.SetFile(exe_path, false); 700 } 701#elif defined (__FreeBSD__) 702 int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() }; 703 size_t exe_path_size; 704 if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) 705 { 706 char *exe_path = new char[exe_path_size]; 707 if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) 708 g_program_filespec.SetFile(exe_path, false); 709 delete[] exe_path; 710 } 711#endif 712 } 713 return g_program_filespec; 714} 715 716FileSpec 717Host::GetModuleFileSpecForHostAddress (const void *host_addr) 718{ 719 FileSpec module_filespec; 720 Dl_info info; 721 if (::dladdr (host_addr, &info)) 722 { 723 if (info.dli_fname) 724 module_filespec.SetFile(info.dli_fname, true); 725 } 726 return module_filespec; 727} 728 729#if !defined (__APPLE__) // see Host.mm 730bool 731Host::ResolveExecutableInBundle (FileSpec &file) 732{ 733 return false; 734} 735#endif 736 737// Opaque info that tracks a dynamic library that was loaded 738struct DynamicLibraryInfo 739{ 740 DynamicLibraryInfo (const FileSpec &fs, int o, void *h) : 741 file_spec (fs), 742 open_options (o), 743 handle (h) 744 { 745 } 746 747 const FileSpec file_spec; 748 uint32_t open_options; 749 void * handle; 750}; 751 752void * 753Host::DynamicLibraryOpen (const FileSpec &file_spec, uint32_t options, Error &error) 754{ 755 char path[PATH_MAX]; 756 if (file_spec.GetPath(path, sizeof(path))) 757 { 758 int mode = 0; 759 760 if (options & eDynamicLibraryOpenOptionLazy) 761 mode |= RTLD_LAZY; 762 else 763 mode |= RTLD_NOW; 764 765 766 if (options & eDynamicLibraryOpenOptionLocal) 767 mode |= RTLD_LOCAL; 768 else 769 mode |= RTLD_GLOBAL; 770 771#ifdef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 772 if (options & eDynamicLibraryOpenOptionLimitGetSymbol) 773 mode |= RTLD_FIRST; 774#endif 775 776 void * opaque = ::dlopen (path, mode); 777 778 if (opaque) 779 { 780 error.Clear(); 781 return new DynamicLibraryInfo (file_spec, options, opaque); 782 } 783 else 784 { 785 error.SetErrorString(::dlerror()); 786 } 787 } 788 else 789 { 790 error.SetErrorString("failed to extract path"); 791 } 792 return NULL; 793} 794 795Error 796Host::DynamicLibraryClose (void *opaque) 797{ 798 Error error; 799 if (opaque == NULL) 800 { 801 error.SetErrorString ("invalid dynamic library handle"); 802 } 803 else 804 { 805 DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; 806 if (::dlclose (dylib_info->handle) != 0) 807 { 808 error.SetErrorString(::dlerror()); 809 } 810 811 dylib_info->open_options = 0; 812 dylib_info->handle = 0; 813 delete dylib_info; 814 } 815 return error; 816} 817 818void * 819Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &error) 820{ 821 if (opaque == NULL) 822 { 823 error.SetErrorString ("invalid dynamic library handle"); 824 } 825 else 826 { 827 DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; 828 829 void *symbol_addr = ::dlsym (dylib_info->handle, symbol_name); 830 if (symbol_addr) 831 { 832#ifndef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 833 // This host doesn't support limiting searches to this shared library 834 // so we need to verify that the match came from this shared library 835 // if it was requested in the Host::DynamicLibraryOpen() function. 836 if (dylib_info->open_options & eDynamicLibraryOpenOptionLimitGetSymbol) 837 { 838 FileSpec match_dylib_spec (Host::GetModuleFileSpecForHostAddress (symbol_addr)); 839 if (match_dylib_spec != dylib_info->file_spec) 840 { 841 char dylib_path[PATH_MAX]; 842 if (dylib_info->file_spec.GetPath (dylib_path, sizeof(dylib_path))) 843 error.SetErrorStringWithFormat ("symbol not found in \"%s\"", dylib_path); 844 else 845 error.SetErrorString ("symbol not found"); 846 return NULL; 847 } 848 } 849#endif 850 error.Clear(); 851 return symbol_addr; 852 } 853 else 854 { 855 error.SetErrorString(::dlerror()); 856 } 857 } 858 return NULL; 859} 860 861bool 862Host::GetLLDBPath (PathType path_type, FileSpec &file_spec) 863{ 864 // To get paths related to LLDB we get the path to the executable that 865 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", 866 // on linux this is assumed to be the "lldb" main executable. If LLDB on 867 // linux is actually in a shared library (lldb.so??) then this function will 868 // need to be modified to "do the right thing". 869 870 switch (path_type) 871 { 872 case ePathTypeLLDBShlibDir: 873 { 874 static ConstString g_lldb_so_dir; 875 if (!g_lldb_so_dir) 876 { 877 FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath)); 878 g_lldb_so_dir = lldb_file_spec.GetDirectory(); 879 } 880 file_spec.GetDirectory() = g_lldb_so_dir; 881 return file_spec.GetDirectory(); 882 } 883 break; 884 885 case ePathTypeSupportExecutableDir: 886 { 887 static ConstString g_lldb_support_exe_dir; 888 if (!g_lldb_support_exe_dir) 889 { 890 FileSpec lldb_file_spec; 891 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 892 { 893 char raw_path[PATH_MAX]; 894 char resolved_path[PATH_MAX]; 895 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 896 897#if defined (__APPLE__) 898 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 899 if (framework_pos) 900 { 901 framework_pos += strlen("LLDB.framework"); 902 ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path)); 903 } 904#endif 905 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 906 g_lldb_support_exe_dir.SetCString(resolved_path); 907 } 908 } 909 file_spec.GetDirectory() = g_lldb_support_exe_dir; 910 return file_spec.GetDirectory(); 911 } 912 break; 913 914 case ePathTypeHeaderDir: 915 { 916 static ConstString g_lldb_headers_dir; 917 if (!g_lldb_headers_dir) 918 { 919#if defined (__APPLE__) 920 FileSpec lldb_file_spec; 921 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 922 { 923 char raw_path[PATH_MAX]; 924 char resolved_path[PATH_MAX]; 925 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 926 927 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 928 if (framework_pos) 929 { 930 framework_pos += strlen("LLDB.framework"); 931 ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path)); 932 } 933 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 934 g_lldb_headers_dir.SetCString(resolved_path); 935 } 936#else 937 // TODO: Anyone know how we can determine this for linux? Other systems?? 938 g_lldb_headers_dir.SetCString ("/opt/local/include/lldb"); 939#endif 940 } 941 file_spec.GetDirectory() = g_lldb_headers_dir; 942 return file_spec.GetDirectory(); 943 } 944 break; 945 946 case ePathTypePythonDir: 947 { 948 // TODO: Anyone know how we can determine this for linux? Other systems? 949 // For linux we are currently assuming the location of the lldb 950 // binary that contains this function is the directory that will 951 // contain lldb.so, lldb.py and embedded_interpreter.py... 952 953 static ConstString g_lldb_python_dir; 954 if (!g_lldb_python_dir) 955 { 956 FileSpec lldb_file_spec; 957 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 958 { 959 char raw_path[PATH_MAX]; 960 char resolved_path[PATH_MAX]; 961 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 962 963#if defined (__APPLE__) 964 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 965 if (framework_pos) 966 { 967 framework_pos += strlen("LLDB.framework"); 968 ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path)); 969 } 970#endif 971 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 972 g_lldb_python_dir.SetCString(resolved_path); 973 } 974 } 975 file_spec.GetDirectory() = g_lldb_python_dir; 976 return file_spec.GetDirectory(); 977 } 978 break; 979 980 case ePathTypeLLDBSystemPlugins: // System plug-ins directory 981 { 982#if defined (__APPLE__) 983 static ConstString g_lldb_system_plugin_dir; 984 static bool g_lldb_system_plugin_dir_located = false; 985 if (!g_lldb_system_plugin_dir_located) 986 { 987 g_lldb_system_plugin_dir_located = true; 988 FileSpec lldb_file_spec; 989 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 990 { 991 char raw_path[PATH_MAX]; 992 char resolved_path[PATH_MAX]; 993 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 994 995 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 996 if (framework_pos) 997 { 998 framework_pos += strlen("LLDB.framework"); 999 ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path)); 1000 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 1001 g_lldb_system_plugin_dir.SetCString(resolved_path); 1002 } 1003 return false; 1004 } 1005 } 1006 1007 if (g_lldb_system_plugin_dir) 1008 { 1009 file_spec.GetDirectory() = g_lldb_system_plugin_dir; 1010 return true; 1011 } 1012#endif 1013 // TODO: where would system LLDB plug-ins be located on linux? Other systems? 1014 return false; 1015 } 1016 break; 1017 1018 case ePathTypeLLDBUserPlugins: // User plug-ins directory 1019 { 1020#if defined (__APPLE__) 1021 static ConstString g_lldb_user_plugin_dir; 1022 if (!g_lldb_user_plugin_dir) 1023 { 1024 char user_plugin_path[PATH_MAX]; 1025 if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns", 1026 user_plugin_path, 1027 sizeof(user_plugin_path))) 1028 { 1029 g_lldb_user_plugin_dir.SetCString(user_plugin_path); 1030 } 1031 } 1032 file_spec.GetDirectory() = g_lldb_user_plugin_dir; 1033 return file_spec.GetDirectory(); 1034#endif 1035 // TODO: where would user LLDB plug-ins be located on linux? Other systems? 1036 return false; 1037 } 1038 default: 1039 assert (!"Unhandled PathType"); 1040 break; 1041 } 1042 1043 return false; 1044} 1045 1046 1047bool 1048Host::GetHostname (std::string &s) 1049{ 1050 char hostname[PATH_MAX]; 1051 hostname[sizeof(hostname) - 1] = '\0'; 1052 if (::gethostname (hostname, sizeof(hostname) - 1) == 0) 1053 { 1054 struct hostent* h = ::gethostbyname (hostname); 1055 if (h) 1056 s.assign (h->h_name); 1057 else 1058 s.assign (hostname); 1059 return true; 1060 } 1061 return false; 1062} 1063 1064const char * 1065Host::GetUserName (uint32_t uid, std::string &user_name) 1066{ 1067 struct passwd user_info; 1068 struct passwd *user_info_ptr = &user_info; 1069 char user_buffer[PATH_MAX]; 1070 size_t user_buffer_size = sizeof(user_buffer); 1071 if (::getpwuid_r (uid, 1072 &user_info, 1073 user_buffer, 1074 user_buffer_size, 1075 &user_info_ptr) == 0) 1076 { 1077 if (user_info_ptr) 1078 { 1079 user_name.assign (user_info_ptr->pw_name); 1080 return user_name.c_str(); 1081 } 1082 } 1083 user_name.clear(); 1084 return NULL; 1085} 1086 1087const char * 1088Host::GetGroupName (uint32_t gid, std::string &group_name) 1089{ 1090 char group_buffer[PATH_MAX]; 1091 size_t group_buffer_size = sizeof(group_buffer); 1092 struct group group_info; 1093 struct group *group_info_ptr = &group_info; 1094 // Try the threadsafe version first 1095 if (::getgrgid_r (gid, 1096 &group_info, 1097 group_buffer, 1098 group_buffer_size, 1099 &group_info_ptr) == 0) 1100 { 1101 if (group_info_ptr) 1102 { 1103 group_name.assign (group_info_ptr->gr_name); 1104 return group_name.c_str(); 1105 } 1106 } 1107 else 1108 { 1109 // The threadsafe version isn't currently working 1110 // for me on darwin, but the non-threadsafe version 1111 // is, so I am calling it below. 1112 group_info_ptr = ::getgrgid (gid); 1113 if (group_info_ptr) 1114 { 1115 group_name.assign (group_info_ptr->gr_name); 1116 return group_name.c_str(); 1117 } 1118 } 1119 group_name.clear(); 1120 return NULL; 1121} 1122 1123 1124#if !defined (__APPLE__) // see macosx/Host.mm 1125 1126bool 1127Host::GetOSBuildString (std::string &s) 1128{ 1129 s.clear(); 1130 return false; 1131} 1132 1133bool 1134Host::GetOSKernelDescription (std::string &s) 1135{ 1136 s.clear(); 1137 return false; 1138} 1139 1140uint32_t 1141Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 1142{ 1143 process_infos.Clear(); 1144 return process_infos.GetSize(); 1145} 1146 1147bool 1148Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 1149{ 1150 process_info.Clear(); 1151 return false; 1152} 1153 1154bool 1155Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) 1156{ 1157 return false; 1158} 1159 1160void 1161Host::SetCrashDescriptionWithFormat (const char *format, ...) 1162{ 1163} 1164 1165void 1166Host::SetCrashDescription (const char *description) 1167{ 1168} 1169 1170lldb::pid_t 1171LaunchApplication (const FileSpec &app_file_spec) 1172{ 1173 return LLDB_INVALID_PROCESS_ID; 1174} 1175 1176#endif 1177