Host.cpp revision 258884
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 <errno.h> 14#include <limits.h> 15#include <sys/types.h> 16#ifdef _WIN32 17#include "lldb/Host/windows/windows.h" 18#include <winsock2.h> 19#include <WS2tcpip.h> 20#else 21#include <dlfcn.h> 22#include <grp.h> 23#include <netdb.h> 24#include <pwd.h> 25#include <sys/stat.h> 26#endif 27 28#if !defined (__GNU__) && !defined (_WIN32) 29// Does not exist under GNU/HURD or Windows 30#include <sys/sysctl.h> 31#endif 32 33#if defined (__APPLE__) 34#include <mach/mach_port.h> 35#include <mach/mach_init.h> 36#include <mach-o/dyld.h> 37#include <AvailabilityMacros.h> 38#endif 39 40#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 41#include <spawn.h> 42#include <sys/wait.h> 43#include <sys/syscall.h> 44#endif 45 46#if defined (__FreeBSD__) 47#include <pthread_np.h> 48#endif 49 50#include "lldb/Host/Host.h" 51#include "lldb/Core/ArchSpec.h" 52#include "lldb/Core/ConstString.h" 53#include "lldb/Core/Debugger.h" 54#include "lldb/Core/Error.h" 55#include "lldb/Core/Log.h" 56#include "lldb/Core/Module.h" 57#include "lldb/Core/StreamString.h" 58#include "lldb/Core/ThreadSafeSTLMap.h" 59#include "lldb/Host/Config.h" 60#include "lldb/Host/Endian.h" 61#include "lldb/Host/FileSpec.h" 62#include "lldb/Host/Mutex.h" 63#include "lldb/Target/Process.h" 64#include "lldb/Target/TargetList.h" 65#include "lldb/Utility/CleanUp.h" 66 67#include "llvm/ADT/SmallString.h" 68#include "llvm/Support/Host.h" 69#include "llvm/Support/raw_ostream.h" 70 71 72using namespace lldb; 73using namespace lldb_private; 74 75 76#if !defined (__APPLE__) && !defined (_WIN32) 77struct MonitorInfo 78{ 79 lldb::pid_t pid; // The process ID to monitor 80 Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals 81 void *callback_baton; // The callback baton for the callback function 82 bool monitor_signals; // If true, call the callback when "pid" gets signaled. 83}; 84 85static thread_result_t 86MonitorChildProcessThreadFunction (void *arg); 87 88lldb::thread_t 89Host::StartMonitoringChildProcess 90( 91 Host::MonitorChildProcessCallback callback, 92 void *callback_baton, 93 lldb::pid_t pid, 94 bool monitor_signals 95) 96{ 97 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; 98 MonitorInfo * info_ptr = new MonitorInfo(); 99 100 info_ptr->pid = pid; 101 info_ptr->callback = callback; 102 info_ptr->callback_baton = callback_baton; 103 info_ptr->monitor_signals = monitor_signals; 104 105 char thread_name[256]; 106 ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); 107 thread = ThreadCreate (thread_name, 108 MonitorChildProcessThreadFunction, 109 info_ptr, 110 NULL); 111 112 return thread; 113} 114 115//------------------------------------------------------------------ 116// Scoped class that will disable thread canceling when it is 117// constructed, and exception safely restore the previous value it 118// when it goes out of scope. 119//------------------------------------------------------------------ 120class ScopedPThreadCancelDisabler 121{ 122public: 123 ScopedPThreadCancelDisabler() 124 { 125 // Disable the ability for this thread to be cancelled 126 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state); 127 if (err != 0) 128 m_old_state = -1; 129 130 } 131 132 ~ScopedPThreadCancelDisabler() 133 { 134 // Restore the ability for this thread to be cancelled to what it 135 // previously was. 136 if (m_old_state != -1) 137 ::pthread_setcancelstate (m_old_state, 0); 138 } 139private: 140 int m_old_state; // Save the old cancelability state. 141}; 142 143static thread_result_t 144MonitorChildProcessThreadFunction (void *arg) 145{ 146 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 147 const char *function = __FUNCTION__; 148 if (log) 149 log->Printf ("%s (arg = %p) thread starting...", function, arg); 150 151 MonitorInfo *info = (MonitorInfo *)arg; 152 153 const Host::MonitorChildProcessCallback callback = info->callback; 154 void * const callback_baton = info->callback_baton; 155 const bool monitor_signals = info->monitor_signals; 156 157 assert (info->pid <= UINT32_MAX); 158 const ::pid_t pid = monitor_signals ? -1 * info->pid : info->pid; 159 160 delete info; 161 162 int status = -1; 163#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 164 #define __WALL 0 165#endif 166 const int options = __WALL; 167 168 while (1) 169 { 170 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 171 if (log) 172 log->Printf("%s ::wait_pid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); 173 174 // Wait for all child processes 175 ::pthread_testcancel (); 176 // Get signals from all children with same process group of pid 177 const ::pid_t wait_pid = ::waitpid (pid, &status, options); 178 ::pthread_testcancel (); 179 180 if (wait_pid == -1) 181 { 182 if (errno == EINTR) 183 continue; 184 else 185 { 186 if (log) 187 log->Printf ("%s (arg = %p) thread exiting because waitpid failed (%s)...", __FUNCTION__, arg, strerror(errno)); 188 break; 189 } 190 } 191 else if (wait_pid > 0) 192 { 193 bool exited = false; 194 int signal = 0; 195 int exit_status = 0; 196 const char *status_cstr = NULL; 197 if (WIFSTOPPED(status)) 198 { 199 signal = WSTOPSIG(status); 200 status_cstr = "STOPPED"; 201 } 202 else if (WIFEXITED(status)) 203 { 204 exit_status = WEXITSTATUS(status); 205 status_cstr = "EXITED"; 206 exited = true; 207 } 208 else if (WIFSIGNALED(status)) 209 { 210 signal = WTERMSIG(status); 211 status_cstr = "SIGNALED"; 212 if (wait_pid == abs(pid)) { 213 exited = true; 214 exit_status = -1; 215 } 216 } 217 else 218 { 219 status_cstr = "(\?\?\?)"; 220 } 221 222 // Scope for pthread_cancel_disabler 223 { 224 ScopedPThreadCancelDisabler pthread_cancel_disabler; 225 226 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 227 if (log) 228 log->Printf ("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i) => pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", 229 function, 230 wait_pid, 231 options, 232 pid, 233 status, 234 status_cstr, 235 signal, 236 exit_status); 237 238 if (exited || (signal != 0 && monitor_signals)) 239 { 240 bool callback_return = false; 241 if (callback) 242 callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status); 243 244 // If our process exited, then this thread should exit 245 if (exited && wait_pid == abs(pid)) 246 { 247 if (log) 248 log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg); 249 break; 250 } 251 // If the callback returns true, it means this process should 252 // exit 253 if (callback_return) 254 { 255 if (log) 256 log->Printf ("%s (arg = %p) thread exiting because callback returned true...", __FUNCTION__, arg); 257 break; 258 } 259 } 260 } 261 } 262 } 263 264 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); 265 if (log) 266 log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg); 267 268 return NULL; 269} 270 271#endif // #if !defined (__APPLE__) && !defined (_WIN32) 272 273#if !defined (__APPLE__) 274 275void 276Host::SystemLog (SystemLogType type, const char *format, va_list args) 277{ 278 vfprintf (stderr, format, args); 279} 280 281#endif 282 283void 284Host::SystemLog (SystemLogType type, const char *format, ...) 285{ 286 va_list args; 287 va_start (args, format); 288 SystemLog (type, format, args); 289 va_end (args); 290} 291 292const ArchSpec & 293Host::GetArchitecture (SystemDefaultArchitecture arch_kind) 294{ 295 static bool g_supports_32 = false; 296 static bool g_supports_64 = false; 297 static ArchSpec g_host_arch_32; 298 static ArchSpec g_host_arch_64; 299 300#if defined (__APPLE__) 301 302 // Apple is different in that it can support both 32 and 64 bit executables 303 // in the same operating system running concurrently. Here we detect the 304 // correct host architectures for both 32 and 64 bit including if 64 bit 305 // executables are supported on the system. 306 307 if (g_supports_32 == false && g_supports_64 == false) 308 { 309 // All apple systems support 32 bit execution. 310 g_supports_32 = true; 311 uint32_t cputype, cpusubtype; 312 uint32_t is_64_bit_capable = false; 313 size_t len = sizeof(cputype); 314 ArchSpec host_arch; 315 // These will tell us about the kernel architecture, which even on a 64 316 // bit machine can be 32 bit... 317 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) 318 { 319 len = sizeof (cpusubtype); 320 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0) 321 cpusubtype = CPU_TYPE_ANY; 322 323 len = sizeof (is_64_bit_capable); 324 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) 325 { 326 if (is_64_bit_capable) 327 g_supports_64 = true; 328 } 329 330 if (is_64_bit_capable) 331 { 332#if defined (__i386__) || defined (__x86_64__) 333 if (cpusubtype == CPU_SUBTYPE_486) 334 cpusubtype = CPU_SUBTYPE_I386_ALL; 335#endif 336 if (cputype & CPU_ARCH_ABI64) 337 { 338 // We have a 64 bit kernel on a 64 bit system 339 g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype); 340 g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 341 } 342 else 343 { 344 // We have a 32 bit kernel on a 64 bit system 345 g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 346 cputype |= CPU_ARCH_ABI64; 347 g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 348 } 349 } 350 else 351 { 352 g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); 353 g_host_arch_64.Clear(); 354 } 355 } 356 } 357 358#else // #if defined (__APPLE__) 359 360 if (g_supports_32 == false && g_supports_64 == false) 361 { 362 llvm::Triple triple(llvm::sys::getDefaultTargetTriple()); 363 364 g_host_arch_32.Clear(); 365 g_host_arch_64.Clear(); 366 367 // If the OS is Linux, "unknown" in the vendor slot isn't what we want 368 // for the default triple. It's probably an artifact of config.guess. 369 if (triple.getOS() == llvm::Triple::Linux && triple.getVendor() == llvm::Triple::UnknownVendor) 370 triple.setVendorName(""); 371 372 switch (triple.getArch()) 373 { 374 default: 375 g_host_arch_32.SetTriple(triple); 376 g_supports_32 = true; 377 break; 378 379 case llvm::Triple::x86_64: 380 g_host_arch_64.SetTriple(triple); 381 g_supports_64 = true; 382 g_host_arch_32.SetTriple(triple.get32BitArchVariant()); 383 g_supports_32 = true; 384 break; 385 386 case llvm::Triple::sparcv9: 387 case llvm::Triple::ppc64: 388 g_host_arch_64.SetTriple(triple); 389 g_supports_64 = true; 390 break; 391 } 392 393 g_supports_32 = g_host_arch_32.IsValid(); 394 g_supports_64 = g_host_arch_64.IsValid(); 395 } 396 397#endif // #else for #if defined (__APPLE__) 398 399 if (arch_kind == eSystemDefaultArchitecture32) 400 return g_host_arch_32; 401 else if (arch_kind == eSystemDefaultArchitecture64) 402 return g_host_arch_64; 403 404 if (g_supports_64) 405 return g_host_arch_64; 406 407 return g_host_arch_32; 408} 409 410const ConstString & 411Host::GetVendorString() 412{ 413 static ConstString g_vendor; 414 if (!g_vendor) 415 { 416 const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture); 417 const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName(); 418 g_vendor.SetCStringWithLength(str_ref.data(), str_ref.size()); 419 } 420 return g_vendor; 421} 422 423const ConstString & 424Host::GetOSString() 425{ 426 static ConstString g_os_string; 427 if (!g_os_string) 428 { 429 const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture); 430 const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName(); 431 g_os_string.SetCStringWithLength(str_ref.data(), str_ref.size()); 432 } 433 return g_os_string; 434} 435 436const ConstString & 437Host::GetTargetTriple() 438{ 439 static ConstString g_host_triple; 440 if (!(g_host_triple)) 441 { 442 const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture); 443 g_host_triple.SetCString(host_arch.GetTriple().getTriple().c_str()); 444 } 445 return g_host_triple; 446} 447 448lldb::pid_t 449Host::GetCurrentProcessID() 450{ 451 return ::getpid(); 452} 453 454#ifndef _WIN32 455 456lldb::tid_t 457Host::GetCurrentThreadID() 458{ 459#if defined (__APPLE__) 460 // Calling "mach_port_deallocate()" bumps the reference count on the thread 461 // port, so we need to deallocate it. mach_task_self() doesn't bump the ref 462 // count. 463 thread_port_t thread_self = mach_thread_self(); 464 mach_port_deallocate(mach_task_self(), thread_self); 465 return thread_self; 466#elif defined(__FreeBSD__) 467 return lldb::tid_t(pthread_getthreadid_np()); 468#elif defined(__linux__) 469 return lldb::tid_t(syscall(SYS_gettid)); 470#else 471 return lldb::tid_t(pthread_self()); 472#endif 473} 474 475lldb::thread_t 476Host::GetCurrentThread () 477{ 478 return lldb::thread_t(pthread_self()); 479} 480 481const char * 482Host::GetSignalAsCString (int signo) 483{ 484 switch (signo) 485 { 486 case SIGHUP: return "SIGHUP"; // 1 hangup 487 case SIGINT: return "SIGINT"; // 2 interrupt 488 case SIGQUIT: return "SIGQUIT"; // 3 quit 489 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught) 490 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught) 491 case SIGABRT: return "SIGABRT"; // 6 abort() 492#if (defined(_POSIX_C_SOURCE) && !defined(_DARWIN_C_SOURCE)) 493 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) 494#endif 495#if !defined(_POSIX_C_SOURCE) 496 case SIGEMT: return "SIGEMT"; // 7 EMT instruction 497#endif 498 case SIGFPE: return "SIGFPE"; // 8 floating point exception 499 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored) 500 case SIGBUS: return "SIGBUS"; // 10 bus error 501 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation 502 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call 503 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it 504 case SIGALRM: return "SIGALRM"; // 14 alarm clock 505 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill 506 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel 507 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty 508 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty 509 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process 510 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit 511 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read 512 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) 513#if !defined(_POSIX_C_SOURCE) 514 case SIGIO: return "SIGIO"; // 23 input/output possible signal 515#endif 516 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit 517 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit 518 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm 519 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm 520#if !defined(_POSIX_C_SOURCE) 521 case SIGWINCH: return "SIGWINCH"; // 28 window size changes 522 case SIGINFO: return "SIGINFO"; // 29 information request 523#endif 524 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1 525 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2 526 default: 527 break; 528 } 529 return NULL; 530} 531 532#endif 533 534void 535Host::WillTerminate () 536{ 537} 538 539#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) // see macosx/Host.mm 540 541void 542Host::ThreadCreated (const char *thread_name) 543{ 544} 545 546void 547Host::Backtrace (Stream &strm, uint32_t max_frames) 548{ 549 // TODO: Is there a way to backtrace the current process on other systems? 550} 551 552size_t 553Host::GetEnvironment (StringList &env) 554{ 555 // TODO: Is there a way to the host environment for this process on other systems? 556 return 0; 557} 558 559#endif // #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) 560 561struct HostThreadCreateInfo 562{ 563 std::string thread_name; 564 thread_func_t thread_fptr; 565 thread_arg_t thread_arg; 566 567 HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) : 568 thread_name (name ? name : ""), 569 thread_fptr (fptr), 570 thread_arg (arg) 571 { 572 } 573}; 574 575static thread_result_t 576#ifdef _WIN32 577__stdcall 578#endif 579ThreadCreateTrampoline (thread_arg_t arg) 580{ 581 HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg; 582 Host::ThreadCreated (info->thread_name.c_str()); 583 thread_func_t thread_fptr = info->thread_fptr; 584 thread_arg_t thread_arg = info->thread_arg; 585 586 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 587 if (log) 588 log->Printf("thread created"); 589 590 delete info; 591 return thread_fptr (thread_arg); 592} 593 594lldb::thread_t 595Host::ThreadCreate 596( 597 const char *thread_name, 598 thread_func_t thread_fptr, 599 thread_arg_t thread_arg, 600 Error *error 601) 602{ 603 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; 604 605 // Host::ThreadCreateTrampoline will delete this pointer for us. 606 HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg); 607 608#ifdef _WIN32 609 thread = ::_beginthreadex(0, 0, ThreadCreateTrampoline, info_ptr, 0, NULL); 610 int err = thread <= 0 ? GetLastError() : 0; 611#else 612 int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr); 613#endif 614 if (err == 0) 615 { 616 if (error) 617 error->Clear(); 618 return thread; 619 } 620 621 if (error) 622 error->SetError (err, eErrorTypePOSIX); 623 624 return LLDB_INVALID_HOST_THREAD; 625} 626 627#ifndef _WIN32 628 629bool 630Host::ThreadCancel (lldb::thread_t thread, Error *error) 631{ 632 int err = ::pthread_cancel (thread); 633 if (error) 634 error->SetError(err, eErrorTypePOSIX); 635 return err == 0; 636} 637 638bool 639Host::ThreadDetach (lldb::thread_t thread, Error *error) 640{ 641 int err = ::pthread_detach (thread); 642 if (error) 643 error->SetError(err, eErrorTypePOSIX); 644 return err == 0; 645} 646 647bool 648Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error) 649{ 650 int err = ::pthread_join (thread, thread_result_ptr); 651 if (error) 652 error->SetError(err, eErrorTypePOSIX); 653 return err == 0; 654} 655 656lldb::thread_key_t 657Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) 658{ 659 pthread_key_t key; 660 ::pthread_key_create (&key, callback); 661 return key; 662} 663 664void* 665Host::ThreadLocalStorageGet(lldb::thread_key_t key) 666{ 667 return ::pthread_getspecific (key); 668} 669 670void 671Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) 672{ 673 ::pthread_setspecific (key, value); 674} 675 676bool 677Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name) 678{ 679#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 680 lldb::pid_t curr_pid = Host::GetCurrentProcessID(); 681 lldb::tid_t curr_tid = Host::GetCurrentThreadID(); 682 if (pid == LLDB_INVALID_PROCESS_ID) 683 pid = curr_pid; 684 685 if (tid == LLDB_INVALID_THREAD_ID) 686 tid = curr_tid; 687 688 // Set the pthread name if possible 689 if (pid == curr_pid && tid == curr_tid) 690 { 691 if (::pthread_setname_np (name) == 0) 692 return true; 693 } 694 return false; 695#elif defined (__FreeBSD__) 696 lldb::pid_t curr_pid = Host::GetCurrentProcessID(); 697 lldb::tid_t curr_tid = Host::GetCurrentThreadID(); 698 if (pid == LLDB_INVALID_PROCESS_ID) 699 pid = curr_pid; 700 701 if (tid == LLDB_INVALID_THREAD_ID) 702 tid = curr_tid; 703 704 // Set the pthread name if possible 705 if (pid == curr_pid && tid == curr_tid) 706 { 707 ::pthread_set_name_np (::pthread_self(), name); 708 return true; 709 } 710 return false; 711#elif defined (__linux__) || defined (__GLIBC__) 712 void *fn = dlsym (RTLD_DEFAULT, "pthread_setname_np"); 713 if (fn) 714 { 715 lldb::pid_t curr_pid = Host::GetCurrentProcessID(); 716 lldb::tid_t curr_tid = Host::GetCurrentThreadID(); 717 if (pid == LLDB_INVALID_PROCESS_ID) 718 pid = curr_pid; 719 720 if (tid == LLDB_INVALID_THREAD_ID) 721 tid = curr_tid; 722 723 if (pid == curr_pid && tid == curr_tid) 724 { 725 int (*pthread_setname_np_func)(pthread_t thread, const char *name); 726 *reinterpret_cast<void **> (&pthread_setname_np_func) = fn; 727 728 if (pthread_setname_np_func (::pthread_self(), name) == 0) 729 return true; 730 } 731 } 732 return false; 733#else 734 return false; 735#endif 736} 737 738bool 739Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, 740 const char *thread_name, size_t len) 741{ 742 char *namebuf = (char *)::malloc (len + 1); 743 744 // Thread names are coming in like '<lldb.comm.debugger.edit>' and 745 // '<lldb.comm.debugger.editline>'. So just chopping the end of the string 746 // off leads to a lot of similar named threads. Go through the thread name 747 // and search for the last dot and use that. 748 const char *lastdot = ::strrchr (thread_name, '.'); 749 750 if (lastdot && lastdot != thread_name) 751 thread_name = lastdot + 1; 752 ::strncpy (namebuf, thread_name, len); 753 namebuf[len] = 0; 754 755 int namebuflen = strlen(namebuf); 756 if (namebuflen > 0) 757 { 758 if (namebuf[namebuflen - 1] == '(' || namebuf[namebuflen - 1] == '>') 759 { 760 // Trim off trailing '(' and '>' characters for a bit more cleanup. 761 namebuflen--; 762 namebuf[namebuflen] = 0; 763 } 764 return Host::SetThreadName (pid, tid, namebuf); 765 } 766 767 ::free(namebuf); 768 return false; 769} 770 771#endif 772 773FileSpec 774Host::GetProgramFileSpec () 775{ 776 static FileSpec g_program_filespec; 777 if (!g_program_filespec) 778 { 779#if defined (__APPLE__) 780 char program_fullpath[PATH_MAX]; 781 // If DST is NULL, then return the number of bytes needed. 782 uint32_t len = sizeof(program_fullpath); 783 int err = _NSGetExecutablePath (program_fullpath, &len); 784 if (err == 0) 785 g_program_filespec.SetFile (program_fullpath, false); 786 else if (err == -1) 787 { 788 char *large_program_fullpath = (char *)::malloc (len + 1); 789 790 err = _NSGetExecutablePath (large_program_fullpath, &len); 791 if (err == 0) 792 g_program_filespec.SetFile (large_program_fullpath, false); 793 794 ::free (large_program_fullpath); 795 } 796#elif defined (__linux__) 797 char exe_path[PATH_MAX]; 798 ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); 799 if (len > 0) { 800 exe_path[len] = 0; 801 g_program_filespec.SetFile(exe_path, false); 802 } 803#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 804 int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() }; 805 size_t exe_path_size; 806 if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) 807 { 808 char *exe_path = new char[exe_path_size]; 809 if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) 810 g_program_filespec.SetFile(exe_path, false); 811 delete[] exe_path; 812 } 813#endif 814 } 815 return g_program_filespec; 816} 817 818#if !defined (__APPLE__) // see Host.mm 819 820bool 821Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) 822{ 823 bundle.Clear(); 824 return false; 825} 826 827bool 828Host::ResolveExecutableInBundle (FileSpec &file) 829{ 830 return false; 831} 832#endif 833 834#ifndef _WIN32 835 836// Opaque info that tracks a dynamic library that was loaded 837struct DynamicLibraryInfo 838{ 839 DynamicLibraryInfo (const FileSpec &fs, int o, void *h) : 840 file_spec (fs), 841 open_options (o), 842 handle (h) 843 { 844 } 845 846 const FileSpec file_spec; 847 uint32_t open_options; 848 void * handle; 849}; 850 851void * 852Host::DynamicLibraryOpen (const FileSpec &file_spec, uint32_t options, Error &error) 853{ 854 char path[PATH_MAX]; 855 if (file_spec.GetPath(path, sizeof(path))) 856 { 857 int mode = 0; 858 859 if (options & eDynamicLibraryOpenOptionLazy) 860 mode |= RTLD_LAZY; 861 else 862 mode |= RTLD_NOW; 863 864 865 if (options & eDynamicLibraryOpenOptionLocal) 866 mode |= RTLD_LOCAL; 867 else 868 mode |= RTLD_GLOBAL; 869 870#ifdef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 871 if (options & eDynamicLibraryOpenOptionLimitGetSymbol) 872 mode |= RTLD_FIRST; 873#endif 874 875 void * opaque = ::dlopen (path, mode); 876 877 if (opaque) 878 { 879 error.Clear(); 880 return new DynamicLibraryInfo (file_spec, options, opaque); 881 } 882 else 883 { 884 error.SetErrorString(::dlerror()); 885 } 886 } 887 else 888 { 889 error.SetErrorString("failed to extract path"); 890 } 891 return NULL; 892} 893 894Error 895Host::DynamicLibraryClose (void *opaque) 896{ 897 Error error; 898 if (opaque == NULL) 899 { 900 error.SetErrorString ("invalid dynamic library handle"); 901 } 902 else 903 { 904 DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; 905 if (::dlclose (dylib_info->handle) != 0) 906 { 907 error.SetErrorString(::dlerror()); 908 } 909 910 dylib_info->open_options = 0; 911 dylib_info->handle = 0; 912 delete dylib_info; 913 } 914 return error; 915} 916 917void * 918Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &error) 919{ 920 if (opaque == NULL) 921 { 922 error.SetErrorString ("invalid dynamic library handle"); 923 } 924 else 925 { 926 DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque; 927 928 void *symbol_addr = ::dlsym (dylib_info->handle, symbol_name); 929 if (symbol_addr) 930 { 931#ifndef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 932 // This host doesn't support limiting searches to this shared library 933 // so we need to verify that the match came from this shared library 934 // if it was requested in the Host::DynamicLibraryOpen() function. 935 if (dylib_info->open_options & eDynamicLibraryOpenOptionLimitGetSymbol) 936 { 937 FileSpec match_dylib_spec (Host::GetModuleFileSpecForHostAddress (symbol_addr)); 938 if (match_dylib_spec != dylib_info->file_spec) 939 { 940 char dylib_path[PATH_MAX]; 941 if (dylib_info->file_spec.GetPath (dylib_path, sizeof(dylib_path))) 942 error.SetErrorStringWithFormat ("symbol not found in \"%s\"", dylib_path); 943 else 944 error.SetErrorString ("symbol not found"); 945 return NULL; 946 } 947 } 948#endif 949 error.Clear(); 950 return symbol_addr; 951 } 952 else 953 { 954 error.SetErrorString(::dlerror()); 955 } 956 } 957 return NULL; 958} 959 960FileSpec 961Host::GetModuleFileSpecForHostAddress (const void *host_addr) 962{ 963 FileSpec module_filespec; 964 Dl_info info; 965 if (::dladdr (host_addr, &info)) 966 { 967 if (info.dli_fname) 968 module_filespec.SetFile(info.dli_fname, true); 969 } 970 return module_filespec; 971} 972 973#endif 974 975bool 976Host::GetLLDBPath (PathType path_type, FileSpec &file_spec) 977{ 978 // To get paths related to LLDB we get the path to the executable that 979 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", 980 // on linux this is assumed to be the "lldb" main executable. If LLDB on 981 // linux is actually in a shared library (liblldb.so) then this function will 982 // need to be modified to "do the right thing". 983 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST); 984 985 switch (path_type) 986 { 987 case ePathTypeLLDBShlibDir: 988 { 989 static ConstString g_lldb_so_dir; 990 if (!g_lldb_so_dir) 991 { 992 FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath)); 993 g_lldb_so_dir = lldb_file_spec.GetDirectory(); 994 if (log) 995 log->Printf("Host::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_lldb_so_dir.GetCString()); 996 } 997 file_spec.GetDirectory() = g_lldb_so_dir; 998 return (bool)file_spec.GetDirectory(); 999 } 1000 break; 1001 1002 case ePathTypeSupportExecutableDir: 1003 { 1004 static ConstString g_lldb_support_exe_dir; 1005 if (!g_lldb_support_exe_dir) 1006 { 1007 FileSpec lldb_file_spec; 1008 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 1009 { 1010 char raw_path[PATH_MAX]; 1011 char resolved_path[PATH_MAX]; 1012 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 1013 1014#if defined (__APPLE__) 1015 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 1016 if (framework_pos) 1017 { 1018 framework_pos += strlen("LLDB.framework"); 1019#if defined (__arm__) 1020 // Shallow bundle 1021 *framework_pos = '\0'; 1022#else 1023 // Normal bundle 1024 ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path)); 1025#endif 1026 } 1027#endif 1028 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 1029 g_lldb_support_exe_dir.SetCString(resolved_path); 1030 } 1031 if (log) 1032 log->Printf("Host::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", g_lldb_support_exe_dir.GetCString()); 1033 } 1034 file_spec.GetDirectory() = g_lldb_support_exe_dir; 1035 return (bool)file_spec.GetDirectory(); 1036 } 1037 break; 1038 1039 case ePathTypeHeaderDir: 1040 { 1041 static ConstString g_lldb_headers_dir; 1042 if (!g_lldb_headers_dir) 1043 { 1044#if defined (__APPLE__) 1045 FileSpec lldb_file_spec; 1046 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 1047 { 1048 char raw_path[PATH_MAX]; 1049 char resolved_path[PATH_MAX]; 1050 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 1051 1052 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 1053 if (framework_pos) 1054 { 1055 framework_pos += strlen("LLDB.framework"); 1056 ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path)); 1057 } 1058 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 1059 g_lldb_headers_dir.SetCString(resolved_path); 1060 } 1061#else 1062 // TODO: Anyone know how we can determine this for linux? Other systems?? 1063 g_lldb_headers_dir.SetCString ("/opt/local/include/lldb"); 1064#endif 1065 if (log) 1066 log->Printf("Host::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_lldb_headers_dir.GetCString()); 1067 } 1068 file_spec.GetDirectory() = g_lldb_headers_dir; 1069 return (bool)file_spec.GetDirectory(); 1070 } 1071 break; 1072 1073#ifdef LLDB_DISABLE_PYTHON 1074 case ePathTypePythonDir: 1075 return false; 1076#else 1077 case ePathTypePythonDir: 1078 { 1079 static ConstString g_lldb_python_dir; 1080 if (!g_lldb_python_dir) 1081 { 1082 FileSpec lldb_file_spec; 1083 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 1084 { 1085 char raw_path[PATH_MAX]; 1086 char resolved_path[PATH_MAX]; 1087 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 1088 1089#if defined (__APPLE__) 1090 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 1091 if (framework_pos) 1092 { 1093 framework_pos += strlen("LLDB.framework"); 1094 ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path)); 1095 } 1096#else 1097 llvm::SmallString<256> python_version_dir; 1098 llvm::raw_svector_ostream os(python_version_dir); 1099 os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages"; 1100 os.flush(); 1101 1102 // We may get our string truncated. Should we protect 1103 // this with an assert? 1104 1105 ::strncat(raw_path, python_version_dir.c_str(), 1106 sizeof(raw_path) - strlen(raw_path) - 1); 1107 1108#endif 1109 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 1110 g_lldb_python_dir.SetCString(resolved_path); 1111 } 1112 1113 if (log) 1114 log->Printf("Host::GetLLDBPath(ePathTypePythonDir) => '%s'", g_lldb_python_dir.GetCString()); 1115 1116 } 1117 file_spec.GetDirectory() = g_lldb_python_dir; 1118 return (bool)file_spec.GetDirectory(); 1119 } 1120 break; 1121#endif 1122 1123 case ePathTypeLLDBSystemPlugins: // System plug-ins directory 1124 { 1125#if defined (__APPLE__) || defined(__linux__) 1126 static ConstString g_lldb_system_plugin_dir; 1127 static bool g_lldb_system_plugin_dir_located = false; 1128 if (!g_lldb_system_plugin_dir_located) 1129 { 1130 g_lldb_system_plugin_dir_located = true; 1131#if defined (__APPLE__) 1132 FileSpec lldb_file_spec; 1133 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) 1134 { 1135 char raw_path[PATH_MAX]; 1136 char resolved_path[PATH_MAX]; 1137 lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); 1138 1139 char *framework_pos = ::strstr (raw_path, "LLDB.framework"); 1140 if (framework_pos) 1141 { 1142 framework_pos += strlen("LLDB.framework"); 1143 ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path)); 1144 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); 1145 g_lldb_system_plugin_dir.SetCString(resolved_path); 1146 } 1147 return false; 1148 } 1149#elif defined (__linux__) 1150 FileSpec lldb_file_spec("/usr/lib/lldb", true); 1151 if (lldb_file_spec.Exists()) 1152 { 1153 g_lldb_system_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str()); 1154 } 1155#endif // __APPLE__ || __linux__ 1156 1157 if (log) 1158 log->Printf("Host::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", g_lldb_system_plugin_dir.GetCString()); 1159 1160 } 1161 1162 if (g_lldb_system_plugin_dir) 1163 { 1164 file_spec.GetDirectory() = g_lldb_system_plugin_dir; 1165 return true; 1166 } 1167#else 1168 // TODO: where would system LLDB plug-ins be located on other systems? 1169 return false; 1170#endif 1171 } 1172 break; 1173 1174 case ePathTypeLLDBUserPlugins: // User plug-ins directory 1175 { 1176#if defined (__APPLE__) 1177 static ConstString g_lldb_user_plugin_dir; 1178 if (!g_lldb_user_plugin_dir) 1179 { 1180 char user_plugin_path[PATH_MAX]; 1181 if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns", 1182 user_plugin_path, 1183 sizeof(user_plugin_path))) 1184 { 1185 g_lldb_user_plugin_dir.SetCString(user_plugin_path); 1186 } 1187 } 1188 file_spec.GetDirectory() = g_lldb_user_plugin_dir; 1189 return (bool)file_spec.GetDirectory(); 1190#elif defined (__linux__) 1191 static ConstString g_lldb_user_plugin_dir; 1192 if (!g_lldb_user_plugin_dir) 1193 { 1194 // XDG Base Directory Specification 1195 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 1196 // If XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb. 1197 FileSpec lldb_file_spec; 1198 const char *xdg_data_home = getenv("XDG_DATA_HOME"); 1199 if (xdg_data_home && xdg_data_home[0]) 1200 { 1201 std::string user_plugin_dir (xdg_data_home); 1202 user_plugin_dir += "/lldb"; 1203 lldb_file_spec.SetFile (user_plugin_dir.c_str(), true); 1204 } 1205 else 1206 { 1207 const char *home_dir = getenv("HOME"); 1208 if (home_dir && home_dir[0]) 1209 { 1210 std::string user_plugin_dir (home_dir); 1211 user_plugin_dir += "/.local/share/lldb"; 1212 lldb_file_spec.SetFile (user_plugin_dir.c_str(), true); 1213 } 1214 } 1215 1216 if (lldb_file_spec.Exists()) 1217 g_lldb_user_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str()); 1218 if (log) 1219 log->Printf("Host::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", g_lldb_user_plugin_dir.GetCString()); 1220 } 1221 file_spec.GetDirectory() = g_lldb_user_plugin_dir; 1222 return (bool)file_spec.GetDirectory(); 1223#endif 1224 // TODO: where would user LLDB plug-ins be located on other systems? 1225 return false; 1226 } 1227 } 1228 1229 return false; 1230} 1231 1232 1233bool 1234Host::GetHostname (std::string &s) 1235{ 1236 char hostname[PATH_MAX]; 1237 hostname[sizeof(hostname) - 1] = '\0'; 1238 if (::gethostname (hostname, sizeof(hostname) - 1) == 0) 1239 { 1240 struct hostent* h = ::gethostbyname (hostname); 1241 if (h) 1242 s.assign (h->h_name); 1243 else 1244 s.assign (hostname); 1245 return true; 1246 } 1247 return false; 1248} 1249 1250#ifndef _WIN32 1251 1252const char * 1253Host::GetUserName (uint32_t uid, std::string &user_name) 1254{ 1255 struct passwd user_info; 1256 struct passwd *user_info_ptr = &user_info; 1257 char user_buffer[PATH_MAX]; 1258 size_t user_buffer_size = sizeof(user_buffer); 1259 if (::getpwuid_r (uid, 1260 &user_info, 1261 user_buffer, 1262 user_buffer_size, 1263 &user_info_ptr) == 0) 1264 { 1265 if (user_info_ptr) 1266 { 1267 user_name.assign (user_info_ptr->pw_name); 1268 return user_name.c_str(); 1269 } 1270 } 1271 user_name.clear(); 1272 return NULL; 1273} 1274 1275const char * 1276Host::GetGroupName (uint32_t gid, std::string &group_name) 1277{ 1278 char group_buffer[PATH_MAX]; 1279 size_t group_buffer_size = sizeof(group_buffer); 1280 struct group group_info; 1281 struct group *group_info_ptr = &group_info; 1282 // Try the threadsafe version first 1283 if (::getgrgid_r (gid, 1284 &group_info, 1285 group_buffer, 1286 group_buffer_size, 1287 &group_info_ptr) == 0) 1288 { 1289 if (group_info_ptr) 1290 { 1291 group_name.assign (group_info_ptr->gr_name); 1292 return group_name.c_str(); 1293 } 1294 } 1295 else 1296 { 1297 // The threadsafe version isn't currently working 1298 // for me on darwin, but the non-threadsafe version 1299 // is, so I am calling it below. 1300 group_info_ptr = ::getgrgid (gid); 1301 if (group_info_ptr) 1302 { 1303 group_name.assign (group_info_ptr->gr_name); 1304 return group_name.c_str(); 1305 } 1306 } 1307 group_name.clear(); 1308 return NULL; 1309} 1310 1311uint32_t 1312Host::GetUserID () 1313{ 1314 return getuid(); 1315} 1316 1317uint32_t 1318Host::GetGroupID () 1319{ 1320 return getgid(); 1321} 1322 1323uint32_t 1324Host::GetEffectiveUserID () 1325{ 1326 return geteuid(); 1327} 1328 1329uint32_t 1330Host::GetEffectiveGroupID () 1331{ 1332 return getegid(); 1333} 1334 1335#endif 1336 1337#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) // see macosx/Host.mm 1338bool 1339Host::GetOSBuildString (std::string &s) 1340{ 1341 s.clear(); 1342 return false; 1343} 1344 1345bool 1346Host::GetOSKernelDescription (std::string &s) 1347{ 1348 s.clear(); 1349 return false; 1350} 1351#endif 1352 1353#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined(__linux__) 1354uint32_t 1355Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 1356{ 1357 process_infos.Clear(); 1358 return process_infos.GetSize(); 1359} 1360 1361bool 1362Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 1363{ 1364 process_info.Clear(); 1365 return false; 1366} 1367#endif 1368 1369#if !defined(__linux__) 1370bool 1371Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) 1372{ 1373 return false; 1374} 1375#endif 1376 1377lldb::TargetSP 1378Host::GetDummyTarget (lldb_private::Debugger &debugger) 1379{ 1380 static TargetSP g_dummy_target_sp; 1381 1382 // FIXME: Maybe the dummy target should be per-Debugger 1383 if (!g_dummy_target_sp || !g_dummy_target_sp->IsValid()) 1384 { 1385 ArchSpec arch(Target::GetDefaultArchitecture()); 1386 if (!arch.IsValid()) 1387 arch = Host::GetArchitecture (); 1388 Error err = debugger.GetTargetList().CreateTarget(debugger, 1389 NULL, 1390 arch.GetTriple().getTriple().c_str(), 1391 false, 1392 NULL, 1393 g_dummy_target_sp); 1394 } 1395 1396 return g_dummy_target_sp; 1397} 1398 1399struct ShellInfo 1400{ 1401 ShellInfo () : 1402 process_reaped (false), 1403 can_delete (false), 1404 pid (LLDB_INVALID_PROCESS_ID), 1405 signo(-1), 1406 status(-1) 1407 { 1408 } 1409 1410 lldb_private::Predicate<bool> process_reaped; 1411 lldb_private::Predicate<bool> can_delete; 1412 lldb::pid_t pid; 1413 int signo; 1414 int status; 1415}; 1416 1417static bool 1418MonitorShellCommand (void *callback_baton, 1419 lldb::pid_t pid, 1420 bool exited, // True if the process did exit 1421 int signo, // Zero for no signal 1422 int status) // Exit value of process if signal is zero 1423{ 1424 ShellInfo *shell_info = (ShellInfo *)callback_baton; 1425 shell_info->pid = pid; 1426 shell_info->signo = signo; 1427 shell_info->status = status; 1428 // Let the thread running Host::RunShellCommand() know that the process 1429 // exited and that ShellInfo has been filled in by broadcasting to it 1430 shell_info->process_reaped.SetValue(1, eBroadcastAlways); 1431 // Now wait for a handshake back from that thread running Host::RunShellCommand 1432 // so we know that we can delete shell_info_ptr 1433 shell_info->can_delete.WaitForValueEqualTo(true); 1434 // Sleep a bit to allow the shell_info->can_delete.SetValue() to complete... 1435 usleep(1000); 1436 // Now delete the shell info that was passed into this function 1437 delete shell_info; 1438 return true; 1439} 1440 1441Error 1442Host::RunShellCommand (const char *command, 1443 const char *working_dir, 1444 int *status_ptr, 1445 int *signo_ptr, 1446 std::string *command_output_ptr, 1447 uint32_t timeout_sec, 1448 const char *shell) 1449{ 1450 Error error; 1451 ProcessLaunchInfo launch_info; 1452 if (shell && shell[0]) 1453 { 1454 // Run the command in a shell 1455 launch_info.SetShell(shell); 1456 launch_info.GetArguments().AppendArgument(command); 1457 const bool localhost = true; 1458 const bool will_debug = false; 1459 const bool first_arg_is_full_shell_command = true; 1460 launch_info.ConvertArgumentsForLaunchingInShell (error, 1461 localhost, 1462 will_debug, 1463 first_arg_is_full_shell_command, 1464 0); 1465 } 1466 else 1467 { 1468 // No shell, just run it 1469 Args args (command); 1470 const bool first_arg_is_executable = true; 1471 launch_info.SetArguments(args, first_arg_is_executable); 1472 } 1473 1474 if (working_dir) 1475 launch_info.SetWorkingDirectory(working_dir); 1476 char output_file_path_buffer[L_tmpnam]; 1477 const char *output_file_path = NULL; 1478 if (command_output_ptr) 1479 { 1480 // Create a temporary file to get the stdout/stderr and redirect the 1481 // output of the command into this file. We will later read this file 1482 // if all goes well and fill the data into "command_output_ptr" 1483 output_file_path = ::tmpnam(output_file_path_buffer); 1484 launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); 1485 launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path, false, true); 1486 launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); 1487 } 1488 else 1489 { 1490 launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); 1491 launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); 1492 launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); 1493 } 1494 1495 // The process monitor callback will delete the 'shell_info_ptr' below... 1496 std::unique_ptr<ShellInfo> shell_info_ap (new ShellInfo()); 1497 1498 const bool monitor_signals = false; 1499 launch_info.SetMonitorProcessCallback(MonitorShellCommand, shell_info_ap.get(), monitor_signals); 1500 1501 error = LaunchProcess (launch_info); 1502 const lldb::pid_t pid = launch_info.GetProcessID(); 1503 1504 if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) 1505 error.SetErrorString("failed to get process ID"); 1506 1507 if (error.Success()) 1508 { 1509 // The process successfully launched, so we can defer ownership of 1510 // "shell_info" to the MonitorShellCommand callback function that will 1511 // get called when the process dies. We release the unique pointer as it 1512 // doesn't need to delete the ShellInfo anymore. 1513 ShellInfo *shell_info = shell_info_ap.release(); 1514 TimeValue *timeout_ptr = nullptr; 1515 TimeValue timeout_time(TimeValue::Now()); 1516 if (timeout_sec > 0) { 1517 timeout_time.OffsetWithSeconds(timeout_sec); 1518 timeout_ptr = &timeout_time; 1519 } 1520 bool timed_out = false; 1521 shell_info->process_reaped.WaitForValueEqualTo(true, timeout_ptr, &timed_out); 1522 if (timed_out) 1523 { 1524 error.SetErrorString("timed out waiting for shell command to complete"); 1525 1526 // Kill the process since it didn't complete withint the timeout specified 1527 Kill (pid, SIGKILL); 1528 // Wait for the monitor callback to get the message 1529 timeout_time = TimeValue::Now(); 1530 timeout_time.OffsetWithSeconds(1); 1531 timed_out = false; 1532 shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out); 1533 } 1534 else 1535 { 1536 if (status_ptr) 1537 *status_ptr = shell_info->status; 1538 1539 if (signo_ptr) 1540 *signo_ptr = shell_info->signo; 1541 1542 if (command_output_ptr) 1543 { 1544 command_output_ptr->clear(); 1545 FileSpec file_spec(output_file_path, File::eOpenOptionRead); 1546 uint64_t file_size = file_spec.GetByteSize(); 1547 if (file_size > 0) 1548 { 1549 if (file_size > command_output_ptr->max_size()) 1550 { 1551 error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string"); 1552 } 1553 else 1554 { 1555 command_output_ptr->resize(file_size); 1556 file_spec.ReadFileContents(0, &((*command_output_ptr)[0]), command_output_ptr->size(), &error); 1557 } 1558 } 1559 } 1560 } 1561 shell_info->can_delete.SetValue(true, eBroadcastAlways); 1562 } 1563 1564 if (output_file_path) 1565 ::unlink (output_file_path); 1566 // Handshake with the monitor thread, or just let it know in advance that 1567 // it can delete "shell_info" in case we timed out and were not able to kill 1568 // the process... 1569 return error; 1570} 1571 1572#if defined(__linux__) || defined(__FreeBSD__) 1573// The functions below implement process launching via posix_spawn() for Linux 1574// and FreeBSD. 1575 1576// The posix_spawn() and posix_spawnp() functions first appeared in FreeBSD 8.0, 1577static Error 1578LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid) 1579{ 1580 Error error; 1581 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); 1582 1583 assert(exe_path); 1584 assert(!launch_info.GetFlags().Test (eLaunchFlagDebug)); 1585 1586 posix_spawnattr_t attr; 1587 1588 error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX); 1589 error.LogIfError(log, "::posix_spawnattr_init ( &attr )"); 1590 if (error.Fail()) 1591 return error; 1592 1593 // Make a quick class that will cleanup the posix spawn attributes in case 1594 // we return in the middle of this function. 1595 lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy); 1596 1597 sigset_t no_signals; 1598 sigset_t all_signals; 1599 sigemptyset (&no_signals); 1600 sigfillset (&all_signals); 1601 ::posix_spawnattr_setsigmask(&attr, &all_signals); 1602 ::posix_spawnattr_setsigdefault(&attr, &no_signals); 1603 1604 short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; 1605 1606 error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); 1607 error.LogIfError(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); 1608 if (error.Fail()) 1609 return error; 1610 1611 const size_t num_file_actions = launch_info.GetNumFileActions (); 1612 posix_spawn_file_actions_t file_actions, *file_action_ptr = NULL; 1613 // Make a quick class that will cleanup the posix spawn attributes in case 1614 // we return in the middle of this function. 1615 lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> 1616 posix_spawn_file_actions_cleanup (file_action_ptr, NULL, posix_spawn_file_actions_destroy); 1617 1618 if (num_file_actions > 0) 1619 { 1620 error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX); 1621 error.LogIfError(log, "::posix_spawn_file_actions_init ( &file_actions )"); 1622 if (error.Fail()) 1623 return error; 1624 1625 file_action_ptr = &file_actions; 1626 posix_spawn_file_actions_cleanup.set(file_action_ptr); 1627 1628 for (size_t i = 0; i < num_file_actions; ++i) 1629 { 1630 const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i); 1631 if (launch_file_action && 1632 !ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions, 1633 launch_file_action, 1634 log, 1635 error)) 1636 return error; 1637 } 1638 } 1639 1640 // Change working directory if neccessary. 1641 char current_dir[PATH_MAX]; 1642 current_dir[0] = '\0'; 1643 1644 const char *working_dir = launch_info.GetWorkingDirectory(); 1645 if (working_dir != NULL) 1646 { 1647 if (::getcwd(current_dir, sizeof(current_dir)) == NULL) 1648 { 1649 error.SetError(errno, eErrorTypePOSIX); 1650 error.LogIfError(log, "unable to save the current directory"); 1651 return error; 1652 } 1653 1654 if (::chdir(working_dir) == -1) 1655 { 1656 error.SetError(errno, eErrorTypePOSIX); 1657 error.LogIfError(log, "unable to change working directory to %s", working_dir); 1658 return error; 1659 } 1660 } 1661 1662 const char *tmp_argv[2]; 1663 char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector(); 1664 char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector(); 1665 1666 // Prepare minimal argument list if we didn't get it from the launch_info structure. 1667 // We must pass argv into posix_spawnp and it must contain at least two items - 1668 // pointer to an executable and NULL. 1669 if (argv == NULL) 1670 { 1671 tmp_argv[0] = exe_path; 1672 tmp_argv[1] = NULL; 1673 argv = (char * const*)tmp_argv; 1674 } 1675 1676 error.SetError (::posix_spawnp (&pid, 1677 exe_path, 1678 (num_file_actions > 0) ? &file_actions : NULL, 1679 &attr, 1680 argv, 1681 envp), 1682 eErrorTypePOSIX); 1683 1684 error.LogIfError(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", 1685 pid, exe_path, file_action_ptr, &attr, argv, envp); 1686 1687 // Change back the current directory. 1688 // NOTE: do not override previously established error from posix_spawnp. 1689 if (working_dir != NULL && ::chdir(current_dir) == -1 && error.Success()) 1690 { 1691 error.SetError(errno, eErrorTypePOSIX); 1692 error.LogIfError(log, "unable to change current directory back to %s", 1693 current_dir); 1694 } 1695 1696 return error; 1697} 1698 1699 1700Error 1701Host::LaunchProcess (ProcessLaunchInfo &launch_info) 1702{ 1703 Error error; 1704 char exe_path[PATH_MAX]; 1705 1706 PlatformSP host_platform_sp (Platform::GetDefaultPlatform ()); 1707 1708 const ArchSpec &arch_spec = launch_info.GetArchitecture(); 1709 1710 FileSpec exe_spec(launch_info.GetExecutableFile()); 1711 1712 FileSpec::FileType file_type = exe_spec.GetFileType(); 1713 if (file_type != FileSpec::eFileTypeRegular) 1714 { 1715 lldb::ModuleSP exe_module_sp; 1716 error = host_platform_sp->ResolveExecutable (exe_spec, 1717 arch_spec, 1718 exe_module_sp, 1719 NULL); 1720 1721 if (error.Fail()) 1722 return error; 1723 1724 if (exe_module_sp) 1725 exe_spec = exe_module_sp->GetFileSpec(); 1726 } 1727 1728 if (exe_spec.Exists()) 1729 { 1730 exe_spec.GetPath (exe_path, sizeof(exe_path)); 1731 } 1732 else 1733 { 1734 launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path)); 1735 error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path); 1736 return error; 1737 } 1738 1739 assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)); 1740 1741 ::pid_t pid = LLDB_INVALID_PROCESS_ID; 1742 1743 error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); 1744 1745 if (pid != LLDB_INVALID_PROCESS_ID) 1746 { 1747 // If all went well, then set the process ID into the launch info 1748 launch_info.SetProcessID(pid); 1749 1750 // Make sure we reap any processes we spawn or we will have zombies. 1751 if (!launch_info.MonitorProcess()) 1752 { 1753 const bool monitor_signals = false; 1754 StartMonitoringChildProcess (Process::SetProcessExitStatus, 1755 NULL, 1756 pid, 1757 monitor_signals); 1758 } 1759 } 1760 else 1761 { 1762 // Invalid process ID, something didn't go well 1763 if (error.Success()) 1764 error.SetErrorString ("process launch failed for unknown reasons"); 1765 } 1766 return error; 1767} 1768 1769#endif // defined(__linux__) or defined(__FreeBSD__) 1770 1771#ifndef _WIN32 1772 1773size_t 1774Host::GetPageSize() 1775{ 1776 return ::getpagesize(); 1777} 1778 1779uint32_t 1780Host::GetNumberCPUS () 1781{ 1782 static uint32_t g_num_cores = UINT32_MAX; 1783 if (g_num_cores == UINT32_MAX) 1784 { 1785#if defined(__APPLE__) or defined (__linux__) or defined (__FreeBSD__) or defined (__FreeBSD_kernel__) 1786 1787 g_num_cores = ::sysconf(_SC_NPROCESSORS_ONLN); 1788 1789#else 1790 1791 // Assume POSIX support if a host specific case has not been supplied above 1792 g_num_cores = 0; 1793 int num_cores = 0; 1794 size_t num_cores_len = sizeof(num_cores); 1795#ifdef HW_AVAILCPU 1796 int mib[] = { CTL_HW, HW_AVAILCPU }; 1797#else 1798 int mib[] = { CTL_HW, HW_NCPU }; 1799#endif 1800 1801 /* get the number of CPUs from the system */ 1802 if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0)) 1803 { 1804 g_num_cores = num_cores; 1805 } 1806 else 1807 { 1808 mib[1] = HW_NCPU; 1809 num_cores_len = sizeof(num_cores); 1810 if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0)) 1811 { 1812 if (num_cores > 0) 1813 g_num_cores = num_cores; 1814 } 1815 } 1816#endif 1817 } 1818 return g_num_cores; 1819} 1820 1821void 1822Host::Kill(lldb::pid_t pid, int signo) 1823{ 1824 ::kill(pid, signo); 1825} 1826 1827#endif 1828 1829#if !defined (__APPLE__) 1830bool 1831Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) 1832{ 1833 return false; 1834} 1835 1836void 1837Host::SetCrashDescriptionWithFormat (const char *format, ...) 1838{ 1839} 1840 1841void 1842Host::SetCrashDescription (const char *description) 1843{ 1844} 1845 1846lldb::pid_t 1847Host::LaunchApplication (const FileSpec &app_file_spec) 1848{ 1849 return LLDB_INVALID_PROCESS_ID; 1850} 1851 1852#endif 1853 1854 1855#ifdef LLDB_DISABLE_POSIX 1856 1857Error 1858Host::MakeDirectory (const char* path, uint32_t mode) 1859{ 1860 Error error; 1861 error.SetErrorStringWithFormat("%s in not implemented on this host", __PRETTY_FUNCTION__); 1862 return error; 1863} 1864 1865Error 1866Host::GetFilePermissions (const char* path, uint32_t &file_permissions) 1867{ 1868 Error error; 1869 error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__); 1870 return error; 1871} 1872 1873Error 1874Host::SetFilePermissions (const char* path, uint32_t file_permissions) 1875{ 1876 Error error; 1877 error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__); 1878 return error; 1879} 1880 1881Error 1882Host::Symlink (const char *src, const char *dst) 1883{ 1884 Error error; 1885 error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__); 1886 return error; 1887} 1888 1889Error 1890Host::Readlink (const char *path, char *buf, size_t buf_len) 1891{ 1892 Error error; 1893 error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__); 1894 return error; 1895} 1896 1897Error 1898Host::Unlink (const char *path) 1899{ 1900 Error error; 1901 error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__); 1902 return error; 1903} 1904 1905#else 1906 1907Error 1908Host::MakeDirectory (const char* path, uint32_t file_permissions) 1909{ 1910 Error error; 1911 if (path && path[0]) 1912 { 1913 if (::mkdir(path, file_permissions) != 0) 1914 { 1915 error.SetErrorToErrno(); 1916 switch (error.GetError()) 1917 { 1918 case ENOENT: 1919 { 1920 // Parent directory doesn't exist, so lets make it if we can 1921 FileSpec spec(path, false); 1922 if (spec.GetDirectory() && spec.GetFilename()) 1923 { 1924 // Make the parent directory and try again 1925 Error error2 = Host::MakeDirectory(spec.GetDirectory().GetCString(), file_permissions); 1926 if (error2.Success()) 1927 { 1928 // Try and make the directory again now that the parent directory was made successfully 1929 if (::mkdir(path, file_permissions) == 0) 1930 error.Clear(); 1931 else 1932 error.SetErrorToErrno(); 1933 } 1934 } 1935 } 1936 break; 1937 case EEXIST: 1938 { 1939 FileSpec path_spec(path, false); 1940 if (path_spec.IsDirectory()) 1941 error.Clear(); // It is a directory and it already exists 1942 } 1943 break; 1944 } 1945 } 1946 } 1947 else 1948 { 1949 error.SetErrorString("empty path"); 1950 } 1951 return error; 1952} 1953 1954Error 1955Host::GetFilePermissions (const char* path, uint32_t &file_permissions) 1956{ 1957 Error error; 1958 struct stat file_stats; 1959 if (::stat (path, &file_stats) == 0) 1960 { 1961 // The bits in "st_mode" currently match the definitions 1962 // for the file mode bits in unix. 1963 file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 1964 } 1965 else 1966 { 1967 error.SetErrorToErrno(); 1968 } 1969 return error; 1970} 1971 1972Error 1973Host::SetFilePermissions (const char* path, uint32_t file_permissions) 1974{ 1975 Error error; 1976 if (::chmod(path, file_permissions) != 0) 1977 error.SetErrorToErrno(); 1978 return error; 1979} 1980 1981Error 1982Host::Symlink (const char *src, const char *dst) 1983{ 1984 Error error; 1985 if (::symlink(dst, src) == -1) 1986 error.SetErrorToErrno(); 1987 return error; 1988} 1989 1990Error 1991Host::Unlink (const char *path) 1992{ 1993 Error error; 1994 if (::unlink(path) == -1) 1995 error.SetErrorToErrno(); 1996 return error; 1997} 1998 1999Error 2000Host::Readlink (const char *path, char *buf, size_t buf_len) 2001{ 2002 Error error; 2003 ssize_t count = ::readlink(path, buf, buf_len); 2004 if (count < 0) 2005 error.SetErrorToErrno(); 2006 else if (count < (buf_len-1)) 2007 buf[count] = '\0'; // Success 2008 else 2009 error.SetErrorString("'buf' buffer is too small to contain link contents"); 2010 return error; 2011} 2012 2013 2014#endif 2015 2016typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap; 2017FDToFileMap& GetFDToFileMap() 2018{ 2019 static FDToFileMap g_fd2filemap; 2020 return g_fd2filemap; 2021} 2022 2023lldb::user_id_t 2024Host::OpenFile (const FileSpec& file_spec, 2025 uint32_t flags, 2026 uint32_t mode, 2027 Error &error) 2028{ 2029 std::string path (file_spec.GetPath()); 2030 if (path.empty()) 2031 { 2032 error.SetErrorString("empty path"); 2033 return UINT64_MAX; 2034 } 2035 FileSP file_sp(new File()); 2036 error = file_sp->Open(path.c_str(),flags,mode); 2037 if (file_sp->IsValid() == false) 2038 return UINT64_MAX; 2039 lldb::user_id_t fd = file_sp->GetDescriptor(); 2040 GetFDToFileMap()[fd] = file_sp; 2041 return fd; 2042} 2043 2044bool 2045Host::CloseFile (lldb::user_id_t fd, Error &error) 2046{ 2047 if (fd == UINT64_MAX) 2048 { 2049 error.SetErrorString ("invalid file descriptor"); 2050 return false; 2051 } 2052 FDToFileMap& file_map = GetFDToFileMap(); 2053 FDToFileMap::iterator pos = file_map.find(fd); 2054 if (pos == file_map.end()) 2055 { 2056 error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd); 2057 return false; 2058 } 2059 FileSP file_sp = pos->second; 2060 if (!file_sp) 2061 { 2062 error.SetErrorString ("invalid host backing file"); 2063 return false; 2064 } 2065 error = file_sp->Close(); 2066 file_map.erase(pos); 2067 return error.Success(); 2068} 2069 2070uint64_t 2071Host::WriteFile (lldb::user_id_t fd, uint64_t offset, const void* src, uint64_t src_len, Error &error) 2072{ 2073 if (fd == UINT64_MAX) 2074 { 2075 error.SetErrorString ("invalid file descriptor"); 2076 return UINT64_MAX; 2077 } 2078 FDToFileMap& file_map = GetFDToFileMap(); 2079 FDToFileMap::iterator pos = file_map.find(fd); 2080 if (pos == file_map.end()) 2081 { 2082 error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64 , fd); 2083 return false; 2084 } 2085 FileSP file_sp = pos->second; 2086 if (!file_sp) 2087 { 2088 error.SetErrorString ("invalid host backing file"); 2089 return UINT64_MAX; 2090 } 2091 if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail()) 2092 return UINT64_MAX; 2093 size_t bytes_written = src_len; 2094 error = file_sp->Write(src, bytes_written); 2095 if (error.Fail()) 2096 return UINT64_MAX; 2097 return bytes_written; 2098} 2099 2100uint64_t 2101Host::ReadFile (lldb::user_id_t fd, uint64_t offset, void* dst, uint64_t dst_len, Error &error) 2102{ 2103 if (fd == UINT64_MAX) 2104 { 2105 error.SetErrorString ("invalid file descriptor"); 2106 return UINT64_MAX; 2107 } 2108 FDToFileMap& file_map = GetFDToFileMap(); 2109 FDToFileMap::iterator pos = file_map.find(fd); 2110 if (pos == file_map.end()) 2111 { 2112 error.SetErrorStringWithFormat ("invalid host file descriptor %" PRIu64, fd); 2113 return false; 2114 } 2115 FileSP file_sp = pos->second; 2116 if (!file_sp) 2117 { 2118 error.SetErrorString ("invalid host backing file"); 2119 return UINT64_MAX; 2120 } 2121 if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail()) 2122 return UINT64_MAX; 2123 size_t bytes_read = dst_len; 2124 error = file_sp->Read(dst ,bytes_read); 2125 if (error.Fail()) 2126 return UINT64_MAX; 2127 return bytes_read; 2128} 2129 2130lldb::user_id_t 2131Host::GetFileSize (const FileSpec& file_spec) 2132{ 2133 return file_spec.GetByteSize(); 2134} 2135 2136bool 2137Host::GetFileExists (const FileSpec& file_spec) 2138{ 2139 return file_spec.Exists(); 2140} 2141 2142bool 2143Host::CalculateMD5 (const FileSpec& file_spec, 2144 uint64_t &low, 2145 uint64_t &high) 2146{ 2147#if defined (__APPLE__) 2148 StreamString md5_cmd_line; 2149 md5_cmd_line.Printf("md5 -q '%s'", file_spec.GetPath().c_str()); 2150 std::string hash_string; 2151 Error err = Host::RunShellCommand(md5_cmd_line.GetData(), NULL, NULL, NULL, &hash_string, 60); 2152 if (err.Fail()) 2153 return false; 2154 // a correctly formed MD5 is 16-bytes, that is 32 hex digits 2155 // if the output is any other length it is probably wrong 2156 if (hash_string.size() != 32) 2157 return false; 2158 std::string part1(hash_string,0,16); 2159 std::string part2(hash_string,16); 2160 const char* part1_cstr = part1.c_str(); 2161 const char* part2_cstr = part2.c_str(); 2162 high = ::strtoull(part1_cstr, NULL, 16); 2163 low = ::strtoull(part2_cstr, NULL, 16); 2164 return true; 2165#else 2166 // your own MD5 implementation here 2167 return false; 2168#endif 2169} 2170