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