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