1 //===-- Host.mm -------------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Host/Host.h" 11 12 #include <AvailabilityMacros.h> 13 14 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 15 #define NO_XPC_SERVICES 1 16 #endif 17 18 #if !defined(NO_XPC_SERVICES) 19 #define __XPC_PRIVATE_H__ 20 #include <xpc/xpc.h> 21 #include "launcherXPCService/LauncherXPCService.h" 22 #endif 23 24 #include <asl.h> 25 #include <crt_externs.h> 26 #include <execinfo.h> 27 #include <grp.h> 28 #include <libproc.h> 29 #include <pwd.h> 30 #include <spawn.h> 31 #include <stdio.h> 32 #include <sys/proc.h> 33 #include <sys/stat.h> 34 #include <sys/sysctl.h> 35 #include <sys/types.h> 36 #include <unistd.h> 37 38 #include "lldb/Core/ArchSpec.h" 39 #include "lldb/Core/Communication.h" 40 #include "lldb/Core/ConnectionFileDescriptor.h" 41 #include "lldb/Core/DataExtractor.h" 42 #include "lldb/Core/Log.h" 43 #include "lldb/Core/Module.h" 44 #include "lldb/Core/StreamFile.h" 45 #include "lldb/Core/StreamString.h" 46 #include "lldb/Host/Endian.h" 47 #include "lldb/Host/FileSpec.h" 48 #include "lldb/Target/Platform.h" 49 #include "lldb/Target/Process.h" 50 #include "lldb/Utility/CleanUp.h" 51 52 #include "cfcpp/CFCBundle.h" 53 #include "cfcpp/CFCMutableArray.h" 54 #include "cfcpp/CFCMutableDictionary.h" 55 #include "cfcpp/CFCReleaser.h" 56 #include "cfcpp/CFCString.h" 57 58 #include "llvm/Support/Host.h" 59 #include "llvm/Support/MachO.h" 60 61 #include <objc/objc-auto.h> 62 63 #include <CoreFoundation/CoreFoundation.h> 64 #include <Foundation/Foundation.h> 65 66 #if !defined(__arm__) 67 #include <Carbon/Carbon.h> 68 #endif 69 70 #ifndef _POSIX_SPAWN_DISABLE_ASLR 71 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 72 #endif 73 74 extern "C" 75 { 76 int __pthread_chdir(const char *path); 77 int __pthread_fchdir (int fildes); 78 } 79 80 using namespace lldb; 81 using namespace lldb_private; 82 83 static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; 84 static pthread_key_t g_thread_create_key = 0; 85 86 class MacOSXDarwinThread 87 { 88 public: 89 MacOSXDarwinThread(const char *thread_name) : 90 m_pool (nil) 91 { 92 // Register our thread with the collector if garbage collection is enabled. 93 if (objc_collectingEnabled()) 94 { 95 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 96 // On Leopard and earlier there is no way objc_registerThreadWithCollector 97 // function, so we do it manually. 98 auto_zone_register_thread(auto_zone()); 99 #else 100 // On SnowLeopard and later we just call the thread registration function. 101 objc_registerThreadWithCollector(); 102 #endif 103 } 104 else 105 { 106 m_pool = [[NSAutoreleasePool alloc] init]; 107 } 108 109 110 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name); 111 } 112 113 ~MacOSXDarwinThread() 114 { 115 if (m_pool) 116 { 117 [m_pool drain]; 118 m_pool = nil; 119 } 120 } 121 122 static void PThreadDestructor (void *v) 123 { 124 if (v) 125 delete static_cast<MacOSXDarwinThread*>(v); 126 ::pthread_setspecific (g_thread_create_key, NULL); 127 } 128 129 protected: 130 NSAutoreleasePool * m_pool; 131 private: 132 DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread); 133 }; 134 135 static void 136 InitThreadCreated() 137 { 138 ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor); 139 } 140 141 void 142 Host::ThreadCreated (const char *thread_name) 143 { 144 ::pthread_once (&g_thread_create_once, InitThreadCreated); 145 if (g_thread_create_key) 146 { 147 ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name)); 148 } 149 } 150 151 std::string 152 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) 153 { 154 std::string thread_name; 155 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 156 // We currently can only get the name of a thread in the current process. 157 if (pid == Host::GetCurrentProcessID()) 158 { 159 char pthread_name[1024]; 160 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0) 161 { 162 if (pthread_name[0]) 163 { 164 thread_name = pthread_name; 165 } 166 } 167 else 168 { 169 dispatch_queue_t current_queue = ::dispatch_get_current_queue (); 170 if (current_queue != NULL) 171 { 172 const char *queue_name = dispatch_queue_get_label (current_queue); 173 if (queue_name && queue_name[0]) 174 { 175 thread_name = queue_name; 176 } 177 } 178 } 179 } 180 #endif 181 return thread_name; 182 } 183 184 bool 185 Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory) 186 { 187 #if defined (__APPLE__) 188 if (file.GetFileType () == FileSpec::eFileTypeDirectory) 189 { 190 char path[PATH_MAX]; 191 if (file.GetPath(path, sizeof(path))) 192 { 193 CFCBundle bundle (path); 194 if (bundle.GetPath (path, sizeof(path))) 195 { 196 bundle_directory.SetFile (path, false); 197 return true; 198 } 199 } 200 } 201 #endif 202 bundle_directory.Clear(); 203 return false; 204 } 205 206 207 bool 208 Host::ResolveExecutableInBundle (FileSpec &file) 209 { 210 #if defined (__APPLE__) 211 if (file.GetFileType () == FileSpec::eFileTypeDirectory) 212 { 213 char path[PATH_MAX]; 214 if (file.GetPath(path, sizeof(path))) 215 { 216 CFCBundle bundle (path); 217 CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ()); 218 if (url.get()) 219 { 220 if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path))) 221 { 222 file.SetFile(path, false); 223 return true; 224 } 225 } 226 } 227 } 228 #endif 229 return false; 230 } 231 232 lldb::pid_t 233 Host::LaunchApplication (const FileSpec &app_file_spec) 234 { 235 #if defined (__arm__) 236 return LLDB_INVALID_PROCESS_ID; 237 #else 238 char app_path[PATH_MAX]; 239 app_file_spec.GetPath(app_path, sizeof(app_path)); 240 241 LSApplicationParameters app_params; 242 ::memset (&app_params, 0, sizeof (app_params)); 243 app_params.flags = kLSLaunchDefaults | 244 kLSLaunchDontAddToRecents | 245 kLSLaunchNewInstance; 246 247 248 FSRef app_fsref; 249 CFCString app_cfstr (app_path, kCFStringEncodingUTF8); 250 251 OSStatus error = ::FSPathMakeRef ((const UInt8 *)app_path, &app_fsref, NULL); 252 253 // If we found the app, then store away the name so we don't have to re-look it up. 254 if (error != noErr) 255 return LLDB_INVALID_PROCESS_ID; 256 257 app_params.application = &app_fsref; 258 259 ProcessSerialNumber psn; 260 261 error = ::LSOpenApplication (&app_params, &psn); 262 263 if (error != noErr) 264 return LLDB_INVALID_PROCESS_ID; 265 266 ::pid_t pid = LLDB_INVALID_PROCESS_ID; 267 error = ::GetProcessPID(&psn, &pid); 268 if (error != noErr) 269 return LLDB_INVALID_PROCESS_ID; 270 return pid; 271 #endif 272 } 273 274 275 static void * 276 AcceptPIDFromInferior (void *arg) 277 { 278 const char *connect_url = (const char *)arg; 279 ConnectionFileDescriptor file_conn; 280 Error error; 281 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess) 282 { 283 char pid_str[256]; 284 ::memset (pid_str, 0, sizeof(pid_str)); 285 ConnectionStatus status; 286 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL); 287 if (pid_str_len > 0) 288 { 289 int pid = atoi (pid_str); 290 return (void *)(intptr_t)pid; 291 } 292 } 293 return NULL; 294 } 295 296 static bool 297 WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) 298 { 299 const int time_delta_usecs = 100000; 300 const int num_retries = timeout_in_seconds/time_delta_usecs; 301 for (int i=0; i<num_retries; i++) 302 { 303 struct proc_bsdinfo bsd_info; 304 int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 305 (uint64_t) 0, 306 &bsd_info, 307 PROC_PIDTBSDINFO_SIZE); 308 309 switch (error) 310 { 311 case EINVAL: 312 case ENOTSUP: 313 case ESRCH: 314 case EPERM: 315 return false; 316 317 default: 318 break; 319 320 case 0: 321 if (bsd_info.pbi_status == SSTOP) 322 return true; 323 } 324 ::usleep (time_delta_usecs); 325 } 326 return false; 327 } 328 #if !defined(__arm__) 329 330 //static lldb::pid_t 331 //LaunchInNewTerminalWithCommandFile 332 //( 333 // const char **argv, 334 // const char **envp, 335 // const char *working_dir, 336 // const ArchSpec *arch_spec, 337 // bool stop_at_entry, 338 // bool disable_aslr 339 //) 340 //{ 341 // if (!argv || !argv[0]) 342 // return LLDB_INVALID_PROCESS_ID; 343 // 344 // OSStatus error = 0; 345 // 346 // FileSpec program (argv[0], false); 347 // 348 // 349 // std::string unix_socket_name; 350 // 351 // char temp_file_path[PATH_MAX]; 352 // const char *tmpdir = ::getenv ("TMPDIR"); 353 // if (tmpdir == NULL) 354 // tmpdir = "/tmp/"; 355 // ::snprintf (temp_file_path, sizeof(temp_file_path), "%s%s-XXXXXX", tmpdir, program.GetFilename().AsCString()); 356 // 357 // if (::mktemp (temp_file_path) == NULL) 358 // return LLDB_INVALID_PROCESS_ID; 359 // 360 // unix_socket_name.assign (temp_file_path); 361 // 362 // ::strlcat (temp_file_path, ".command", sizeof (temp_file_path)); 363 // 364 // StreamFile command_file; 365 // command_file.GetFile().Open (temp_file_path, 366 // File::eOpenOptionWrite | File::eOpenOptionCanCreate, 367 // File::ePermissionsDefault); 368 // 369 // if (!command_file.GetFile().IsValid()) 370 // return LLDB_INVALID_PROCESS_ID; 371 // 372 // FileSpec darwin_debug_file_spec; 373 // if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec)) 374 // return LLDB_INVALID_PROCESS_ID; 375 // darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); 376 // 377 // if (!darwin_debug_file_spec.Exists()) 378 // return LLDB_INVALID_PROCESS_ID; 379 // 380 // char launcher_path[PATH_MAX]; 381 // darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); 382 // command_file.Printf("\"%s\" ", launcher_path); 383 // 384 // command_file.Printf("--unix-socket=%s ", unix_socket_name.c_str()); 385 // 386 // if (arch_spec && arch_spec->IsValid()) 387 // { 388 // command_file.Printf("--arch=%s ", arch_spec->GetArchitectureName()); 389 // } 390 // 391 // if (disable_aslr) 392 // { 393 // command_file.PutCString("--disable-aslr "); 394 // } 395 // 396 // command_file.PutCString("-- "); 397 // 398 // if (argv) 399 // { 400 // for (size_t i=0; argv[i] != NULL; ++i) 401 // { 402 // command_file.Printf("\"%s\" ", argv[i]); 403 // } 404 // } 405 // command_file.PutCString("\necho Process exited with status $?\n"); 406 // command_file.GetFile().Close(); 407 // if (::chmod (temp_file_path, S_IRWXU | S_IRWXG) != 0) 408 // return LLDB_INVALID_PROCESS_ID; 409 // 410 // CFCMutableDictionary cf_env_dict; 411 // 412 // const bool can_create = true; 413 // if (envp) 414 // { 415 // for (size_t i=0; envp[i] != NULL; ++i) 416 // { 417 // const char *env_entry = envp[i]; 418 // const char *equal_pos = strchr(env_entry, '='); 419 // if (equal_pos) 420 // { 421 // std::string env_key (env_entry, equal_pos); 422 // std::string env_val (equal_pos + 1); 423 // CFCString cf_env_key (env_key.c_str(), kCFStringEncodingUTF8); 424 // CFCString cf_env_val (env_val.c_str(), kCFStringEncodingUTF8); 425 // cf_env_dict.AddValue (cf_env_key.get(), cf_env_val.get(), can_create); 426 // } 427 // } 428 // } 429 // 430 // LSApplicationParameters app_params; 431 // ::memset (&app_params, 0, sizeof (app_params)); 432 // app_params.flags = kLSLaunchDontAddToRecents | kLSLaunchAsync; 433 // app_params.argv = NULL; 434 // app_params.environment = (CFDictionaryRef)cf_env_dict.get(); 435 // 436 // CFCReleaser<CFURLRef> command_file_url (::CFURLCreateFromFileSystemRepresentation (NULL, 437 // (const UInt8 *)temp_file_path, 438 // strlen(temp_file_path), 439 // false)); 440 // 441 // CFCMutableArray urls; 442 // 443 // // Terminal.app will open the ".command" file we have created 444 // // and run our process inside it which will wait at the entry point 445 // // for us to attach. 446 // urls.AppendValue(command_file_url.get()); 447 // 448 // 449 // lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 450 // 451 // Error lldb_error; 452 // // Sleep and wait a bit for debugserver to start to listen... 453 // char connect_url[128]; 454 // ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str()); 455 // 456 // // Spawn a new thread to accept incoming connection on the connect_url 457 // // so we can grab the pid from the inferior 458 // lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(), 459 // AcceptPIDFromInferior, 460 // connect_url, 461 // &lldb_error); 462 // 463 // ProcessSerialNumber psn; 464 // error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1); 465 // if (error == noErr) 466 // { 467 // thread_result_t accept_thread_result = NULL; 468 // if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error)) 469 // { 470 // if (accept_thread_result) 471 // { 472 // pid = (intptr_t)accept_thread_result; 473 // 474 // // Wait for process to be stopped the the entry point by watching 475 // // for the process status to be set to SSTOP which indicates it it 476 // // SIGSTOP'ed at the entry point 477 // WaitForProcessToSIGSTOP (pid, 5); 478 // } 479 // } 480 // } 481 // else 482 // { 483 // Host::ThreadCancel (accept_thread, &lldb_error); 484 // } 485 // 486 // return pid; 487 //} 488 489 const char *applscript_in_new_tty = 490 "tell application \"Terminal\"\n" 491 " do script \"%s\"\n" 492 "end tell\n"; 493 494 495 const char *applscript_in_existing_tty = "\ 496 set the_shell_script to \"%s\"\n\ 497 tell application \"Terminal\"\n\ 498 repeat with the_window in (get windows)\n\ 499 repeat with the_tab in tabs of the_window\n\ 500 set the_tty to tty in the_tab\n\ 501 if the_tty contains \"%s\" then\n\ 502 if the_tab is not busy then\n\ 503 set selected of the_tab to true\n\ 504 set frontmost of the_window to true\n\ 505 do script the_shell_script in the_tab\n\ 506 return\n\ 507 end if\n\ 508 end if\n\ 509 end repeat\n\ 510 end repeat\n\ 511 do script the_shell_script\n\ 512 end tell\n"; 513 514 515 static Error 516 LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &launch_info) 517 { 518 Error error; 519 char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; 520 if (::mktemp (unix_socket_name) == NULL) 521 { 522 error.SetErrorString ("failed to make temporary path for a unix socket"); 523 return error; 524 } 525 526 StreamString command; 527 FileSpec darwin_debug_file_spec; 528 if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec)) 529 { 530 error.SetErrorString ("can't locate the 'darwin-debug' executable"); 531 return error; 532 } 533 534 darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); 535 536 if (!darwin_debug_file_spec.Exists()) 537 { 538 error.SetErrorStringWithFormat ("the 'darwin-debug' executable doesn't exists at '%s'", 539 darwin_debug_file_spec.GetPath().c_str()); 540 return error; 541 } 542 543 char launcher_path[PATH_MAX]; 544 darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); 545 546 const ArchSpec &arch_spec = launch_info.GetArchitecture(); 547 if (arch_spec.IsValid()) 548 command.Printf("arch -arch %s ", arch_spec.GetArchitectureName()); 549 550 command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name); 551 552 if (arch_spec.IsValid()) 553 command.Printf(" --arch=%s", arch_spec.GetArchitectureName()); 554 555 const char *working_dir = launch_info.GetWorkingDirectory(); 556 if (working_dir) 557 command.Printf(" --working-dir '%s'", working_dir); 558 else 559 { 560 char cwd[PATH_MAX]; 561 if (getcwd(cwd, PATH_MAX)) 562 command.Printf(" --working-dir '%s'", cwd); 563 } 564 565 if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) 566 command.PutCString(" --disable-aslr"); 567 568 // We are launching on this host in a terminal. So compare the environemnt on the host 569 // to what is supplied in the launch_info. Any items that aren't in the host environemnt 570 // need to be sent to darwin-debug. If we send all environment entries, we might blow the 571 // max command line length, so we only send user modified entries. 572 const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector (); 573 StringList host_env; 574 const size_t host_env_count = Host::GetEnvironment (host_env); 575 const char *env_entry; 576 for (size_t env_idx = 0; (env_entry = envp[env_idx]) != NULL; ++env_idx) 577 { 578 bool add_entry = true; 579 for (size_t i=0; i<host_env_count; ++i) 580 { 581 const char *host_env_entry = host_env.GetStringAtIndex(i); 582 if (strcmp(env_entry, host_env_entry) == 0) 583 { 584 add_entry = false; 585 break; 586 } 587 } 588 if (add_entry) 589 { 590 command.Printf(" --env='%s'", env_entry); 591 } 592 } 593 594 command.PutCString(" -- "); 595 596 const char **argv = launch_info.GetArguments().GetConstArgumentVector (); 597 if (argv) 598 { 599 for (size_t i=0; argv[i] != NULL; ++i) 600 { 601 if (i==0) 602 command.Printf(" '%s'", exe_path); 603 else 604 command.Printf(" '%s'", argv[i]); 605 } 606 } 607 else 608 { 609 command.Printf(" '%s'", exe_path); 610 } 611 command.PutCString (" ; echo Process exited with status $?"); 612 613 StreamString applescript_source; 614 615 const char *tty_command = command.GetString().c_str(); 616 // if (tty_name && tty_name[0]) 617 // { 618 // applescript_source.Printf (applscript_in_existing_tty, 619 // tty_command, 620 // tty_name); 621 // } 622 // else 623 // { 624 applescript_source.Printf (applscript_in_new_tty, 625 tty_command); 626 // } 627 628 629 630 const char *script_source = applescript_source.GetString().c_str(); 631 //puts (script_source); 632 NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]]; 633 634 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 635 636 Error lldb_error; 637 // Sleep and wait a bit for debugserver to start to listen... 638 ConnectionFileDescriptor file_conn; 639 char connect_url[128]; 640 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); 641 642 // Spawn a new thread to accept incoming connection on the connect_url 643 // so we can grab the pid from the inferior. We have to do this because we 644 // are sending an AppleScript that will launch a process in Terminal.app, 645 // in a shell and the shell will fork/exec a couple of times before we get 646 // to the process that we wanted to launch. So when our process actually 647 // gets launched, we will handshake with it and get the process ID for it. 648 lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name, 649 AcceptPIDFromInferior, 650 connect_url, 651 &lldb_error); 652 653 654 [applescript executeAndReturnError:nil]; 655 656 thread_result_t accept_thread_result = NULL; 657 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error)) 658 { 659 if (accept_thread_result) 660 { 661 pid = (intptr_t)accept_thread_result; 662 663 // Wait for process to be stopped the the entry point by watching 664 // for the process status to be set to SSTOP which indicates it it 665 // SIGSTOP'ed at the entry point 666 WaitForProcessToSIGSTOP (pid, 5); 667 } 668 } 669 ::unlink (unix_socket_name); 670 [applescript release]; 671 if (pid != LLDB_INVALID_PROCESS_ID) 672 launch_info.SetProcessID (pid); 673 return error; 674 } 675 676 #endif // #if !defined(__arm__) 677 678 679 // On MacOSX CrashReporter will display a string for each shared library if 680 // the shared library has an exported symbol named "__crashreporter_info__". 681 682 static Mutex& 683 GetCrashReporterMutex () 684 { 685 static Mutex g_mutex; 686 return g_mutex; 687 } 688 689 extern "C" { 690 const char *__crashreporter_info__ = NULL; 691 } 692 693 asm(".desc ___crashreporter_info__, 0x10"); 694 695 void 696 Host::SetCrashDescriptionWithFormat (const char *format, ...) 697 { 698 static StreamString g_crash_description; 699 Mutex::Locker locker (GetCrashReporterMutex ()); 700 701 if (format) 702 { 703 va_list args; 704 va_start (args, format); 705 g_crash_description.GetString().clear(); 706 g_crash_description.PrintfVarArg(format, args); 707 va_end (args); 708 __crashreporter_info__ = g_crash_description.GetData(); 709 } 710 else 711 { 712 __crashreporter_info__ = NULL; 713 } 714 } 715 716 void 717 Host::SetCrashDescription (const char *cstr) 718 { 719 Mutex::Locker locker (GetCrashReporterMutex ()); 720 static std::string g_crash_description; 721 if (cstr) 722 { 723 g_crash_description.assign (cstr); 724 __crashreporter_info__ = g_crash_description.c_str(); 725 } 726 else 727 { 728 __crashreporter_info__ = NULL; 729 } 730 } 731 732 bool 733 Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) 734 { 735 #if defined(__arm__) 736 return false; 737 #else 738 // We attach this to an 'odoc' event to specify a particular selection 739 typedef struct { 740 int16_t reserved0; // must be zero 741 int16_t fLineNumber; 742 int32_t fSelStart; 743 int32_t fSelEnd; 744 uint32_t reserved1; // must be zero 745 uint32_t reserved2; // must be zero 746 } BabelAESelInfo; 747 748 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); 749 char file_path[PATH_MAX]; 750 file_spec.GetPath(file_path, PATH_MAX); 751 CFCString file_cfstr (file_path, kCFStringEncodingUTF8); 752 CFCReleaser<CFURLRef> file_URL (::CFURLCreateWithFileSystemPath (NULL, 753 file_cfstr.get(), 754 kCFURLPOSIXPathStyle, 755 false)); 756 757 if (log) 758 log->Printf("Sending source file: \"%s\" and line: %d to external editor.\n", file_path, line_no); 759 760 long error; 761 BabelAESelInfo file_and_line_info = 762 { 763 0, // reserved0 764 (int16_t)(line_no - 1), // fLineNumber (zero based line number) 765 1, // fSelStart 766 1024, // fSelEnd 767 0, // reserved1 768 0 // reserved2 769 }; 770 771 AEKeyDesc file_and_line_desc; 772 773 error = ::AECreateDesc (typeUTF8Text, 774 &file_and_line_info, 775 sizeof (file_and_line_info), 776 &(file_and_line_desc.descContent)); 777 778 if (error != noErr) 779 { 780 if (log) 781 log->Printf("Error creating AEDesc: %ld.\n", error); 782 return false; 783 } 784 785 file_and_line_desc.descKey = keyAEPosition; 786 787 static std::string g_app_name; 788 static FSRef g_app_fsref; 789 790 LSApplicationParameters app_params; 791 ::memset (&app_params, 0, sizeof (app_params)); 792 app_params.flags = kLSLaunchDefaults | 793 kLSLaunchDontAddToRecents | 794 kLSLaunchDontSwitch; 795 796 char *external_editor = ::getenv ("LLDB_EXTERNAL_EDITOR"); 797 798 if (external_editor) 799 { 800 if (log) 801 log->Printf("Looking for external editor \"%s\".\n", external_editor); 802 803 if (g_app_name.empty() || strcmp (g_app_name.c_str(), external_editor) != 0) 804 { 805 CFCString editor_name (external_editor, kCFStringEncodingUTF8); 806 error = ::LSFindApplicationForInfo (kLSUnknownCreator, 807 NULL, 808 editor_name.get(), 809 &g_app_fsref, 810 NULL); 811 812 // If we found the app, then store away the name so we don't have to re-look it up. 813 if (error != noErr) 814 { 815 if (log) 816 log->Printf("Could not find External Editor application, error: %ld.\n", error); 817 return false; 818 } 819 820 } 821 app_params.application = &g_app_fsref; 822 } 823 824 ProcessSerialNumber psn; 825 CFCReleaser<CFArrayRef> file_array(CFArrayCreate (NULL, (const void **) file_URL.ptr_address(false), 1, NULL)); 826 error = ::LSOpenURLsWithRole (file_array.get(), 827 kLSRolesAll, 828 &file_and_line_desc, 829 &app_params, 830 &psn, 831 1); 832 833 AEDisposeDesc (&(file_and_line_desc.descContent)); 834 835 if (error != noErr) 836 { 837 if (log) 838 log->Printf("LSOpenURLsWithRole failed, error: %ld.\n", error); 839 840 return false; 841 } 842 843 ProcessInfoRec which_process; 844 ::memset(&which_process, 0, sizeof(which_process)); 845 unsigned char ap_name[PATH_MAX]; 846 which_process.processName = ap_name; 847 error = ::GetProcessInformation (&psn, &which_process); 848 849 bool using_xcode; 850 if (error != noErr) 851 { 852 if (log) 853 log->Printf("GetProcessInformation failed, error: %ld.\n", error); 854 using_xcode = false; 855 } 856 else 857 using_xcode = strncmp((char *) ap_name+1, "Xcode", (int) ap_name[0]) == 0; 858 859 // Xcode doesn't obey the line number in the Open Apple Event. So I have to send 860 // it an AppleScript to focus on the right line. 861 862 if (using_xcode) 863 { 864 static ComponentInstance osa_component = NULL; 865 static const char *as_template = "tell application \"Xcode\"\n" 866 "set doc to the first document whose path is \"%s\"\n" 867 "set the selection to paragraph %d of doc\n" 868 "--- set the selected paragraph range to {%d, %d} of doc\n" 869 "end tell\n"; 870 const int chars_for_int = 32; 871 static int as_template_len = strlen (as_template); 872 873 874 char *as_str; 875 AEDesc as_desc; 876 877 if (osa_component == NULL) 878 { 879 osa_component = ::OpenDefaultComponent (kOSAComponentType, 880 kAppleScriptSubtype); 881 } 882 883 if (osa_component == NULL) 884 { 885 if (log) 886 log->Printf("Could not get default AppleScript component.\n"); 887 return false; 888 } 889 890 uint32_t as_str_size = as_template_len + strlen (file_path) + 3 * chars_for_int + 1; 891 as_str = (char *) malloc (as_str_size); 892 ::snprintf (as_str, 893 as_str_size - 1, 894 as_template, 895 file_path, 896 line_no, 897 line_no, 898 line_no); 899 900 error = ::AECreateDesc (typeChar, 901 as_str, 902 strlen (as_str), 903 &as_desc); 904 905 ::free (as_str); 906 907 if (error != noErr) 908 { 909 if (log) 910 log->Printf("Failed to create AEDesc for Xcode AppleEvent: %ld.\n", error); 911 return false; 912 } 913 914 OSAID ret_OSAID; 915 error = ::OSACompileExecute (osa_component, 916 &as_desc, 917 kOSANullScript, 918 kOSAModeNeverInteract, 919 &ret_OSAID); 920 921 ::OSADispose (osa_component, ret_OSAID); 922 923 ::AEDisposeDesc (&as_desc); 924 925 if (error != noErr) 926 { 927 if (log) 928 log->Printf("Sending AppleEvent to Xcode failed, error: %ld.\n", error); 929 return false; 930 } 931 } 932 return true; 933 #endif // #if !defined(__arm__) 934 } 935 936 937 void 938 Host::Backtrace (Stream &strm, uint32_t max_frames) 939 { 940 if (max_frames > 0) 941 { 942 std::vector<void *> frame_buffer (max_frames, NULL); 943 int num_frames = ::backtrace (&frame_buffer[0], frame_buffer.size()); 944 char** strs = ::backtrace_symbols (&frame_buffer[0], num_frames); 945 if (strs) 946 { 947 // Start at 1 to skip the "Host::Backtrace" frame 948 for (int i = 1; i < num_frames; ++i) 949 strm.Printf("%s\n", strs[i]); 950 ::free (strs); 951 } 952 } 953 } 954 955 size_t 956 Host::GetEnvironment (StringList &env) 957 { 958 char **host_env = *_NSGetEnviron(); 959 char *env_entry; 960 size_t i; 961 for (i=0; (env_entry = host_env[i]) != NULL; ++i) 962 env.AppendString(env_entry); 963 return i; 964 965 } 966 967 968 bool 969 Host::GetOSBuildString (std::string &s) 970 { 971 int mib[2] = { CTL_KERN, KERN_OSVERSION }; 972 char cstr[PATH_MAX]; 973 size_t cstr_len = sizeof(cstr); 974 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) 975 { 976 s.assign (cstr, cstr_len); 977 return true; 978 } 979 980 s.clear(); 981 return false; 982 } 983 984 bool 985 Host::GetOSKernelDescription (std::string &s) 986 { 987 int mib[2] = { CTL_KERN, KERN_VERSION }; 988 char cstr[PATH_MAX]; 989 size_t cstr_len = sizeof(cstr); 990 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) 991 { 992 s.assign (cstr, cstr_len); 993 return true; 994 } 995 s.clear(); 996 return false; 997 } 998 999 #include <libxml/parser.h> 1000 #include <libxml/tree.h> 1001 1002 bool 1003 Host::GetOSVersion 1004 ( 1005 uint32_t &major, 1006 uint32_t &minor, 1007 uint32_t &update 1008 ) 1009 { 1010 static const char *version_plist_file = "/System/Library/CoreServices/SystemVersion.plist"; 1011 char buffer[256]; 1012 const char *product_version_str = NULL; 1013 1014 CFCReleaser<CFURLRef> plist_url(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, 1015 (UInt8 *) version_plist_file, 1016 strlen (version_plist_file), NO)); 1017 if (plist_url.get()) 1018 { 1019 CFCReleaser<CFPropertyListRef> property_list; 1020 CFCReleaser<CFStringRef> error_string; 1021 CFCReleaser<CFDataRef> resource_data; 1022 SInt32 error_code; 1023 1024 // Read the XML file. 1025 if (CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault, 1026 plist_url.get(), 1027 resource_data.ptr_address(), 1028 NULL, 1029 NULL, 1030 &error_code)) 1031 { 1032 // Reconstitute the dictionary using the XML data. 1033 property_list = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, 1034 resource_data.get(), 1035 kCFPropertyListImmutable, 1036 error_string.ptr_address()); 1037 if (CFGetTypeID(property_list.get()) == CFDictionaryGetTypeID()) 1038 { 1039 CFDictionaryRef property_dict = (CFDictionaryRef) property_list.get(); 1040 CFStringRef product_version_key = CFSTR("ProductVersion"); 1041 CFPropertyListRef product_version_value; 1042 product_version_value = CFDictionaryGetValue(property_dict, product_version_key); 1043 if (product_version_value && CFGetTypeID(product_version_value) == CFStringGetTypeID()) 1044 { 1045 CFStringRef product_version_cfstr = (CFStringRef) product_version_value; 1046 product_version_str = CFStringGetCStringPtr(product_version_cfstr, kCFStringEncodingUTF8); 1047 if (product_version_str != NULL) { 1048 if (CFStringGetCString(product_version_cfstr, buffer, 256, kCFStringEncodingUTF8)) 1049 product_version_str = buffer; 1050 } 1051 } 1052 } 1053 } 1054 } 1055 1056 1057 if (product_version_str) 1058 { 1059 Args::StringToVersion(product_version_str, major, minor, update); 1060 return true; 1061 } 1062 else 1063 return false; 1064 1065 } 1066 1067 static bool 1068 GetMacOSXProcessName (const ProcessInstanceInfoMatch *match_info_ptr, 1069 ProcessInstanceInfo &process_info) 1070 { 1071 if (process_info.ProcessIDIsValid()) 1072 { 1073 char process_name[MAXCOMLEN * 2 + 1]; 1074 int name_len = ::proc_name(process_info.GetProcessID(), process_name, MAXCOMLEN * 2); 1075 if (name_len == 0) 1076 return false; 1077 1078 if (match_info_ptr == NULL || NameMatches(process_name, 1079 match_info_ptr->GetNameMatchType(), 1080 match_info_ptr->GetProcessInfo().GetName())) 1081 { 1082 process_info.GetExecutableFile().SetFile (process_name, false); 1083 return true; 1084 } 1085 } 1086 process_info.GetExecutableFile().Clear(); 1087 return false; 1088 } 1089 1090 1091 static bool 1092 GetMacOSXProcessCPUType (ProcessInstanceInfo &process_info) 1093 { 1094 if (process_info.ProcessIDIsValid()) 1095 { 1096 // Make a new mib to stay thread safe 1097 int mib[CTL_MAXNAME]={0,}; 1098 size_t mib_len = CTL_MAXNAME; 1099 if (::sysctlnametomib("sysctl.proc_cputype", mib, &mib_len)) 1100 return false; 1101 1102 mib[mib_len] = process_info.GetProcessID(); 1103 mib_len++; 1104 1105 cpu_type_t cpu, sub = 0; 1106 size_t len = sizeof(cpu); 1107 if (::sysctl (mib, mib_len, &cpu, &len, 0, 0) == 0) 1108 { 1109 switch (cpu) 1110 { 1111 case llvm::MachO::CPUTypeI386: sub = llvm::MachO::CPUSubType_I386_ALL; break; 1112 case llvm::MachO::CPUTypeX86_64: sub = llvm::MachO::CPUSubType_X86_64_ALL; break; 1113 case llvm::MachO::CPUTypeARM: 1114 { 1115 uint32_t cpusubtype = 0; 1116 len = sizeof(cpusubtype); 1117 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 1118 sub = cpusubtype; 1119 } 1120 break; 1121 1122 default: 1123 break; 1124 } 1125 process_info.GetArchitecture ().SetArchitecture (eArchTypeMachO, cpu, sub); 1126 return true; 1127 } 1128 } 1129 process_info.GetArchitecture().Clear(); 1130 return false; 1131 } 1132 1133 static bool 1134 GetMacOSXProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, 1135 ProcessInstanceInfo &process_info) 1136 { 1137 if (process_info.ProcessIDIsValid()) 1138 { 1139 int proc_args_mib[3] = { CTL_KERN, KERN_PROCARGS2, (int)process_info.GetProcessID() }; 1140 1141 char arg_data[8192]; 1142 size_t arg_data_size = sizeof(arg_data); 1143 if (::sysctl (proc_args_mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) 1144 { 1145 DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); 1146 lldb::offset_t offset = 0; 1147 uint32_t argc = data.GetU32 (&offset); 1148 const char *cstr; 1149 1150 cstr = data.GetCStr (&offset); 1151 if (cstr) 1152 { 1153 process_info.GetExecutableFile().SetFile(cstr, false); 1154 1155 if (match_info_ptr == NULL || 1156 NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), 1157 match_info_ptr->GetNameMatchType(), 1158 match_info_ptr->GetProcessInfo().GetName())) 1159 { 1160 // Skip NULLs 1161 while (1) 1162 { 1163 const uint8_t *p = data.PeekData(offset, 1); 1164 if ((p == NULL) || (*p != '\0')) 1165 break; 1166 ++offset; 1167 } 1168 // Now extract all arguments 1169 Args &proc_args = process_info.GetArguments(); 1170 for (int i=0; i<argc; ++i) 1171 { 1172 cstr = data.GetCStr(&offset); 1173 if (cstr) 1174 proc_args.AppendArgument(cstr); 1175 } 1176 return true; 1177 } 1178 } 1179 } 1180 } 1181 return false; 1182 } 1183 1184 static bool 1185 GetMacOSXProcessUserAndGroup (ProcessInstanceInfo &process_info) 1186 { 1187 if (process_info.ProcessIDIsValid()) 1188 { 1189 int mib[4]; 1190 mib[0] = CTL_KERN; 1191 mib[1] = KERN_PROC; 1192 mib[2] = KERN_PROC_PID; 1193 mib[3] = process_info.GetProcessID(); 1194 struct kinfo_proc proc_kinfo; 1195 size_t proc_kinfo_size = sizeof(struct kinfo_proc); 1196 1197 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) 1198 { 1199 if (proc_kinfo_size > 0) 1200 { 1201 process_info.SetParentProcessID (proc_kinfo.kp_eproc.e_ppid); 1202 process_info.SetUserID (proc_kinfo.kp_eproc.e_pcred.p_ruid); 1203 process_info.SetGroupID (proc_kinfo.kp_eproc.e_pcred.p_rgid); 1204 process_info.SetEffectiveUserID (proc_kinfo.kp_eproc.e_ucred.cr_uid); 1205 if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) 1206 process_info.SetEffectiveGroupID (proc_kinfo.kp_eproc.e_ucred.cr_groups[0]); 1207 else 1208 process_info.SetEffectiveGroupID (UINT32_MAX); 1209 return true; 1210 } 1211 } 1212 } 1213 process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); 1214 process_info.SetUserID (UINT32_MAX); 1215 process_info.SetGroupID (UINT32_MAX); 1216 process_info.SetEffectiveUserID (UINT32_MAX); 1217 process_info.SetEffectiveGroupID (UINT32_MAX); 1218 return false; 1219 } 1220 1221 1222 uint32_t 1223 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 1224 { 1225 std::vector<struct kinfo_proc> kinfos; 1226 1227 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; 1228 1229 size_t pid_data_size = 0; 1230 if (::sysctl (mib, 4, NULL, &pid_data_size, NULL, 0) != 0) 1231 return 0; 1232 1233 // Add a few extra in case a few more show up 1234 const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; 1235 1236 kinfos.resize (estimated_pid_count); 1237 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); 1238 1239 if (::sysctl (mib, 4, &kinfos[0], &pid_data_size, NULL, 0) != 0) 1240 return 0; 1241 1242 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); 1243 1244 bool all_users = match_info.GetMatchAllUsers(); 1245 const lldb::pid_t our_pid = getpid(); 1246 const uid_t our_uid = getuid(); 1247 for (int i = 0; i < actual_pid_count; i++) 1248 { 1249 const struct kinfo_proc &kinfo = kinfos[i]; 1250 1251 bool kinfo_user_matches = false; 1252 if (all_users) 1253 kinfo_user_matches = true; 1254 else 1255 kinfo_user_matches = kinfo.kp_eproc.e_pcred.p_ruid == our_uid; 1256 1257 // Special case, if lldb is being run as root we can attach to anything. 1258 if (our_uid == 0) 1259 kinfo_user_matches = true; 1260 1261 if (kinfo_user_matches == false || // Make sure the user is acceptable 1262 kinfo.kp_proc.p_pid == our_pid || // Skip this process 1263 kinfo.kp_proc.p_pid == 0 || // Skip kernel (kernel pid is zero) 1264 kinfo.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains... 1265 kinfo.kp_proc.p_flag & P_TRACED || // Being debugged? 1266 kinfo.kp_proc.p_flag & P_WEXIT || // Working on exiting? 1267 kinfo.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta) 1268 continue; 1269 1270 ProcessInstanceInfo process_info; 1271 process_info.SetProcessID (kinfo.kp_proc.p_pid); 1272 process_info.SetParentProcessID (kinfo.kp_eproc.e_ppid); 1273 process_info.SetUserID (kinfo.kp_eproc.e_pcred.p_ruid); 1274 process_info.SetGroupID (kinfo.kp_eproc.e_pcred.p_rgid); 1275 process_info.SetEffectiveUserID (kinfo.kp_eproc.e_ucred.cr_uid); 1276 if (kinfo.kp_eproc.e_ucred.cr_ngroups > 0) 1277 process_info.SetEffectiveGroupID (kinfo.kp_eproc.e_ucred.cr_groups[0]); 1278 else 1279 process_info.SetEffectiveGroupID (UINT32_MAX); 1280 1281 // Make sure our info matches before we go fetch the name and cpu type 1282 if (match_info.Matches (process_info)) 1283 { 1284 if (GetMacOSXProcessArgs (&match_info, process_info)) 1285 { 1286 GetMacOSXProcessCPUType (process_info); 1287 if (match_info.Matches (process_info)) 1288 process_infos.Append (process_info); 1289 } 1290 } 1291 } 1292 return process_infos.GetSize(); 1293 } 1294 1295 bool 1296 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 1297 { 1298 process_info.SetProcessID(pid); 1299 bool success = false; 1300 1301 if (GetMacOSXProcessArgs (NULL, process_info)) 1302 success = true; 1303 1304 if (GetMacOSXProcessCPUType (process_info)) 1305 success = true; 1306 1307 if (GetMacOSXProcessUserAndGroup (process_info)) 1308 success = true; 1309 1310 if (success) 1311 return true; 1312 1313 process_info.Clear(); 1314 return false; 1315 } 1316 1317 static short 1318 GetPosixspawnFlags (ProcessLaunchInfo &launch_info) 1319 { 1320 short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; 1321 if (launch_info.GetFlags().Test (eLaunchFlagExec)) 1322 flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag 1323 1324 if (launch_info.GetFlags().Test (eLaunchFlagDebug)) 1325 flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag 1326 1327 if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) 1328 flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag 1329 1330 if (launch_info.GetLaunchInSeparateProcessGroup()) 1331 flags |= POSIX_SPAWN_SETPGROUP; 1332 1333 //#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT 1334 // // Close all files exception those with file actions if this is supported. 1335 // flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; 1336 //#endif 1337 1338 return flags; 1339 } 1340 1341 #if !NO_XPC_SERVICES 1342 static void 1343 PackageXPCArguments (xpc_object_t message, const char *prefix, const Args& args) 1344 { 1345 size_t count = args.GetArgumentCount(); 1346 char buf[50]; // long enough for 'argXXX' 1347 memset(buf, 0, 50); 1348 sprintf(buf, "%sCount", prefix); 1349 xpc_dictionary_set_int64(message, buf, count); 1350 for (int i=0; i<count; i++) { 1351 memset(buf, 0, 50); 1352 sprintf(buf, "%s%i", prefix, i); 1353 xpc_dictionary_set_string(message, buf, args.GetArgumentAtIndex(i)); 1354 } 1355 } 1356 1357 /* 1358 A valid authorizationRef means that 1359 - there is the LaunchUsingXPCRightName rights in the /etc/authorization 1360 - we have successfully copied the rights to be send over the XPC wire 1361 Once obtained, it will be valid for as long as the process lives. 1362 */ 1363 static AuthorizationRef authorizationRef = NULL; 1364 static Error 1365 getXPCAuthorization (ProcessLaunchInfo &launch_info) 1366 { 1367 Error error; 1368 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); 1369 1370 if ((launch_info.GetUserID() == 0) && !authorizationRef) 1371 { 1372 OSStatus createStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); 1373 if (createStatus != errAuthorizationSuccess) 1374 { 1375 error.SetError(1, eErrorTypeGeneric); 1376 error.SetErrorString("Can't create authorizationRef."); 1377 if (log) 1378 { 1379 error.PutToLog(log, "%s", error.AsCString()); 1380 } 1381 return error; 1382 } 1383 1384 OSStatus rightsStatus = AuthorizationRightGet(LaunchUsingXPCRightName, NULL); 1385 if (rightsStatus != errAuthorizationSuccess) 1386 { 1387 // No rights in the security database, Create it with the right prompt. 1388 CFStringRef prompt = CFSTR("Xcode is trying to take control of a root process."); 1389 CFStringRef keys[] = { CFSTR("en") }; 1390 CFTypeRef values[] = { prompt }; 1391 CFDictionaryRef promptDict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1392 1393 CFStringRef keys1[] = { CFSTR("class"), CFSTR("group"), CFSTR("comment"), CFSTR("default-prompt"), CFSTR("shared") }; 1394 CFTypeRef values1[] = { CFSTR("user"), CFSTR("admin"), CFSTR(LaunchUsingXPCRightName), promptDict, kCFBooleanFalse }; 1395 CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys1, (const void **)values1, 5, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 1396 rightsStatus = AuthorizationRightSet(authorizationRef, LaunchUsingXPCRightName, dict, NULL, NULL, NULL); 1397 CFRelease(promptDict); 1398 CFRelease(dict); 1399 } 1400 1401 OSStatus copyRightStatus = errAuthorizationDenied; 1402 if (rightsStatus == errAuthorizationSuccess) 1403 { 1404 AuthorizationItem item1 = { LaunchUsingXPCRightName, 0, NULL, 0 }; 1405 AuthorizationItem items[] = {item1}; 1406 AuthorizationRights requestedRights = {1, items }; 1407 AuthorizationFlags authorizationFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; 1408 copyRightStatus = AuthorizationCopyRights(authorizationRef, &requestedRights, kAuthorizationEmptyEnvironment, authorizationFlags, NULL); 1409 } 1410 1411 if (copyRightStatus != errAuthorizationSuccess) 1412 { 1413 // Eventually when the commandline supports running as root and the user is not 1414 // logged in in the current audit session, we will need the trick in gdb where 1415 // we ask the user to type in the root passwd in the terminal. 1416 error.SetError(2, eErrorTypeGeneric); 1417 error.SetErrorStringWithFormat("Launching as root needs root authorization."); 1418 if (log) 1419 { 1420 error.PutToLog(log, "%s", error.AsCString()); 1421 } 1422 1423 if (authorizationRef) 1424 { 1425 AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); 1426 authorizationRef = NULL; 1427 } 1428 } 1429 } 1430 1431 return error; 1432 } 1433 #endif 1434 1435 static Error 1436 LaunchProcessXPC (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid) 1437 { 1438 #if !NO_XPC_SERVICES 1439 Error error = getXPCAuthorization(launch_info); 1440 if (error.Fail()) 1441 return error; 1442 1443 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); 1444 1445 uid_t requested_uid = launch_info.GetUserID(); 1446 const char *xpc_service = nil; 1447 bool send_auth = false; 1448 AuthorizationExternalForm extForm; 1449 if ((requested_uid == UINT32_MAX) || (requested_uid == Host::GetEffectiveUserID())) 1450 { 1451 xpc_service = "com.apple.lldb.launcherXPCService"; 1452 } 1453 else if (requested_uid == 0) 1454 { 1455 if (AuthorizationMakeExternalForm(authorizationRef, &extForm) == errAuthorizationSuccess) 1456 { 1457 send_auth = true; 1458 } 1459 else 1460 { 1461 error.SetError(3, eErrorTypeGeneric); 1462 error.SetErrorStringWithFormat("Launching root via XPC needs to externalize authorization reference."); 1463 if (log) 1464 { 1465 error.PutToLog(log, "%s", error.AsCString()); 1466 } 1467 return error; 1468 } 1469 xpc_service = "com.apple.lldb.launcherRootXPCService"; 1470 } 1471 else 1472 { 1473 error.SetError(4, eErrorTypeGeneric); 1474 error.SetErrorStringWithFormat("Launching via XPC is only currently available for either the login user or root."); 1475 if (log) 1476 { 1477 error.PutToLog(log, "%s", error.AsCString()); 1478 } 1479 return error; 1480 } 1481 1482 xpc_connection_t conn = xpc_connection_create(xpc_service, NULL); 1483 1484 xpc_connection_set_event_handler(conn, ^(xpc_object_t event) { 1485 xpc_type_t type = xpc_get_type(event); 1486 1487 if (type == XPC_TYPE_ERROR) { 1488 if (event == XPC_ERROR_CONNECTION_INTERRUPTED) { 1489 // The service has either canceled itself, crashed, or been terminated. 1490 // The XPC connection is still valid and sending a message to it will re-launch the service. 1491 // If the service is state-full, this is the time to initialize the new service. 1492 return; 1493 } else if (event == XPC_ERROR_CONNECTION_INVALID) { 1494 // The service is invalid. Either the service name supplied to xpc_connection_create() is incorrect 1495 // or we (this process) have canceled the service; we can do any cleanup of appliation state at this point. 1496 // printf("Service disconnected"); 1497 return; 1498 } else { 1499 // printf("Unexpected error from service: %s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); 1500 } 1501 1502 } else { 1503 // printf("Received unexpected event in handler"); 1504 } 1505 }); 1506 1507 xpc_connection_set_finalizer_f (conn, xpc_finalizer_t(xpc_release)); 1508 xpc_connection_resume (conn); 1509 xpc_object_t message = xpc_dictionary_create (nil, nil, 0); 1510 1511 if (send_auth) 1512 { 1513 xpc_dictionary_set_data(message, LauncherXPCServiceAuthKey, extForm.bytes, sizeof(AuthorizationExternalForm)); 1514 } 1515 1516 PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey, launch_info.GetArguments()); 1517 PackageXPCArguments(message, LauncherXPCServiceEnvPrefxKey, launch_info.GetEnvironmentEntries()); 1518 1519 // Posix spawn stuff. 1520 xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, launch_info.GetArchitecture().GetMachOCPUType()); 1521 xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, GetPosixspawnFlags(launch_info)); 1522 1523 xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, message); 1524 xpc_type_t returnType = xpc_get_type(reply); 1525 if (returnType == XPC_TYPE_DICTIONARY) 1526 { 1527 pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey); 1528 if (pid == 0) 1529 { 1530 int errorType = xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey); 1531 int errorCode = xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey); 1532 1533 error.SetError(errorCode, eErrorTypeGeneric); 1534 error.SetErrorStringWithFormat("Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode); 1535 if (log) 1536 { 1537 error.PutToLog(log, "%s", error.AsCString()); 1538 } 1539 1540 if (authorizationRef) 1541 { 1542 AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); 1543 authorizationRef = NULL; 1544 } 1545 } 1546 } 1547 else if (returnType == XPC_TYPE_ERROR) 1548 { 1549 error.SetError(5, eErrorTypeGeneric); 1550 error.SetErrorStringWithFormat("Problems with launching via XPC. XPC error : %s", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION)); 1551 if (log) 1552 { 1553 error.PutToLog(log, "%s", error.AsCString()); 1554 } 1555 } 1556 1557 return error; 1558 #else 1559 Error error; 1560 return error; 1561 #endif 1562 } 1563 1564 static Error 1565 LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid) 1566 { 1567 Error error; 1568 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); 1569 1570 posix_spawnattr_t attr; 1571 error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX); 1572 1573 if (error.Fail() || log) 1574 error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); 1575 if (error.Fail()) 1576 return error; 1577 1578 // Make a quick class that will cleanup the posix spawn attributes in case 1579 // we return in the middle of this function. 1580 lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy); 1581 1582 sigset_t no_signals; 1583 sigset_t all_signals; 1584 sigemptyset (&no_signals); 1585 sigfillset (&all_signals); 1586 ::posix_spawnattr_setsigmask(&attr, &no_signals); 1587 ::posix_spawnattr_setsigdefault(&attr, &all_signals); 1588 1589 short flags = GetPosixspawnFlags(launch_info); 1590 error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); 1591 if (error.Fail() || log) 1592 error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); 1593 if (error.Fail()) 1594 return error; 1595 1596 #if !defined(__arm__) 1597 1598 // We don't need to do this for ARM, and we really shouldn't now that we 1599 // have multiple CPU subtypes and no posix_spawnattr call that allows us 1600 // to set which CPU subtype to launch... 1601 const ArchSpec &arch_spec = launch_info.GetArchitecture(); 1602 cpu_type_t cpu = arch_spec.GetMachOCPUType(); 1603 if (cpu != 0 && 1604 cpu != UINT32_MAX && 1605 cpu != LLDB_INVALID_CPUTYPE) 1606 { 1607 size_t ocount = 0; 1608 error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX); 1609 if (error.Fail() || log) 1610 error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount); 1611 1612 if (error.Fail() || ocount != 1) 1613 return error; 1614 } 1615 1616 #endif 1617 1618 const char *tmp_argv[2]; 1619 char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector(); 1620 char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector(); 1621 if (argv == NULL) 1622 { 1623 // posix_spawn gets very unhappy if it doesn't have at least the program 1624 // name in argv[0]. One of the side affects I have noticed is the environment 1625 // variables don't make it into the child process if "argv == NULL"!!! 1626 tmp_argv[0] = exe_path; 1627 tmp_argv[1] = NULL; 1628 argv = (char * const*)tmp_argv; 1629 } 1630 1631 const char *working_dir = launch_info.GetWorkingDirectory(); 1632 if (working_dir) 1633 { 1634 // No more thread specific current working directory 1635 if (__pthread_chdir (working_dir) < 0) { 1636 if (errno == ENOENT) { 1637 error.SetErrorStringWithFormat("No such file or directory: %s", working_dir); 1638 } else if (errno == ENOTDIR) { 1639 error.SetErrorStringWithFormat("Path doesn't name a directory: %s", working_dir); 1640 } else { 1641 error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution."); 1642 } 1643 return error; 1644 } 1645 } 1646 1647 const size_t num_file_actions = launch_info.GetNumFileActions (); 1648 if (num_file_actions > 0) 1649 { 1650 posix_spawn_file_actions_t file_actions; 1651 error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX); 1652 if (error.Fail() || log) 1653 error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); 1654 if (error.Fail()) 1655 return error; 1656 1657 // Make a quick class that will cleanup the posix spawn attributes in case 1658 // we return in the middle of this function. 1659 lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy); 1660 1661 for (size_t i=0; i<num_file_actions; ++i) 1662 { 1663 const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i); 1664 if (launch_file_action) 1665 { 1666 if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions, 1667 launch_file_action, 1668 log, 1669 error)) 1670 return error; 1671 } 1672 } 1673 1674 error.SetError (::posix_spawnp (&pid, 1675 exe_path, 1676 &file_actions, 1677 &attr, 1678 argv, 1679 envp), 1680 eErrorTypePOSIX); 1681 1682 if (error.Fail() || log) 1683 { 1684 error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", 1685 pid, 1686 exe_path, 1687 &file_actions, 1688 &attr, 1689 argv, 1690 envp); 1691 if (log) 1692 { 1693 for (int ii=0; argv[ii]; ++ii) 1694 log->Printf("argv[%i] = '%s'", ii, argv[ii]); 1695 } 1696 } 1697 1698 } 1699 else 1700 { 1701 error.SetError (::posix_spawnp (&pid, 1702 exe_path, 1703 NULL, 1704 &attr, 1705 argv, 1706 envp), 1707 eErrorTypePOSIX); 1708 1709 if (error.Fail() || log) 1710 { 1711 error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )", 1712 pid, 1713 exe_path, 1714 &attr, 1715 argv, 1716 envp); 1717 if (log) 1718 { 1719 for (int ii=0; argv[ii]; ++ii) 1720 log->Printf("argv[%i] = '%s'", ii, argv[ii]); 1721 } 1722 } 1723 } 1724 1725 if (working_dir) 1726 { 1727 // No more thread specific current working directory 1728 __pthread_fchdir (-1); 1729 } 1730 1731 return error; 1732 } 1733 1734 static bool 1735 ShouldLaunchUsingXPC(const char *exe_path, ProcessLaunchInfo &launch_info) 1736 { 1737 bool result = false; 1738 1739 #if !NO_XPC_SERVICES 1740 const char *debugserver = "/debugserver"; 1741 int len = strlen(debugserver); 1742 int exe_len = strlen(exe_path); 1743 if (exe_len >= len) 1744 { 1745 const char *part = exe_path + (exe_len - len); 1746 if (strcmp(part, debugserver) == 0) 1747 { 1748 // We are dealing with debugserver. 1749 uid_t requested_uid = launch_info.GetUserID(); 1750 if (requested_uid == 0) 1751 { 1752 // Launching XPC works for root. It also works for the non-attaching case for current login 1753 // but unfortunately, we can't detect it here. 1754 result = true; 1755 } 1756 } 1757 } 1758 #endif 1759 1760 return result; 1761 } 1762 1763 Error 1764 Host::LaunchProcess (ProcessLaunchInfo &launch_info) 1765 { 1766 Error error; 1767 char exe_path[PATH_MAX]; 1768 PlatformSP host_platform_sp (Platform::GetDefaultPlatform ()); 1769 1770 const ArchSpec &arch_spec = launch_info.GetArchitecture(); 1771 1772 FileSpec exe_spec(launch_info.GetExecutableFile()); 1773 1774 FileSpec::FileType file_type = exe_spec.GetFileType(); 1775 if (file_type != FileSpec::eFileTypeRegular) 1776 { 1777 lldb::ModuleSP exe_module_sp; 1778 error = host_platform_sp->ResolveExecutable (exe_spec, 1779 arch_spec, 1780 exe_module_sp, 1781 NULL); 1782 1783 if (error.Fail()) 1784 return error; 1785 1786 if (exe_module_sp) 1787 exe_spec = exe_module_sp->GetFileSpec(); 1788 } 1789 1790 if (exe_spec.Exists()) 1791 { 1792 exe_spec.GetPath (exe_path, sizeof(exe_path)); 1793 } 1794 else 1795 { 1796 launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path)); 1797 error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path); 1798 return error; 1799 } 1800 1801 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)) 1802 { 1803 #if !defined(__arm__) 1804 return LaunchInNewTerminalWithAppleScript (exe_path, launch_info); 1805 #else 1806 error.SetErrorString ("launching a processs in a new terminal is not supported on iOS devices"); 1807 return error; 1808 #endif 1809 } 1810 1811 ::pid_t pid = LLDB_INVALID_PROCESS_ID; 1812 1813 if (ShouldLaunchUsingXPC(exe_path, launch_info)) 1814 { 1815 error = LaunchProcessXPC(exe_path, launch_info, pid); 1816 } 1817 else 1818 { 1819 error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); 1820 } 1821 1822 if (pid != LLDB_INVALID_PROCESS_ID) 1823 { 1824 // If all went well, then set the process ID into the launch info 1825 launch_info.SetProcessID(pid); 1826 1827 // Make sure we reap any processes we spawn or we will have zombies. 1828 if (!launch_info.MonitorProcess()) 1829 { 1830 const bool monitor_signals = false; 1831 StartMonitoringChildProcess (Process::SetProcessExitStatus, 1832 NULL, 1833 pid, 1834 monitor_signals); 1835 } 1836 } 1837 else 1838 { 1839 // Invalid process ID, something didn't go well 1840 if (error.Success()) 1841 error.SetErrorString ("process launch failed for unknown reasons"); 1842 } 1843 return error; 1844 } 1845 1846 lldb::thread_t 1847 Host::StartMonitoringChildProcess (Host::MonitorChildProcessCallback callback, 1848 void *callback_baton, 1849 lldb::pid_t pid, 1850 bool monitor_signals) 1851 { 1852 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; 1853 unsigned long mask = DISPATCH_PROC_EXIT; 1854 if (monitor_signals) 1855 mask |= DISPATCH_PROC_SIGNAL; 1856 1857 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); 1858 1859 1860 dispatch_source_t source = ::dispatch_source_create (DISPATCH_SOURCE_TYPE_PROC, 1861 pid, 1862 mask, 1863 ::dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT,0)); 1864 1865 if (log) 1866 log->Printf ("Host::StartMonitoringChildProcess (callback=%p, baton=%p, pid=%i, monitor_signals=%i) source = %p\n", 1867 callback, 1868 callback_baton, 1869 (int)pid, 1870 monitor_signals, 1871 source); 1872 1873 if (source) 1874 { 1875 ::dispatch_source_set_cancel_handler (source, ^{ 1876 ::dispatch_release (source); 1877 }); 1878 ::dispatch_source_set_event_handler (source, ^{ 1879 1880 int status= 0; 1881 int wait_pid = 0; 1882 bool cancel = false; 1883 bool exited = false; 1884 do 1885 { 1886 wait_pid = ::waitpid (pid, &status, 0); 1887 } while (wait_pid < 0 && errno == EINTR); 1888 1889 if (wait_pid >= 0) 1890 { 1891 int signal = 0; 1892 int exit_status = 0; 1893 const char *status_cstr = NULL; 1894 if (WIFSTOPPED(status)) 1895 { 1896 signal = WSTOPSIG(status); 1897 status_cstr = "STOPPED"; 1898 } 1899 else if (WIFEXITED(status)) 1900 { 1901 exit_status = WEXITSTATUS(status); 1902 status_cstr = "EXITED"; 1903 exited = true; 1904 } 1905 else if (WIFSIGNALED(status)) 1906 { 1907 signal = WTERMSIG(status); 1908 status_cstr = "SIGNALED"; 1909 exited = true; 1910 exit_status = -1; 1911 } 1912 else 1913 { 1914 status_cstr = "???"; 1915 } 1916 1917 if (log) 1918 log->Printf ("::waitpid (pid = %llu, &status, 0) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_status = %i", 1919 pid, 1920 wait_pid, 1921 status, 1922 status_cstr, 1923 signal, 1924 exit_status); 1925 1926 if (callback) 1927 cancel = callback (callback_baton, pid, exited, signal, exit_status); 1928 1929 if (exited || cancel) 1930 { 1931 ::dispatch_source_cancel(source); 1932 } 1933 } 1934 }); 1935 1936 ::dispatch_resume (source); 1937 } 1938 return thread; 1939 } 1940 1941 //---------------------------------------------------------------------- 1942 // Log to both stderr and to ASL Logging when running on MacOSX. 1943 //---------------------------------------------------------------------- 1944 void 1945 Host::SystemLog (SystemLogType type, const char *format, va_list args) 1946 { 1947 if (format && format[0]) 1948 { 1949 static aslmsg g_aslmsg = NULL; 1950 if (g_aslmsg == NULL) 1951 { 1952 g_aslmsg = ::asl_new (ASL_TYPE_MSG); 1953 char asl_key_sender[PATH_MAX]; 1954 snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.LLDB.framework"); 1955 ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender); 1956 } 1957 1958 // Copy the va_list so we can log this message twice 1959 va_list copy_args; 1960 va_copy (copy_args, args); 1961 // Log to stderr 1962 ::vfprintf (stderr, format, copy_args); 1963 va_end (copy_args); 1964 1965 int asl_level; 1966 switch (type) 1967 { 1968 case eSystemLogError: 1969 asl_level = ASL_LEVEL_ERR; 1970 break; 1971 1972 case eSystemLogWarning: 1973 asl_level = ASL_LEVEL_WARNING; 1974 break; 1975 } 1976 1977 // Log to ASL 1978 ::asl_vlog (NULL, g_aslmsg, asl_level, format, args); 1979 } 1980 } 1981 1982 lldb::DataBufferSP 1983 Host::GetAuxvData(lldb_private::Process *process) 1984 { 1985 return lldb::DataBufferSP(); 1986 } 1987