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