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