1 //===-- DarwinProcessLauncher.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 // 11 // DarwinProcessLauncher.cpp 12 // lldb 13 // 14 // Created by Todd Fiala on 8/30/16. 15 // 16 // 17 18 #include "DarwinProcessLauncher.h" 19 20 // C includes 21 #include <spawn.h> 22 #include <sys/ptrace.h> 23 #include <sys/stat.h> 24 #include <sys/sysctl.h> 25 26 #ifndef _POSIX_SPAWN_DISABLE_ASLR 27 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 28 #endif 29 30 // LLDB includes 31 #include "lldb/lldb-enumerations.h" 32 33 #include "lldb/Core/Error.h" 34 #include "lldb/Core/Log.h" 35 #include "lldb/Core/StreamString.h" 36 #include "lldb/Target/ProcessLaunchInfo.h" 37 #include "lldb/Utility/PseudoTerminal.h" 38 39 #include "CFBundle.h" 40 #include "CFString.h" 41 42 using namespace lldb; 43 using namespace lldb_private; 44 using namespace lldb_private::process_darwin; 45 using namespace lldb_private::darwin_process_launcher; 46 47 namespace { 48 static LaunchFlavor g_launch_flavor = LaunchFlavor::Default; 49 } 50 51 namespace lldb_private { 52 namespace darwin_process_launcher { 53 54 static uint32_t GetCPUTypeForLocalProcess(::pid_t pid) { 55 int mib[CTL_MAXNAME] = { 56 0, 57 }; 58 size_t len = CTL_MAXNAME; 59 if (::sysctlnametomib("sysctl.proc_cputype", mib, &len)) 60 return 0; 61 62 mib[len] = pid; 63 len++; 64 65 cpu_type_t cpu; 66 size_t cpu_len = sizeof(cpu); 67 if (::sysctl(mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0)) 68 cpu = 0; 69 return cpu; 70 } 71 72 static bool ResolveExecutablePath(const char *path, char *resolved_path, 73 size_t resolved_path_size) { 74 if (path == NULL || path[0] == '\0') 75 return false; 76 77 char max_path[PATH_MAX]; 78 std::string result; 79 CFString::GlobPath(path, result); 80 81 if (result.empty()) 82 result = path; 83 84 struct stat path_stat; 85 if (::stat(path, &path_stat) == 0) { 86 if ((path_stat.st_mode & S_IFMT) == S_IFDIR) { 87 CFBundle bundle(path); 88 CFReleaser<CFURLRef> url(bundle.CopyExecutableURL()); 89 if (url.get()) { 90 if (::CFURLGetFileSystemRepresentation( 91 url.get(), true, (UInt8 *)resolved_path, resolved_path_size)) 92 return true; 93 } 94 } 95 } 96 97 if (realpath(path, max_path)) { 98 // Found the path relatively... 99 ::strncpy(resolved_path, max_path, resolved_path_size); 100 return strlen(resolved_path) + 1 < resolved_path_size; 101 } else { 102 // Not a relative path, check the PATH environment variable if the 103 const char *PATH = getenv("PATH"); 104 if (PATH) { 105 const char *curr_path_start = PATH; 106 const char *curr_path_end; 107 while (curr_path_start && *curr_path_start) { 108 curr_path_end = strchr(curr_path_start, ':'); 109 if (curr_path_end == NULL) { 110 result.assign(curr_path_start); 111 curr_path_start = NULL; 112 } else if (curr_path_end > curr_path_start) { 113 size_t len = curr_path_end - curr_path_start; 114 result.assign(curr_path_start, len); 115 curr_path_start += len + 1; 116 } else 117 break; 118 119 result += '/'; 120 result += path; 121 struct stat s; 122 if (stat(result.c_str(), &s) == 0) { 123 ::strncpy(resolved_path, result.c_str(), resolved_path_size); 124 return result.size() + 1 < resolved_path_size; 125 } 126 } 127 } 128 } 129 return false; 130 } 131 132 // TODO check if we have a general purpose fork and exec. We may be 133 // able to get rid of this entirely. 134 static Error ForkChildForPTraceDebugging(const char *path, char const *argv[], 135 char const *envp[], ::pid_t *pid, 136 int *pty_fd) { 137 Error error; 138 if (!path || !argv || !envp || !pid || !pty_fd) { 139 error.SetErrorString("invalid arguments"); 140 return error; 141 } 142 143 // Use a fork that ties the child process's stdin/out/err to a pseudo 144 // terminal so we can read it in our MachProcess::STDIOThread 145 // as unbuffered io. 146 lldb_utility::PseudoTerminal pty; 147 char fork_error[256]; 148 memset(fork_error, 0, sizeof(fork_error)); 149 *pid = static_cast<::pid_t>(pty.Fork(fork_error, sizeof(fork_error))); 150 if (*pid < 0) { 151 //-------------------------------------------------------------- 152 // Error during fork. 153 //-------------------------------------------------------------- 154 *pid = static_cast<::pid_t>(LLDB_INVALID_PROCESS_ID); 155 error.SetErrorStringWithFormat("%s(): fork failed: %s", __FUNCTION__, 156 fork_error); 157 return error; 158 } else if (pid == 0) { 159 //-------------------------------------------------------------- 160 // Child process 161 //-------------------------------------------------------------- 162 163 // Debug this process. 164 ::ptrace(PT_TRACE_ME, 0, 0, 0); 165 166 // Get BSD signals as mach exceptions. 167 ::ptrace(PT_SIGEXC, 0, 0, 0); 168 169 // If our parent is setgid, lets make sure we don't inherit those 170 // extra powers due to nepotism. 171 if (::setgid(getgid()) == 0) { 172 // Let the child have its own process group. We need to execute 173 // this call in both the child and parent to avoid a race 174 // condition between the two processes. 175 176 // Set the child process group to match its pid. 177 ::setpgid(0, 0); 178 179 // Sleep a bit to before the exec call. 180 ::sleep(1); 181 182 // Turn this process into the given executable. 183 ::execv(path, (char *const *)argv); 184 } 185 // Exit with error code. Child process should have taken 186 // over in above exec call and if the exec fails it will 187 // exit the child process below. 188 ::exit(127); 189 } else { 190 //-------------------------------------------------------------- 191 // Parent process 192 //-------------------------------------------------------------- 193 // Let the child have its own process group. We need to execute 194 // this call in both the child and parent to avoid a race condition 195 // between the two processes. 196 197 // Set the child process group to match its pid 198 ::setpgid(*pid, *pid); 199 if (pty_fd) { 200 // Release our master pty file descriptor so the pty class doesn't 201 // close it and so we can continue to use it in our STDIO thread 202 *pty_fd = pty.ReleaseMasterFileDescriptor(); 203 } 204 } 205 return error; 206 } 207 208 static Error 209 CreatePosixSpawnFileAction(const FileAction &action, 210 posix_spawn_file_actions_t *file_actions) { 211 Error error; 212 213 // Log it. 214 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 215 if (log) { 216 StreamString stream; 217 stream.PutCString("converting file action for posix_spawn(): "); 218 action.Dump(stream); 219 stream.Flush(); 220 log->PutCString(stream.GetString().c_str()); 221 } 222 223 // Validate args. 224 if (!file_actions) { 225 error.SetErrorString("mandatory file_actions arg is null"); 226 return error; 227 } 228 229 // Build the posix file action. 230 switch (action.GetAction()) { 231 case FileAction::eFileActionOpen: { 232 const int error_code = ::posix_spawn_file_actions_addopen( 233 file_actions, action.GetFD(), action.GetPath(), 234 action.GetActionArgument(), 0); 235 if (error_code != 0) { 236 error.SetError(error_code, eErrorTypePOSIX); 237 return error; 238 } 239 break; 240 } 241 242 case FileAction::eFileActionClose: { 243 const int error_code = 244 ::posix_spawn_file_actions_addclose(file_actions, action.GetFD()); 245 if (error_code != 0) { 246 error.SetError(error_code, eErrorTypePOSIX); 247 return error; 248 } 249 break; 250 } 251 252 case FileAction::eFileActionDuplicate: { 253 const int error_code = ::posix_spawn_file_actions_adddup2( 254 file_actions, action.GetFD(), action.GetActionArgument()); 255 if (error_code != 0) { 256 error.SetError(error_code, eErrorTypePOSIX); 257 return error; 258 } 259 break; 260 } 261 262 case FileAction::eFileActionNone: 263 default: 264 if (log) 265 log->Printf("%s(): unsupported file action %u", __FUNCTION__, 266 action.GetAction()); 267 break; 268 } 269 270 return error; 271 } 272 273 static Error PosixSpawnChildForPTraceDebugging(const char *path, 274 ProcessLaunchInfo &launch_info, 275 ::pid_t *pid, 276 cpu_type_t *actual_cpu_type) { 277 Error error; 278 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 279 280 if (!pid) { 281 error.SetErrorStringWithFormat("%s(): pid arg cannot be null", 282 __FUNCTION__); 283 return error; 284 } 285 286 posix_spawnattr_t attr; 287 short flags; 288 if (log) { 289 StreamString stream; 290 stream.Printf("%s(path='%s',...)\n", __FUNCTION__, path); 291 launch_info.Dump(stream, nullptr); 292 stream.Flush(); 293 log->PutCString(stream.GetString().c_str()); 294 } 295 296 int error_code; 297 if ((error_code = ::posix_spawnattr_init(&attr)) != 0) { 298 if (log) 299 log->Printf("::posix_spawnattr_init(&attr) failed"); 300 error.SetError(error_code, eErrorTypePOSIX); 301 return error; 302 } 303 304 // Ensure we clean up the spawnattr structure however we exit this 305 // function. 306 std::unique_ptr<posix_spawnattr_t, int (*)(posix_spawnattr_t *)> spawnattr_up( 307 &attr, ::posix_spawnattr_destroy); 308 309 flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF | 310 POSIX_SPAWN_SETSIGMASK; 311 if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) 312 flags |= _POSIX_SPAWN_DISABLE_ASLR; 313 314 sigset_t no_signals; 315 sigset_t all_signals; 316 sigemptyset(&no_signals); 317 sigfillset(&all_signals); 318 ::posix_spawnattr_setsigmask(&attr, &no_signals); 319 ::posix_spawnattr_setsigdefault(&attr, &all_signals); 320 321 if ((error_code = ::posix_spawnattr_setflags(&attr, flags)) != 0) { 322 if (log) 323 log->Printf("::posix_spawnattr_setflags(&attr, " 324 "POSIX_SPAWN_START_SUSPENDED%s) failed: %s", 325 flags & _POSIX_SPAWN_DISABLE_ASLR 326 ? " | _POSIX_SPAWN_DISABLE_ASLR" 327 : "", 328 strerror(error_code)); 329 error.SetError(error_code, eErrorTypePOSIX); 330 return error; 331 } 332 333 #if !defined(__arm__) 334 335 // We don't need to do this for ARM, and we really shouldn't now that we 336 // have multiple CPU subtypes and no posix_spawnattr call that allows us 337 // to set which CPU subtype to launch... 338 cpu_type_t desired_cpu_type = launch_info.GetArchitecture().GetMachOCPUType(); 339 if (desired_cpu_type != LLDB_INVALID_CPUTYPE) { 340 size_t ocount = 0; 341 error_code = 342 ::posix_spawnattr_setbinpref_np(&attr, 1, &desired_cpu_type, &ocount); 343 if (error_code != 0) { 344 if (log) 345 log->Printf("::posix_spawnattr_setbinpref_np(&attr, 1, " 346 "cpu_type = 0x%8.8x, count => %llu): %s", 347 desired_cpu_type, (uint64_t)ocount, strerror(error_code)); 348 error.SetError(error_code, eErrorTypePOSIX); 349 return error; 350 } 351 if (ocount != 1) { 352 error.SetErrorStringWithFormat("posix_spawnattr_setbinpref_np " 353 "did not set the expected number " 354 "of cpu_type entries: expected 1 " 355 "but was %zu", 356 ocount); 357 return error; 358 } 359 } 360 #endif 361 362 posix_spawn_file_actions_t file_actions; 363 if ((error_code = ::posix_spawn_file_actions_init(&file_actions)) != 0) { 364 if (log) 365 log->Printf("::posix_spawn_file_actions_init(&file_actions) " 366 "failed: %s", 367 strerror(error_code)); 368 error.SetError(error_code, eErrorTypePOSIX); 369 return error; 370 } 371 372 // Ensure we clean up file actions however we exit this. When the 373 // file_actions_up below goes out of scope, we'll get our file action 374 // cleanup. 375 std::unique_ptr<posix_spawn_file_actions_t, 376 int (*)(posix_spawn_file_actions_t *)> 377 file_actions_up(&file_actions, ::posix_spawn_file_actions_destroy); 378 379 // We assume the caller has setup the file actions appropriately. We 380 // are not in the business of figuring out what we really need here. 381 // lldb-server will have already called FinalizeFileActions() as well 382 // to button these up properly. 383 const size_t num_actions = launch_info.GetNumFileActions(); 384 for (size_t action_index = 0; action_index < num_actions; ++action_index) { 385 const FileAction *const action = 386 launch_info.GetFileActionAtIndex(action_index); 387 if (!action) 388 continue; 389 390 error = CreatePosixSpawnFileAction(*action, &file_actions); 391 if (!error.Success()) { 392 if (log) 393 log->Printf("%s(): error converting FileAction to posix_spawn " 394 "file action: %s", 395 __FUNCTION__, error.AsCString()); 396 return error; 397 } 398 } 399 400 // TODO: Verify if we can set the working directory back immediately 401 // after the posix_spawnp call without creating a race condition??? 402 const char *const working_directory = 403 launch_info.GetWorkingDirectory().GetCString(); 404 if (working_directory && working_directory[0]) 405 ::chdir(working_directory); 406 407 auto argv = launch_info.GetArguments().GetArgumentVector(); 408 auto envp = launch_info.GetEnvironmentEntries().GetArgumentVector(); 409 error_code = ::posix_spawnp(pid, path, &file_actions, &attr, 410 (char *const *)argv, (char *const *)envp); 411 if (error_code != 0) { 412 if (log) 413 log->Printf("::posix_spawnp(pid => %p, path = '%s', file_actions " 414 "= %p, attr = %p, argv = %p, envp = %p) failed: %s", 415 pid, path, &file_actions, &attr, argv, envp, 416 strerror(error_code)); 417 error.SetError(error_code, eErrorTypePOSIX); 418 return error; 419 } 420 421 // Validate we got a pid. 422 if (pid == LLDB_INVALID_PROCESS_ID) { 423 error.SetErrorString("posix_spawn() did not indicate a failure but it " 424 "failed to return a pid, aborting."); 425 return error; 426 } 427 428 if (actual_cpu_type) { 429 *actual_cpu_type = GetCPUTypeForLocalProcess(*pid); 430 if (log) 431 log->Printf("%s(): cpu type for launched process pid=%i: " 432 "cpu_type=0x%8.8x", 433 __FUNCTION__, *pid, *actual_cpu_type); 434 } 435 436 return error; 437 } 438 439 Error LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd, 440 LaunchFlavor *launch_flavor) { 441 Error error; 442 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 443 444 if (!launch_flavor) { 445 error.SetErrorString("mandatory launch_flavor field was null"); 446 return error; 447 } 448 449 if (log) { 450 StreamString stream; 451 stream.Printf("NativeProcessDarwin::%s(): launching with the " 452 "following launch info:", 453 __FUNCTION__); 454 launch_info.Dump(stream, nullptr); 455 stream.Flush(); 456 log->PutCString(stream.GetString().c_str()); 457 } 458 459 // Retrieve the binary name given to us. 460 char given_path[PATH_MAX]; 461 given_path[0] = '\0'; 462 launch_info.GetExecutableFile().GetPath(given_path, sizeof(given_path)); 463 464 // Determine the manner in which we'll launch. 465 *launch_flavor = g_launch_flavor; 466 if (*launch_flavor == LaunchFlavor::Default) { 467 // Our default launch method is posix spawn 468 *launch_flavor = LaunchFlavor::PosixSpawn; 469 #if defined WITH_FBS 470 // Check if we have an app bundle, if so launch using BackBoard Services. 471 if (strstr(given_path, ".app")) { 472 *launch_flavor = eLaunchFlavorFBS; 473 } 474 #elif defined WITH_BKS 475 // Check if we have an app bundle, if so launch using BackBoard Services. 476 if (strstr(given_path, ".app")) { 477 *launch_flavor = eLaunchFlavorBKS; 478 } 479 #elif defined WITH_SPRINGBOARD 480 // Check if we have an app bundle, if so launch using SpringBoard. 481 if (strstr(given_path, ".app")) { 482 *launch_flavor = eLaunchFlavorSpringBoard; 483 } 484 #endif 485 } 486 487 // Attempt to resolve the binary name to an absolute path. 488 char resolved_path[PATH_MAX]; 489 resolved_path[0] = '\0'; 490 491 if (log) 492 log->Printf("%s(): attempting to resolve given binary path: \"%s\"", 493 __FUNCTION__, given_path); 494 495 // If we fail to resolve the path to our executable, then just use what we 496 // were given and hope for the best 497 if (!ResolveExecutablePath(given_path, resolved_path, 498 sizeof(resolved_path))) { 499 if (log) 500 log->Printf("%s(): failed to resolve binary path, using " 501 "what was given verbatim and hoping for the best", 502 __FUNCTION__); 503 ::strncpy(resolved_path, given_path, sizeof(resolved_path)); 504 } else { 505 if (log) 506 log->Printf("%s(): resolved given binary path to: \"%s\"", __FUNCTION__, 507 resolved_path); 508 } 509 510 char launch_err_str[PATH_MAX]; 511 launch_err_str[0] = '\0'; 512 513 // TODO figure out how to handle QSetProcessEvent 514 // const char *process_event = ctx.GetProcessEvent(); 515 516 // Ensure the binary is there. 517 struct stat path_stat; 518 if (::stat(resolved_path, &path_stat) == -1) { 519 error.SetErrorToErrno(); 520 return error; 521 } 522 523 // Fork a child process for debugging 524 // state_callback(eStateLaunching); 525 526 const auto argv = launch_info.GetArguments().GetConstArgumentVector(); 527 const auto envp = 528 launch_info.GetEnvironmentEntries().GetConstArgumentVector(); 529 530 switch (*launch_flavor) { 531 case LaunchFlavor::ForkExec: { 532 ::pid_t pid = LLDB_INVALID_PROCESS_ID; 533 error = ForkChildForPTraceDebugging(resolved_path, argv, envp, &pid, 534 pty_master_fd); 535 if (error.Success()) { 536 launch_info.SetProcessID(static_cast<lldb::pid_t>(pid)); 537 } else { 538 // Reset any variables that might have been set during a failed 539 // launch attempt. 540 if (pty_master_fd) 541 *pty_master_fd = -1; 542 543 // We're done. 544 return error; 545 } 546 } break; 547 548 #ifdef WITH_FBS 549 case LaunchFlavor::FBS: { 550 const char *app_ext = strstr(path, ".app"); 551 if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) { 552 std::string app_bundle_path(path, app_ext + strlen(".app")); 553 m_flags |= eMachProcessFlagsUsingFBS; 554 if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp, 555 no_stdio, disable_aslr, event_data, 556 launch_err) != 0) 557 return m_pid; // A successful SBLaunchForDebug() returns and assigns a 558 // non-zero m_pid. 559 else 560 break; // We tried a FBS launch, but didn't succeed lets get out 561 } 562 } break; 563 #endif 564 565 #ifdef WITH_BKS 566 case LaunchFlavor::BKS: { 567 const char *app_ext = strstr(path, ".app"); 568 if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) { 569 std::string app_bundle_path(path, app_ext + strlen(".app")); 570 m_flags |= eMachProcessFlagsUsingBKS; 571 if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp, 572 no_stdio, disable_aslr, event_data, 573 launch_err) != 0) 574 return m_pid; // A successful SBLaunchForDebug() returns and assigns a 575 // non-zero m_pid. 576 else 577 break; // We tried a BKS launch, but didn't succeed lets get out 578 } 579 } break; 580 #endif 581 582 #ifdef WITH_SPRINGBOARD 583 case LaunchFlavor::SpringBoard: { 584 // .../whatever.app/whatever ? 585 // Or .../com.apple.whatever.app/whatever -- be careful of ".app" in 586 // "com.apple.whatever" here 587 const char *app_ext = strstr(path, ".app/"); 588 if (app_ext == NULL) { 589 // .../whatever.app ? 590 int len = strlen(path); 591 if (len > 5) { 592 if (strcmp(path + len - 4, ".app") == 0) { 593 app_ext = path + len - 4; 594 } 595 } 596 } 597 if (app_ext) { 598 std::string app_bundle_path(path, app_ext + strlen(".app")); 599 if (SBLaunchForDebug(app_bundle_path.c_str(), argv, envp, no_stdio, 600 disable_aslr, launch_err) != 0) 601 return m_pid; // A successful SBLaunchForDebug() returns and assigns a 602 // non-zero m_pid. 603 else 604 break; // We tried a springboard launch, but didn't succeed lets get out 605 } 606 } break; 607 #endif 608 609 case LaunchFlavor::PosixSpawn: { 610 ::pid_t pid = LLDB_INVALID_PROCESS_ID; 611 612 // Retrieve paths for stdin/stdout/stderr. 613 cpu_type_t actual_cpu_type = 0; 614 error = PosixSpawnChildForPTraceDebugging(resolved_path, launch_info, &pid, 615 &actual_cpu_type); 616 if (error.Success()) { 617 launch_info.SetProcessID(static_cast<lldb::pid_t>(pid)); 618 if (pty_master_fd) 619 *pty_master_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 620 } else { 621 // Reset any variables that might have been set during a failed 622 // launch attempt. 623 if (pty_master_fd) 624 *pty_master_fd = -1; 625 626 // We're done. 627 return error; 628 } 629 break; 630 } 631 632 default: 633 // Invalid launch flavor. 634 error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): unknown " 635 "launch flavor %d", 636 __FUNCTION__, (int)*launch_flavor); 637 return error; 638 } 639 640 if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) { 641 // If we don't have a valid process ID and no one has set the error, 642 // then return a generic error. 643 if (error.Success()) 644 error.SetErrorStringWithFormat("%s(): failed to launch, no reason " 645 "specified", 646 __FUNCTION__); 647 } 648 649 // We're done with the launch side of the operation. 650 return error; 651 } 652 } 653 } // namespaces 654