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