Host.cpp revision 0c2921f5b9dab2ca1832bb746ab3aa3f66fdd0b5
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/lldb-python.h" 11 12// C includes 13#include <dlfcn.h> 14#include <errno.h> 15#include <grp.h> 16#include <limits.h> 17#include <netdb.h> 18#include <pwd.h> 19#include <sys/sysctl.h> 20#include <sys/types.h> 21#include <unistd.h> 22 23#if defined (__APPLE__) 24 25#include <dispatch/dispatch.h> 26#include <libproc.h> 27#include <mach-o/dyld.h> 28#include <mach/mach_port.h> 29 30#elif defined (__linux__) || defined(__FreeBSD_kernel__) 31/* Linux or the FreeBSD kernel with glibc (Debian KFreeBSD for example) */ 32 33#include <sys/wait.h> 34 35#elif defined (__FreeBSD__) 36 37#include <sys/wait.h> 38#include <pthread_np.h> 39 40#endif 41 42#include "lldb/Host/Host.h" 43#include "lldb/Core/ArchSpec.h" 44#include "lldb/Core/ConstString.h" 45#include "lldb/Core/Debugger.h" 46#include "lldb/Core/Error.h" 47#include "lldb/Core/Log.h" 48#include "lldb/Core/StreamString.h" 49#include "lldb/Core/ThreadSafeSTLMap.h" 50#include "lldb/Host/Config.h" 51#include "lldb/Host/Endian.h" 52#include "lldb/Host/FileSpec.h" 53#include "lldb/Host/Mutex.h" 54#include "lldb/Target/Process.h" 55#include "lldb/Target/TargetList.h" 56 57#include "llvm/Support/Host.h" 58#include "llvm/Support/MachO.h" 59#include "llvm/ADT/Twine.h" 60 61 62 63 64 65using namespace lldb; 66using namespace lldb_private; 67 68 69#if !defined (__APPLE__) 70struct MonitorInfo 71{ 72 lldb::pid_t pid; // The process ID to monitor 73 Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals 74 void *callback_baton; // The callback baton for the callback function 75 bool monitor_signals; // If true, call the callback when "pid" gets signaled. 76}; 77 78static void * 79MonitorChildProcessThreadFunction (void *arg); 80 81lldb::thread_t 82Host::StartMonitoringChildProcess 83( 84 Host::MonitorChildProcessCallback callback, 85 void *callback_baton, 86 lldb::pid_t pid, 87 bool monitor_signals 88) 89{ 90 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; 91 MonitorInfo * info_ptr = new MonitorInfo(); 92 93 info_ptr->pid = pid; 94 info_ptr->callback = callback; 95 info_ptr->callback_baton = callback_baton; 96 info_ptr->monitor_signals = monitor_signals; 97 98 char thread_name[256]; 99 ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); 100 thread = ThreadCreate (thread_name, 101 MonitorChildProcessThreadFunction, 102 info_ptr, 103 NULL); 104 105 return thread; 106} 107 108//------------------------------------------------------------------ 109// Scoped class that will disable thread canceling when it is 110// constructed, and exception safely restore the previous value it 111// when it goes out of scope. 112//------------------------------------------------------------------ 113class ScopedPThreadCancelDisabler 114{ 115public: 116 ScopedPThreadCancelDisabler() 117 { 118 // Disable the ability for this thread to be cancelled 119 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state); 120 if (err != 0) 121 m_old_state = -1; 122 123 } 124 125 ~ScopedPThreadCancelDisabler() 126 { 127 // Restore the ability for this thread to be cancelled to what it 128 // previously was. 129 if (m_old_state != -1) 130 ::pthread_setcancelstate (m_old_state, 0); 131 } 132private: 133 int m_old_state; // Save the old cancelability state. 134}; 135 136static void * 137MonitorChildProcessThreadFunction (void *arg) 138{ 139 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 140 const char *function = __FUNCTION__; 141 if (log) 142 log->Printf ("%s (arg = %p) thread starting...", function, arg); 143 144 MonitorInfo *info = (MonitorInfo *)arg; 145 146 const Host::MonitorChildProcessCallback callback = info->callback; 147 void * const callback_baton = info->callback_baton; 148 const lldb::pid_t pid = info->pid; 149 const bool monitor_signals = info->monitor_signals; 150 151 delete info; 152 153 int status = -1; 154#if defined (__FreeBSD__) 155 #define __WALL 0 156#endif 157 const int options = __WALL; 158 159 while (1) 160 { 161 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 162 if (log) 163 log->Printf("%s ::wait_pid (pid = %" PRIu64 ", &status, options = %i)...", function, pid, options); 164 165 // Wait for all child processes 166 ::pthread_testcancel (); 167 // Get signals from all children with same process group of pid 168 const lldb::pid_t wait_pid = ::waitpid (-1*pid, &status, options); 169 ::pthread_testcancel (); 170 171 if (wait_pid == -1) 172 { 173 if (errno == EINTR) 174 continue; 175 else 176 break; 177 } 178 else if (wait_pid > 0) 179 { 180 bool exited = false; 181 int signal = 0; 182 int exit_status = 0; 183 const char *status_cstr = NULL; 184 if (WIFSTOPPED(status)) 185 { 186 signal = WSTOPSIG(status); 187 status_cstr = "STOPPED"; 188 } 189 else if (WIFEXITED(status)) 190 { 191 exit_status = WEXITSTATUS(status); 192 status_cstr = "EXITED"; 193 if (wait_pid == pid) 194 exited = true; 195 } 196 else if (WIFSIGNALED(status)) 197 { 198 signal = WTERMSIG(status); 199 status_cstr = "SIGNALED"; 200 if (wait_pid == pid) { 201 exited = true; 202 exit_status = -1; 203 } 204 } 205 else 206 { 207 status_cstr = "(\?\?\?)"; 208 } 209 210 // Scope for pthread_cancel_disabler 211 { 212 ScopedPThreadCancelDisabler pthread_cancel_disabler; 213 214 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 215 if (log) 216 log->Printf ("%s ::waitpid (pid = %" PRIu64 ", &status, options = %i) => pid = %" PRIu64 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", 217 function, 218 wait_pid, 219 options, 220 pid, 221 status, 222 status_cstr, 223 signal, 224 exit_status); 225 226 if (exited || (signal != 0 && monitor_signals)) 227 { 228 bool callback_return = false; 229 if (callback) 230 callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status); 231 232 // If our process exited, then this thread should exit 233 if (exited) 234 break; 235 // If the callback returns true, it means this process should 236 // exit 237 if (callback_return) 238 break; 239 } 240 } 241 } 242 } 243 244 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 245 if (log) 246 log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg); 247 248 return NULL; 249} 250 251 252void 253Host::SystemLog (SystemLogType type, const char *format, va_list args) 254{ 255 vfprintf (stderr, format, args); 256} 257 258#endif // #if !defined (__APPLE__) 259 260void 261Host::SystemLog (SystemLogType type, const char *format, ...) 262{ 263 va_list args; 264 va_start (args, format); 265 SystemLog (type, format, args); 266 va_end (args); 267} 268 269size_t 270Host::GetPageSize() 271{ 272 return ::getpagesize(); 273} 274 275const ArchSpec & 276Host::GetArchitecture (SystemDefaultArchitecture arch_kind) 277{ 278 static bool g_supports_32 = false; 279 static bool g_supports_64 = false; 280 static ArchSpec g_host_arch_32; 281 static ArchSpec g_host_arch_64; 282 283#if defined (__APPLE__) 284 285 // Apple is different in that it can support both 32 and 64 bit executables 286 // in the same operating system running concurrently. Here we detect the 287 // correct host architectures for both 32 and 64 bit including if 64 bit 288 // executables are supported on the system. 289 290 if (g_supports_32 == false && g_supports_64 == false) 291 { 292 // All apple systems support 32 bit execution. 293 g_supports_32 = true; 294 uint32_t cputype, cpusubtype; 295 uint32_t is_64_bit_capable = false; 296 size_t len = sizeof(cputype); 297 ArchSpec host_arch; 298 // These will tell us about the kernel architecture, which even on a 64 299 // bit machine can be 32 bit... 300 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) 301 { 302 len = sizeof (cpusubtype); 303 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0) 304 cpusubtype = CPU_TYPE_ANY; 305 306 len = sizeof (is_64_bit_capable); 307 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) 308 { 309 if (is_64_bit_capable) 310 g_supports_64 = true; 311 } 312 313 if (is_64_bit_capable) 314 { 315#if defined (__i386__) || defined (__x86_64__) 316 if (cpusubtype == CPU_SUBTYPE_486) 317 cpusubtype = CPU_SUBTYPE_I386_ALL; 318#endif 319 if (cputype & CPU_ARCH_ABI64) 320 { 321 // We have a 64 bit kernel on a 64 bit system 322 g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype); 323 g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 324 } 325 else 326 { 327 // We have a 32 bit kernel on a 64 bit system 328 g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 329 cputype |= CPU_ARCH_ABI64; 330 g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 331 } 332 } 333 else 334 { 335 g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 336 g_host_arch_64.Clear(); 337 } 338 } 339 } 340 341#else // #if defined (__APPLE__) 342 343 if (g_supports_32 == false && g_supports_64 == false) 344 { 345 llvm::Triple triple(llvm::sys::getDefaultTargetTriple()); 346 347 g_host_arch_32.Clear(); 348 g_host_arch_64.Clear(); 349 350 // If the OS is Linux, "unknown" in the vendor slot isn't what we want 351 // for the default triple. It's probably an artifact of config.guess. 352 if (triple.getOS() == llvm::Triple::Linux && triple.getVendor() == llvm::Triple::UnknownVendor) 353 triple.setVendorName(""); 354 355 switch (triple.getArch()) 356 { 357 default: 358 g_host_arch_32.SetTriple(triple); 359 g_supports_32 = true; 360 break; 361 362 case llvm::Triple::x86_64: 363 g_host_arch_64.SetTriple(triple); 364 g_supports_64 = true; 365 g_host_arch_32.SetTriple(triple.get32BitArchVariant()); 366 g_supports_32 = true; 367 break; 368 369 case llvm::Triple::sparcv9: 370 case llvm::Triple::ppc64: 371 g_host_arch_64.SetTriple(triple); 372 g_supports_64 = true; 373 break; 374 } 375 376 g_supports_32 = g_host_arch_32.IsValid(); 377 g_supports_64 = g_host_arch_64.IsValid(); 378 } 379 380#endif // #else for #if defined (__APPLE__) 381 382 if (arch_kind == eSystemDefaultArchitecture32) 383 return g_host_arch_32; 384 else if (arch_kind == eSystemDefaultArchitecture64) 385 return g_host_arch_64; 386 387 if (g_supports_64) 388 return g_host_arch_64; 389 390 return g_host_arch_32; 391} 392 393const ConstString & 394Host::GetVendorString() 395{ 396 static ConstString g_vendor; 397 if (!g_vendor) 398 { 399 const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture); 400 const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName(); 401 g_vendor.SetCStringWithLength(str_ref.data(), str_ref.size()); 402 } 403 return g_vendor; 404} 405 406const ConstString & 407Host::GetOSString() 408{ 409 static ConstString g_os_string; 410 if (!g_os_string) 411 { 412 const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture); 413 const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName(); 414 g_os_string.SetCStringWithLength(str_ref.data(), str_ref.size()); 415 } 416 return g_os_string; 417} 418 419const ConstString & 420Host::GetTargetTriple() 421{ 422 static ConstString g_host_triple; 423 if (!(g_host_triple)) 424 { 425 const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture); 426 g_host_triple.SetCString(host_arch.GetTriple().getTriple().c_str()); 427 } 428 return g_host_triple; 429} 430 431lldb::pid_t 432Host::GetCurrentProcessID() 433{ 434 return ::getpid(); 435} 436 437lldb::tid_t 438Host::GetCurrentThreadID() 439{ 440#if defined (__APPLE__) 441 // Calling "mach_port_deallocate()" bumps the reference count on the thread 442 // port, so we need to deallocate it. mach_task_self() doesn't bump the ref 443 // count. 444 thread_port_t thread_self = mach_thread_self(); 445 mach_port_deallocate(mach_task_self(), thread_self); 446 return thread_self; 447#elif defined(__FreeBSD__) 448 return lldb::tid_t(pthread_getthreadid_np()); 449#else 450 return lldb::tid_t(pthread_self()); 451#endif 452} 453 454lldb::thread_t 455Host::GetCurrentThread () 456{ 457 return lldb::thread_t(pthread_self()); 458} 459 460const char * 461Host::GetSignalAsCString (int signo) 462{ 463 switch (signo) 464 { 465 case SIGHUP: return "SIGHUP"; // 1 hangup 466 case SIGINT: return "SIGINT"; // 2 interrupt 467 case SIGQUIT: return "SIGQUIT"; // 3 quit 468 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught) 469 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught) 470 case SIGABRT: return "SIGABRT"; // 6 abort() 471#if (defined(_POSIX_C_SOURCE) && !defined(_DARWIN_C_SOURCE)) 472 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) 473#endif 474#if !defined(_POSIX_C_SOURCE) 475 case SIGEMT: return "SIGEMT"; // 7 EMT instruction 476#endif 477 case SIGFPE: return "SIGFPE"; // 8 floating point exception 478 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored) 479 case SIGBUS: return "SIGBUS"; // 10 bus error 480 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation 481 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call 482 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it 483 case SIGALRM: return "SIGALRM"; // 14 alarm clock 484 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill 485 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel 486 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty 487 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty 488 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process 489 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit 490 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read 491 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) 492#if !defined(_POSIX_C_SOURCE) 493 case SIGIO: return "SIGIO"; // 23 input/output possible signal 494#endif 495 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit 496 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit 497 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm 498 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm 499#if !defined(_POSIX_C_SOURCE) 500 case SIGWINCH: return "SIGWINCH"; // 28 window size changes 501 case SIGINFO: return "SIGINFO"; // 29 information request 502#endif 503 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1 504 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2 505 default: 506 break; 507 } 508 return NULL; 509} 510 511void 512Host::WillTerminate () 513{ 514} 515 516#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__linux__) // see macosx/Host.mm 517 518void 519Host::ThreadCreated (const char *thread_name) 520{ 521} 522 523void 524Host::Backtrace (Stream &strm, uint32_t max_frames) 525{ 526 // TODO: Is there a way to backtrace the current process on linux? Other systems? 527} 528 529size_t 530Host::GetEnvironment (StringList &env) 531{ 532 // TODO: Is there a way to the host environment for this process on linux? Other systems? 533 return 0; 534} 535 536#endif // #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__linux__) 537 538struct HostThreadCreateInfo 539{ 540 std::string thread_name; 541 thread_func_t thread_fptr; 542 thread_arg_t thread_arg; 543 544 HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) : 545 thread_name (name ? name : ""), 546 thread_fptr (fptr), 547 thread_arg (arg) 548 { 549 } 550}; 551 552static thread_result_t 553ThreadCreateTrampoline (thread_arg_t arg) 554{ 555 HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg; 556 Host::ThreadCreated (info->thread_name.c_str()); 557 thread_func_t thread_fptr = info->thread_fptr; 558 thread_arg_t thread_arg = info->thread_arg; 559 560 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 561 if (log) 562 log->Printf("thread created"); 563 564 delete info; 565 return thread_fptr (thread_arg); 566} 567 568lldb::thread_t 569Host::ThreadCreate 570( 571 const char *thread_name, 572 thread_func_t thread_fptr, 573 thread_arg_t thread_arg, 574 Error *error 575) 576{ 577 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; 578 579 // Host::ThreadCreateTrampoline will delete this pointer for us. 580 HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg); 581 582 int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr); 583 if (err == 0) 584 { 585 if (error) 586 error->Clear(); 587 return thread; 588 } 589 590 if (error) 591 error->SetError (err, eErrorTypePOSIX); 592 593 return LLDB_INVALID_HOST_THREAD; 594} 595 596bool 597Host::ThreadCancel (lldb::thread_t thread, Error *error) 598{ 599 int err = ::pthread_cancel (thread); 600 if (error) 601 error->SetError(err, eErrorTypePOSIX); 602 return err == 0; 603} 604 605bool 606Host::ThreadDetach (lldb::thread_t thread, Error *error) 607{ 608 int err = ::pthread_detach (thread); 609 if (error) 610 error->SetError(err, eErrorTypePOSIX); 611 return err == 0; 612} 613 614bool 615Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error) 616{ 617 int err = ::pthread_join (thread, thread_result_ptr); 618 if (error) 619 error->SetError(err, eErrorTypePOSIX); 620 return err == 0; 621} 622 623 624std::string 625Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) 626{ 627 std::string thread_name; 628#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 629 // We currently can only get the name of a thread in the current process. 630 if (pid == Host::GetCurrentProcessID()) 631 { 632 char pthread_name[1024]; 633 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0) 634 { 635 if (pthread_name[0]) 636 { 637 thread_name = pthread_name; 638 } 639 } 640 else 641 { 642 dispatch_queue_t current_queue = ::dispatch_get_current_queue (); 643 if (current_queue != NULL) 644 { 645 const char *queue_name = dispatch_queue_get_label (current_queue); 646 if (queue_name && queue_name[0]) 647 { 648 thread_name = queue_name; 649 } 650 } 651 } 652 } 653#endif 654 return thread_name; 655} 656 657bool 658Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name) 659{ 660#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 661 lldb::pid_t curr_pid = Host::GetCurrentProcessID(); 662 lldb::tid_t curr_tid = Host::GetCurrentThreadID(); 663 if (pid == LLDB_INVALID_PROCESS_ID) 664 pid = curr_pid; 665 666 if (tid == LLDB_INVALID_THREAD_ID) 667 tid = curr_tid; 668 669 // Set the pthread name if possible 670 if (pid == curr_pid && tid == curr_tid) 671 { 672 if (::pthread_setname_np (name) == 0) 673 return true; 674 } 675 return false; 676#elif defined (__linux__) 677 void *fn = dlsym (RTLD_DEFAULT, "pthread_setname_np"); 678 if (fn) 679 { 680 int (*pthread_setname_np_func)(pthread_t thread, const char *name); 681 *reinterpret_cast<void **> (&pthread_setname_np_func) = fn; 682 683 lldb::pid_t curr_pid = Host::GetCurrentProcessID(); 684 lldb::tid_t curr_tid = Host::GetCurrentThreadID(); 685 686 if (pid == LLDB_INVALID_PROCESS_ID) 687 pid = curr_pid; 688 689 if (tid == LLDB_INVALID_THREAD_ID) 690 tid = curr_tid; 691 692 if (pid == curr_pid) 693 { 694 if (pthread_setname_np_func (tid, name) == 0) 695 return true; 696 } 697 } 698 return false; 699#else 700 return false; 701#endif 702} 703 704FileSpec 705Host::GetProgramFileSpec () 706{ 707 static FileSpec g_program_filespec; 708 if (!g_program_filespec) 709 { 710#if defined (__APPLE__) 711 char program_fullpath[PATH_MAX]; 712 // If DST is NULL, then return the number of bytes needed. 713 uint32_t len = sizeof(program_fullpath); 714 int err = _NSGetExecutablePath (program_fullpath, &len); 715 if (err == 0) 716 g_program_filespec.SetFile (program_fullpath, false); 717 else if (err == -1) 718 { 719 char *large_program_fullpath = (char *)::malloc (len + 1); 720 721 err = _NSGetExecutablePath (large_program_fullpath, &len); 722 if (err == 0) 723 g_program_filespec.SetFile (large_program_fullpath, false); 724 725 ::free (large_program_fullpath); 726 } 727#elif defined (__linux__) 728 char exe_path[PATH_MAX]; 729 ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); 730 if (len > 0) { 731 exe_path[len] = 0; 732 g_program_filespec.SetFile(exe_path, false); 733 } 734#elif defined (__FreeBSD__) 735 int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() }; 736 size_t exe_path_size; 737 if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) 738 { 739 char *exe_path = new char[exe_path_size]; 740 if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) 741 g_program_filespec.SetFile(exe_path, false); 742 delete[] exe_path; 743 } 744#endif 745 } 746 return g_program_filespec; 747} 748 749FileSpec 750Host::GetModuleFileSpecForHostAddress (const void *host_addr) 751{ 752 FileSpec module_filespec; 753 Dl_info info; 754 if (::dladdr (host_addr, &info)) 755 { 756 if (info.dli_fname) 757 module_filespec.SetFile(info.dli_fname, true); 758 } 759 return module_filespec; 760} 761 762#if !defined (__APPLE__) // see Host.mm 763 764bool 765Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) 766{ 767 bundle.Clear(); 768 return false; 769} 770 771bool 772Host::ResolveExecutableInBundle (FileSpec &file) 773{ 774 return false; 775} 776#endif 777 778// Opaque info that tracks a dynamic library that was loaded 779struct DynamicLibraryInfo 780{ 781 DynamicLibraryInfo (const FileSpec &fs, int o, void *h) : 782 file_spec (fs), 783 open_options (o), 784 handle (h) 785 { 786 } 787 788 const FileSpec file_spec; 789 uint32_t open_options; 790 void * handle; 791}; 792 793void * 794Host::DynamicLibraryOpen (const FileSpec &file_spec, uint32_t options, Error &error) 795{ 796 char path[PATH_MAX]; 797 if (file_spec.GetPath(path, sizeof(path))) 798 { 799 int mode = 0; 800 801 if (options & eDynamicLibraryOpenOptionLazy) 802 mode |= RTLD_LAZY; 803 else 804 mode |= RTLD_NOW; 805 806 807 if (options & eDynamicLibraryOpenOptionLocal) 808 mode |= RTLD_LOCAL; 809 else 810 mode |= RTLD_GLOBAL; 811 812#ifdef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 813 if (options & eDynamicLibraryOpenOptionLimitGetSymbol) 814 mode |= RTLD_FIRST; 815#endif 816 817 void * opaque = ::dlopen (path, mode); 818 819 if (opaque) 820 { 821 error.Clear(); 822 return new DynamicLibraryInfo (file_spec, options, opaque); 823 } 824 else 825 { 826 error.SetErrorString(::dlerror()); 827 } 828 } 829 else 830 { 831 error.SetErrorString("failed to extract path"); 832 } 833 return NULL; 834} 835 836Error 837Host::DynamicLibraryClose (void *opaque) 838{ 839 Error error; 840 if (opaque == NULL) 841 { 842 error.SetErrorString ("invalid dynamic library handle"); 843 } 844 else 845 { 846 DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; 847 if (::dlclose (dylib_info->handle) != 0) 848 { 849 error.SetErrorString(::dlerror()); 850 } 851 852 dylib_info->open_options = 0; 853 dylib_info->handle = 0; 854 delete dylib_info; 855 } 856 return error; 857} 858 859void * 860Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &error) 861{ 862 if (opaque == NULL) 863 { 864 error.SetErrorString ("invalid dynamic library handle"); 865 } 866 else 867 { 868 DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; 869 870 void *symbol_addr = ::dlsym (dylib_info->handle, symbol_name); 871 if (symbol_addr) 872 { 873#ifndef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 874 // This host doesn't support limiting searches to this shared library 875 // so we need to verify that the match came from this shared library 876 // if it was requested in the Host::DynamicLibraryOpen() function. 877 if (dylib_info->open_options & eDynamicLibraryOpenOptionLimitGetSymbol) 878 { 879 FileSpec match_dylib_spec (Host::GetModuleFileSpecForHostAddress (symbol_addr)); 880 if (match_dylib_spec != dylib_info->file_spec) 881 { 882 char dylib_path[PATH_MAX]; 883 if (dylib_info->file_spec.GetPath (dylib_path, sizeof(dylib_path))) 884 error.SetErrorStringWithFormat ("symbol not found in \"%s\"", dylib_path); 885 else 886 error.SetErrorString ("symbol not found"); 887 return NULL; 888 } 889 } 890#endif 891 error.Clear(); 892 return symbol_addr; 893 } 894 else 895 { 896 error.SetErrorString(::dlerror()); 897 } 898 } 899 return NULL; 900} 901 902bool 903Host::GetLLDBPath (PathType path_type, FileSpec &file_spec) 904{ 905 // To get paths related to LLDB we get the path to the executable that 906 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", 907 // on linux this is assumed to be the "lldb" main executable. If LLDB on 908 // linux is actually in a shared library (lldb.so??) then this function will 909 // need to be modified to "do the right thing". 910 911 switch (path_type) 912 { 913 case ePathTypeLLDBShlibDir: 914 { 915 static ConstString g_lldb_so_dir; 916 if (!g_lldb_so_dir) 917 { 918 FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath)); 919 g_lldb_so_dir = lldb_file_spec.GetDirectory(); 920 } 921 file_spec.GetDirectory() = g_lldb_so_dir; 922 return file_spec.GetDirectory(); 923 } 924 break; 925 926 case ePathTypeSupportExecutableDir: 927 { 928 static ConstString g_lldb_support_exe_dir; 929 if (!g_lldb_support_exe_dir) 930 { 931 FileSpec lldb_file_spec; 932 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 933 { 934 char raw_path[PATH_MAX]; 935 char resolved_path[PATH_MAX]; 936 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 937 938#if defined (__APPLE__) 939 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 940 if (framework_pos) 941 { 942 framework_pos += strlen("LLDB.framework"); 943#if !defined (__arm__) 944 ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path)); 945#endif 946 } 947#endif 948 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 949 g_lldb_support_exe_dir.SetCString(resolved_path); 950 } 951 } 952 file_spec.GetDirectory() = g_lldb_support_exe_dir; 953 return file_spec.GetDirectory(); 954 } 955 break; 956 957 case ePathTypeHeaderDir: 958 { 959 static ConstString g_lldb_headers_dir; 960 if (!g_lldb_headers_dir) 961 { 962#if defined (__APPLE__) 963 FileSpec lldb_file_spec; 964 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 965 { 966 char raw_path[PATH_MAX]; 967 char resolved_path[PATH_MAX]; 968 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 969 970 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 971 if (framework_pos) 972 { 973 framework_pos += strlen("LLDB.framework"); 974 ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path)); 975 } 976 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 977 g_lldb_headers_dir.SetCString(resolved_path); 978 } 979#else 980 // TODO: Anyone know how we can determine this for linux? Other systems?? 981 g_lldb_headers_dir.SetCString ("/opt/local/include/lldb"); 982#endif 983 } 984 file_spec.GetDirectory() = g_lldb_headers_dir; 985 return file_spec.GetDirectory(); 986 } 987 break; 988 989 case ePathTypePythonDir: 990 { 991 static ConstString g_lldb_python_dir; 992 if (!g_lldb_python_dir) 993 { 994 FileSpec lldb_file_spec; 995 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 996 { 997 char raw_path[PATH_MAX]; 998 char resolved_path[PATH_MAX]; 999 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 1000 1001#if defined (__APPLE__) 1002 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 1003 if (framework_pos) 1004 { 1005 framework_pos += strlen("LLDB.framework"); 1006 ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path)); 1007 } 1008#else 1009 llvm::Twine python_version_dir; 1010 python_version_dir = "/python" 1011 + llvm::Twine(PY_MAJOR_VERSION) 1012 + "." 1013 + llvm::Twine(PY_MINOR_VERSION) 1014 + "/site-packages"; 1015 1016 // We may get our string truncated. Should we protect 1017 // this with an assert? 1018 1019 ::strncat(raw_path, python_version_dir.str().c_str(), 1020 sizeof(raw_path) - strlen(raw_path) - 1); 1021 1022#endif 1023 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 1024 g_lldb_python_dir.SetCString(resolved_path); 1025 } 1026 } 1027 file_spec.GetDirectory() = g_lldb_python_dir; 1028 return file_spec.GetDirectory(); 1029 } 1030 break; 1031 1032 case ePathTypeLLDBSystemPlugins: // System plug-ins directory 1033 { 1034#if defined (__APPLE__) 1035 static ConstString g_lldb_system_plugin_dir; 1036 static bool g_lldb_system_plugin_dir_located = false; 1037 if (!g_lldb_system_plugin_dir_located) 1038 { 1039 g_lldb_system_plugin_dir_located = true; 1040 FileSpec lldb_file_spec; 1041 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 1042 { 1043 char raw_path[PATH_MAX]; 1044 char resolved_path[PATH_MAX]; 1045 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 1046 1047 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 1048 if (framework_pos) 1049 { 1050 framework_pos += strlen("LLDB.framework"); 1051 ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path)); 1052 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 1053 g_lldb_system_plugin_dir.SetCString(resolved_path); 1054 } 1055 return false; 1056 } 1057 } 1058 1059 if (g_lldb_system_plugin_dir) 1060 { 1061 file_spec.GetDirectory() = g_lldb_system_plugin_dir; 1062 return true; 1063 } 1064#endif 1065 // TODO: where would system LLDB plug-ins be located on linux? Other systems? 1066 return false; 1067 } 1068 break; 1069 1070 case ePathTypeLLDBUserPlugins: // User plug-ins directory 1071 { 1072#if defined (__APPLE__) 1073 static ConstString g_lldb_user_plugin_dir; 1074 if (!g_lldb_user_plugin_dir) 1075 { 1076 char user_plugin_path[PATH_MAX]; 1077 if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns", 1078 user_plugin_path, 1079 sizeof(user_plugin_path))) 1080 { 1081 g_lldb_user_plugin_dir.SetCString(user_plugin_path); 1082 } 1083 } 1084 file_spec.GetDirectory() = g_lldb_user_plugin_dir; 1085 return file_spec.GetDirectory(); 1086#endif 1087 // TODO: where would user LLDB plug-ins be located on linux? Other systems? 1088 return false; 1089 } 1090 } 1091 1092 return false; 1093} 1094 1095 1096bool 1097Host::GetHostname (std::string &s) 1098{ 1099 char hostname[PATH_MAX]; 1100 hostname[sizeof(hostname) - 1] = '\0'; 1101 if (::gethostname (hostname, sizeof(hostname) - 1) == 0) 1102 { 1103 struct hostent* h = ::gethostbyname (hostname); 1104 if (h) 1105 s.assign (h->h_name); 1106 else 1107 s.assign (hostname); 1108 return true; 1109 } 1110 return false; 1111} 1112 1113const char * 1114Host::GetUserName (uint32_t uid, std::string &user_name) 1115{ 1116 struct passwd user_info; 1117 struct passwd *user_info_ptr = &user_info; 1118 char user_buffer[PATH_MAX]; 1119 size_t user_buffer_size = sizeof(user_buffer); 1120 if (::getpwuid_r (uid, 1121 &user_info, 1122 user_buffer, 1123 user_buffer_size, 1124 &user_info_ptr) == 0) 1125 { 1126 if (user_info_ptr) 1127 { 1128 user_name.assign (user_info_ptr->pw_name); 1129 return user_name.c_str(); 1130 } 1131 } 1132 user_name.clear(); 1133 return NULL; 1134} 1135 1136const char * 1137Host::GetGroupName (uint32_t gid, std::string &group_name) 1138{ 1139 char group_buffer[PATH_MAX]; 1140 size_t group_buffer_size = sizeof(group_buffer); 1141 struct group group_info; 1142 struct group *group_info_ptr = &group_info; 1143 // Try the threadsafe version first 1144 if (::getgrgid_r (gid, 1145 &group_info, 1146 group_buffer, 1147 group_buffer_size, 1148 &group_info_ptr) == 0) 1149 { 1150 if (group_info_ptr) 1151 { 1152 group_name.assign (group_info_ptr->gr_name); 1153 return group_name.c_str(); 1154 } 1155 } 1156 else 1157 { 1158 // The threadsafe version isn't currently working 1159 // for me on darwin, but the non-threadsafe version 1160 // is, so I am calling it below. 1161 group_info_ptr = ::getgrgid (gid); 1162 if (group_info_ptr) 1163 { 1164 group_name.assign (group_info_ptr->gr_name); 1165 return group_name.c_str(); 1166 } 1167 } 1168 group_name.clear(); 1169 return NULL; 1170} 1171 1172#if !defined (__APPLE__) && !defined (__FreeBSD__) // see macosx/Host.mm 1173bool 1174Host::GetOSBuildString (std::string &s) 1175{ 1176 s.clear(); 1177 return false; 1178} 1179 1180bool 1181Host::GetOSKernelDescription (std::string &s) 1182{ 1183 s.clear(); 1184 return false; 1185} 1186#endif 1187 1188uint32_t 1189Host::GetUserID () 1190{ 1191 return getuid(); 1192} 1193 1194uint32_t 1195Host::GetGroupID () 1196{ 1197 return getgid(); 1198} 1199 1200uint32_t 1201Host::GetEffectiveUserID () 1202{ 1203 return geteuid(); 1204} 1205 1206uint32_t 1207Host::GetEffectiveGroupID () 1208{ 1209 return getegid(); 1210} 1211 1212#if !defined (__APPLE__) && !defined(__linux__) 1213uint32_t 1214Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 1215{ 1216 process_infos.Clear(); 1217 return process_infos.GetSize(); 1218} 1219#endif // #if !defined (__APPLE__) && !defined(__linux__) 1220 1221#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined(__linux__) 1222bool 1223Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 1224{ 1225 process_info.Clear(); 1226 return false; 1227} 1228#endif 1229 1230lldb::TargetSP 1231Host::GetDummyTarget (lldb_private::Debugger &debugger) 1232{ 1233 static TargetSP g_dummy_target_sp; 1234 1235 // FIXME: Maybe the dummy target should be per-Debugger 1236 if (!g_dummy_target_sp || !g_dummy_target_sp->IsValid()) 1237 { 1238 ArchSpec arch(Target::GetDefaultArchitecture()); 1239 if (!arch.IsValid()) 1240 arch = Host::GetArchitecture (); 1241 Error err = debugger.GetTargetList().CreateTarget(debugger, 1242 NULL, 1243 arch.GetTriple().getTriple().c_str(), 1244 false, 1245 NULL, 1246 g_dummy_target_sp); 1247 } 1248 1249 return g_dummy_target_sp; 1250} 1251 1252struct ShellInfo 1253{ 1254 ShellInfo () : 1255 process_reaped (false), 1256 can_delete (false), 1257 pid (LLDB_INVALID_PROCESS_ID), 1258 signo(-1), 1259 status(-1) 1260 { 1261 } 1262 1263 lldb_private::Predicate<bool> process_reaped; 1264 lldb_private::Predicate<bool> can_delete; 1265 lldb::pid_t pid; 1266 int signo; 1267 int status; 1268}; 1269 1270static bool 1271MonitorShellCommand (void *callback_baton, 1272 lldb::pid_t pid, 1273 bool exited, // True if the process did exit 1274 int signo, // Zero for no signal 1275 int status) // Exit value of process if signal is zero 1276{ 1277 ShellInfo *shell_info = (ShellInfo *)callback_baton; 1278 shell_info->pid = pid; 1279 shell_info->signo = signo; 1280 shell_info->status = status; 1281 // Let the thread running Host::RunShellCommand() know that the process 1282 // exited and that ShellInfo has been filled in by broadcasting to it 1283 shell_info->process_reaped.SetValue(1, eBroadcastAlways); 1284 // Now wait for a handshake back from that thread running Host::RunShellCommand 1285 // so we know that we can delete shell_info_ptr 1286 shell_info->can_delete.WaitForValueEqualTo(true); 1287 // Sleep a bit to allow the shell_info->can_delete.SetValue() to complete... 1288 usleep(1000); 1289 // Now delete the shell info that was passed into this function 1290 delete shell_info; 1291 return true; 1292} 1293 1294Error 1295Host::RunShellCommand (const char *command, 1296 const char *working_dir, 1297 int *status_ptr, 1298 int *signo_ptr, 1299 std::string *command_output_ptr, 1300 uint32_t timeout_sec, 1301 const char *shell) 1302{ 1303 Error error; 1304 ProcessLaunchInfo launch_info; 1305 if (shell && shell[0]) 1306 { 1307 // Run the command in a shell 1308 launch_info.SetShell(shell); 1309 launch_info.GetArguments().AppendArgument(command); 1310 const bool localhost = true; 1311 const bool will_debug = false; 1312 const bool first_arg_is_full_shell_command = true; 1313 launch_info.ConvertArgumentsForLaunchingInShell (error, 1314 localhost, 1315 will_debug, 1316 first_arg_is_full_shell_command); 1317 } 1318 else 1319 { 1320 // No shell, just run it 1321 Args args (command); 1322 const bool first_arg_is_executable = true; 1323 launch_info.SetArguments(args, first_arg_is_executable); 1324 } 1325 1326 if (working_dir) 1327 launch_info.SetWorkingDirectory(working_dir); 1328 char output_file_path_buffer[L_tmpnam]; 1329 const char *output_file_path = NULL; 1330 if (command_output_ptr) 1331 { 1332 // Create a temporary file to get the stdout/stderr and redirect the 1333 // output of the command into this file. We will later read this file 1334 // if all goes well and fill the data into "command_output_ptr" 1335 output_file_path = ::tmpnam(output_file_path_buffer); 1336 launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); 1337 launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path, false, true); 1338 launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); 1339 } 1340 else 1341 { 1342 launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); 1343 launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); 1344 launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); 1345 } 1346 1347 // The process monitor callback will delete the 'shell_info_ptr' below... 1348 std::unique_ptr<ShellInfo> shell_info_ap (new ShellInfo()); 1349 1350 const bool monitor_signals = false; 1351 launch_info.SetMonitorProcessCallback(MonitorShellCommand, shell_info_ap.get(), monitor_signals); 1352 1353 error = LaunchProcess (launch_info); 1354 const lldb::pid_t pid = launch_info.GetProcessID(); 1355 if (pid != LLDB_INVALID_PROCESS_ID) 1356 { 1357 // The process successfully launched, so we can defer ownership of 1358 // "shell_info" to the MonitorShellCommand callback function that will 1359 // get called when the process dies. We release the unique pointer as it 1360 // doesn't need to delete the ShellInfo anymore. 1361 ShellInfo *shell_info = shell_info_ap.release(); 1362 TimeValue timeout_time(TimeValue::Now()); 1363 timeout_time.OffsetWithSeconds(timeout_sec); 1364 bool timed_out = false; 1365 shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out); 1366 if (timed_out) 1367 { 1368 error.SetErrorString("timed out waiting for shell command to complete"); 1369 1370 // Kill the process since it didn't complete withint the timeout specified 1371 ::kill (pid, SIGKILL); 1372 // Wait for the monitor callback to get the message 1373 timeout_time = TimeValue::Now(); 1374 timeout_time.OffsetWithSeconds(1); 1375 timed_out = false; 1376 shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out); 1377 } 1378 else 1379 { 1380 if (status_ptr) 1381 *status_ptr = shell_info->status; 1382 1383 if (signo_ptr) 1384 *signo_ptr = shell_info->signo; 1385 1386 if (command_output_ptr) 1387 { 1388 command_output_ptr->clear(); 1389 FileSpec file_spec(output_file_path, File::eOpenOptionRead); 1390 uint64_t file_size = file_spec.GetByteSize(); 1391 if (file_size > 0) 1392 { 1393 if (file_size > command_output_ptr->max_size()) 1394 { 1395 error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string"); 1396 } 1397 else 1398 { 1399 command_output_ptr->resize(file_size); 1400 file_spec.ReadFileContents(0, &((*command_output_ptr)[0]), command_output_ptr->size(), &error); 1401 } 1402 } 1403 } 1404 } 1405 shell_info->can_delete.SetValue(true, eBroadcastAlways); 1406 } 1407 else 1408 { 1409 error.SetErrorString("failed to get process ID"); 1410 } 1411 1412 if (output_file_path) 1413 ::unlink (output_file_path); 1414 // Handshake with the monitor thread, or just let it know in advance that 1415 // it can delete "shell_info" in case we timed out and were not able to kill 1416 // the process... 1417 return error; 1418} 1419 1420 1421uint32_t 1422Host::GetNumberCPUS () 1423{ 1424 static uint32_t g_num_cores = UINT32_MAX; 1425 if (g_num_cores == UINT32_MAX) 1426 { 1427#if defined(__APPLE__) or defined (__linux__) or defined (__FreeBSD__) 1428 1429 g_num_cores = ::sysconf(_SC_NPROCESSORS_ONLN); 1430 1431#elif defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) 1432 1433 // Header file for this might need to be included at the top of this file 1434 SYSTEM_INFO system_info; 1435 ::GetSystemInfo (&system_info); 1436 g_num_cores = system_info.dwNumberOfProcessors; 1437 1438#else 1439 1440 // Assume POSIX support if a host specific case has not been supplied above 1441 g_num_cores = 0; 1442 int num_cores = 0; 1443 size_t num_cores_len = sizeof(num_cores); 1444 int mib[] = { CTL_HW, HW_AVAILCPU }; 1445 1446 /* get the number of CPUs from the system */ 1447 if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0)) 1448 { 1449 g_num_cores = num_cores; 1450 } 1451 else 1452 { 1453 mib[1] = HW_NCPU; 1454 num_cores_len = sizeof(num_cores); 1455 if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0)) 1456 { 1457 if (num_cores > 0) 1458 g_num_cores = num_cores; 1459 } 1460 } 1461#endif 1462 } 1463 return g_num_cores; 1464} 1465 1466 1467 1468#if !defined (__APPLE__) 1469bool 1470Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) 1471{ 1472 return false; 1473} 1474 1475void 1476Host::SetCrashDescriptionWithFormat (const char *format, ...) 1477{ 1478} 1479 1480void 1481Host::SetCrashDescription (const char *description) 1482{ 1483} 1484 1485lldb::pid_t 1486LaunchApplication (const FileSpec &app_file_spec) 1487{ 1488 return LLDB_INVALID_PROCESS_ID; 1489} 1490 1491#endif 1492