1 //===-- Host.cpp ----------------------------------------------------------===// 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 // C includes 10 #include <cerrno> 11 #include <climits> 12 #include <cstdlib> 13 #include <sys/types.h> 14 #ifndef _WIN32 15 #include <dlfcn.h> 16 #include <grp.h> 17 #include <netdb.h> 18 #include <pwd.h> 19 #include <sys/stat.h> 20 #include <unistd.h> 21 #endif 22 23 #if defined(__APPLE__) 24 #include <mach-o/dyld.h> 25 #include <mach/mach_init.h> 26 #include <mach/mach_port.h> 27 #endif 28 29 #if defined(__linux__) || defined(__FreeBSD__) || \ 30 defined(__FreeBSD_kernel__) || defined(__APPLE__) || \ 31 defined(__NetBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) 32 #if !defined(__ANDROID__) 33 #include <spawn.h> 34 #endif 35 #include <sys/syscall.h> 36 #include <sys/wait.h> 37 #endif 38 39 #if defined(__FreeBSD__) 40 #include <pthread_np.h> 41 #endif 42 43 #if defined(__NetBSD__) 44 #include <lwp.h> 45 #endif 46 47 #include <csignal> 48 49 #include "lldb/Host/FileAction.h" 50 #include "lldb/Host/FileSystem.h" 51 #include "lldb/Host/Host.h" 52 #include "lldb/Host/HostInfo.h" 53 #include "lldb/Host/HostProcess.h" 54 #include "lldb/Host/MonitoringProcessLauncher.h" 55 #include "lldb/Host/ProcessLaunchInfo.h" 56 #include "lldb/Host/ProcessLauncher.h" 57 #include "lldb/Host/ThreadLauncher.h" 58 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" 59 #include "lldb/Utility/DataBufferLLVM.h" 60 #include "lldb/Utility/FileSpec.h" 61 #include "lldb/Utility/Log.h" 62 #include "lldb/Utility/Predicate.h" 63 #include "lldb/Utility/ReproducerProvider.h" 64 #include "lldb/Utility/Status.h" 65 #include "lldb/lldb-private-forward.h" 66 #include "llvm/ADT/SmallString.h" 67 #include "llvm/ADT/StringSwitch.h" 68 #include "llvm/Support/Errno.h" 69 #include "llvm/Support/FileSystem.h" 70 71 #if defined(_WIN32) 72 #include "lldb/Host/windows/ConnectionGenericFileWindows.h" 73 #include "lldb/Host/windows/ProcessLauncherWindows.h" 74 #else 75 #include "lldb/Host/posix/ProcessLauncherPosixFork.h" 76 #endif 77 78 #if defined(__APPLE__) 79 #ifndef _POSIX_SPAWN_DISABLE_ASLR 80 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 81 #endif 82 83 extern "C" { 84 int __pthread_chdir(const char *path); 85 int __pthread_fchdir(int fildes); 86 } 87 88 #endif 89 90 using namespace lldb; 91 using namespace lldb_private; 92 93 #if !defined(__APPLE__) && !defined(_WIN32) 94 struct MonitorInfo { 95 lldb::pid_t pid; // The process ID to monitor 96 Host::MonitorChildProcessCallback 97 callback; // The callback function to call when "pid" exits or signals 98 bool monitor_signals; // If true, call the callback when "pid" gets signaled. 99 }; 100 101 static thread_result_t MonitorChildProcessThreadFunction(void *arg); 102 103 llvm::Expected<HostThread> Host::StartMonitoringChildProcess( 104 const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, 105 bool monitor_signals) { 106 MonitorInfo *info_ptr = new MonitorInfo(); 107 108 info_ptr->pid = pid; 109 info_ptr->callback = callback; 110 info_ptr->monitor_signals = monitor_signals; 111 112 char thread_name[256]; 113 ::snprintf(thread_name, sizeof(thread_name), 114 "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); 115 return ThreadLauncher::LaunchThread( 116 thread_name, MonitorChildProcessThreadFunction, info_ptr, 0); 117 } 118 119 #ifndef __linux__ 120 // Scoped class that will disable thread canceling when it is constructed, and 121 // exception safely restore the previous value it when it goes out of scope. 122 class ScopedPThreadCancelDisabler { 123 public: 124 ScopedPThreadCancelDisabler() { 125 // Disable the ability for this thread to be cancelled 126 int err = ::pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &m_old_state); 127 if (err != 0) 128 m_old_state = -1; 129 } 130 131 ~ScopedPThreadCancelDisabler() { 132 // Restore the ability for this thread to be cancelled to what it 133 // previously was. 134 if (m_old_state != -1) 135 ::pthread_setcancelstate(m_old_state, 0); 136 } 137 138 private: 139 int m_old_state; // Save the old cancelability state. 140 }; 141 #endif // __linux__ 142 143 #ifdef __linux__ 144 #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) 145 static __thread volatile sig_atomic_t g_usr1_called; 146 #else 147 static thread_local volatile sig_atomic_t g_usr1_called; 148 #endif 149 150 static void SigUsr1Handler(int) { g_usr1_called = 1; } 151 #endif // __linux__ 152 153 static bool CheckForMonitorCancellation() { 154 #ifdef __linux__ 155 if (g_usr1_called) { 156 g_usr1_called = 0; 157 return true; 158 } 159 #else 160 ::pthread_testcancel(); 161 #endif 162 return false; 163 } 164 165 static thread_result_t MonitorChildProcessThreadFunction(void *arg) { 166 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 167 const char *function = __FUNCTION__; 168 LLDB_LOGF(log, "%s (arg = %p) thread starting...", function, arg); 169 170 MonitorInfo *info = (MonitorInfo *)arg; 171 172 const Host::MonitorChildProcessCallback callback = info->callback; 173 const bool monitor_signals = info->monitor_signals; 174 175 assert(info->pid <= UINT32_MAX); 176 const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid; 177 178 delete info; 179 180 int status = -1; 181 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) 182 #define __WALL 0 183 #endif 184 const int options = __WALL; 185 186 #ifdef __linux__ 187 // This signal is only used to interrupt the thread from waitpid 188 struct sigaction sigUsr1Action; 189 memset(&sigUsr1Action, 0, sizeof(sigUsr1Action)); 190 sigUsr1Action.sa_handler = SigUsr1Handler; 191 ::sigaction(SIGUSR1, &sigUsr1Action, nullptr); 192 #endif // __linux__ 193 194 while (true) { 195 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); 196 LLDB_LOGF(log, "%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", 197 function, pid, options); 198 199 if (CheckForMonitorCancellation()) 200 break; 201 202 // Get signals from all children with same process group of pid 203 const ::pid_t wait_pid = ::waitpid(pid, &status, options); 204 205 if (CheckForMonitorCancellation()) 206 break; 207 208 if (wait_pid == -1) { 209 if (errno == EINTR) 210 continue; 211 else { 212 LLDB_LOG(log, 213 "arg = {0}, thread exiting because waitpid failed ({1})...", 214 arg, llvm::sys::StrError()); 215 break; 216 } 217 } else if (wait_pid > 0) { 218 bool exited = false; 219 int signal = 0; 220 int exit_status = 0; 221 const char *status_cstr = nullptr; 222 if (WIFSTOPPED(status)) { 223 signal = WSTOPSIG(status); 224 status_cstr = "STOPPED"; 225 } else if (WIFEXITED(status)) { 226 exit_status = WEXITSTATUS(status); 227 status_cstr = "EXITED"; 228 exited = true; 229 } else if (WIFSIGNALED(status)) { 230 signal = WTERMSIG(status); 231 status_cstr = "SIGNALED"; 232 if (wait_pid == abs(pid)) { 233 exited = true; 234 exit_status = -1; 235 } 236 } else { 237 status_cstr = "(\?\?\?)"; 238 } 239 240 // Scope for pthread_cancel_disabler 241 { 242 #ifndef __linux__ 243 ScopedPThreadCancelDisabler pthread_cancel_disabler; 244 #endif 245 246 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); 247 LLDB_LOGF(log, 248 "%s ::waitpid (pid = %" PRIi32 249 ", &status, options = %i) => pid = %" PRIi32 250 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", 251 function, pid, options, wait_pid, status, status_cstr, signal, 252 exit_status); 253 254 if (exited || (signal != 0 && monitor_signals)) { 255 bool callback_return = false; 256 if (callback) 257 callback_return = callback(wait_pid, exited, signal, exit_status); 258 259 // If our process exited, then this thread should exit 260 if (exited && wait_pid == abs(pid)) { 261 LLDB_LOGF(log, 262 "%s (arg = %p) thread exiting because pid received " 263 "exit signal...", 264 __FUNCTION__, arg); 265 break; 266 } 267 // If the callback returns true, it means this process should exit 268 if (callback_return) { 269 LLDB_LOGF(log, 270 "%s (arg = %p) thread exiting because callback " 271 "returned true...", 272 __FUNCTION__, arg); 273 break; 274 } 275 } 276 } 277 } 278 } 279 280 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); 281 LLDB_LOGF(log, "%s (arg = %p) thread exiting...", __FUNCTION__, arg); 282 283 return nullptr; 284 } 285 286 #endif // #if !defined (__APPLE__) && !defined (_WIN32) 287 288 #if !defined(__APPLE__) 289 290 void Host::SystemLog(SystemLogType type, const char *format, va_list args) { 291 vfprintf(stderr, format, args); 292 } 293 294 #endif 295 296 void Host::SystemLog(SystemLogType type, const char *format, ...) { 297 { 298 va_list args; 299 va_start(args, format); 300 SystemLog(type, format, args); 301 va_end(args); 302 } 303 304 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST)); 305 if (log && log->GetVerbose()) { 306 // Log to log channel. This allows testcases to grep for log output. 307 va_list args; 308 va_start(args, format); 309 log->VAPrintf(format, args); 310 va_end(args); 311 } 312 } 313 314 lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); } 315 316 #ifndef _WIN32 317 318 lldb::thread_t Host::GetCurrentThread() { 319 return lldb::thread_t(pthread_self()); 320 } 321 322 const char *Host::GetSignalAsCString(int signo) { 323 switch (signo) { 324 case SIGHUP: 325 return "SIGHUP"; // 1 hangup 326 case SIGINT: 327 return "SIGINT"; // 2 interrupt 328 case SIGQUIT: 329 return "SIGQUIT"; // 3 quit 330 case SIGILL: 331 return "SIGILL"; // 4 illegal instruction (not reset when caught) 332 case SIGTRAP: 333 return "SIGTRAP"; // 5 trace trap (not reset when caught) 334 case SIGABRT: 335 return "SIGABRT"; // 6 abort() 336 #if defined(SIGPOLL) 337 #if !defined(SIGIO) || (SIGPOLL != SIGIO) 338 // Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to 339 // fail with 'multiple define cases with same value' 340 case SIGPOLL: 341 return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) 342 #endif 343 #endif 344 #if defined(SIGEMT) 345 case SIGEMT: 346 return "SIGEMT"; // 7 EMT instruction 347 #endif 348 case SIGFPE: 349 return "SIGFPE"; // 8 floating point exception 350 case SIGKILL: 351 return "SIGKILL"; // 9 kill (cannot be caught or ignored) 352 case SIGBUS: 353 return "SIGBUS"; // 10 bus error 354 case SIGSEGV: 355 return "SIGSEGV"; // 11 segmentation violation 356 case SIGSYS: 357 return "SIGSYS"; // 12 bad argument to system call 358 case SIGPIPE: 359 return "SIGPIPE"; // 13 write on a pipe with no one to read it 360 case SIGALRM: 361 return "SIGALRM"; // 14 alarm clock 362 case SIGTERM: 363 return "SIGTERM"; // 15 software termination signal from kill 364 case SIGURG: 365 return "SIGURG"; // 16 urgent condition on IO channel 366 case SIGSTOP: 367 return "SIGSTOP"; // 17 sendable stop signal not from tty 368 case SIGTSTP: 369 return "SIGTSTP"; // 18 stop signal from tty 370 case SIGCONT: 371 return "SIGCONT"; // 19 continue a stopped process 372 case SIGCHLD: 373 return "SIGCHLD"; // 20 to parent on child stop or exit 374 case SIGTTIN: 375 return "SIGTTIN"; // 21 to readers pgrp upon background tty read 376 case SIGTTOU: 377 return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) 378 #if defined(SIGIO) 379 case SIGIO: 380 return "SIGIO"; // 23 input/output possible signal 381 #endif 382 case SIGXCPU: 383 return "SIGXCPU"; // 24 exceeded CPU time limit 384 case SIGXFSZ: 385 return "SIGXFSZ"; // 25 exceeded file size limit 386 case SIGVTALRM: 387 return "SIGVTALRM"; // 26 virtual time alarm 388 case SIGPROF: 389 return "SIGPROF"; // 27 profiling time alarm 390 #if defined(SIGWINCH) 391 case SIGWINCH: 392 return "SIGWINCH"; // 28 window size changes 393 #endif 394 #if defined(SIGINFO) 395 case SIGINFO: 396 return "SIGINFO"; // 29 information request 397 #endif 398 case SIGUSR1: 399 return "SIGUSR1"; // 30 user defined signal 1 400 case SIGUSR2: 401 return "SIGUSR2"; // 31 user defined signal 2 402 default: 403 break; 404 } 405 return nullptr; 406 } 407 408 #endif 409 410 #if !defined(__APPLE__) // see Host.mm 411 412 bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle) { 413 bundle.Clear(); 414 return false; 415 } 416 417 bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; } 418 #endif 419 420 #ifndef _WIN32 421 422 FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { 423 FileSpec module_filespec; 424 #if !defined(__ANDROID__) 425 Dl_info info; 426 if (::dladdr(host_addr, &info)) { 427 if (info.dli_fname) { 428 module_filespec.SetFile(info.dli_fname, FileSpec::Style::native); 429 FileSystem::Instance().Resolve(module_filespec); 430 } 431 } 432 #endif 433 return module_filespec; 434 } 435 436 #endif 437 438 #if !defined(__linux__) 439 bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) { 440 return false; 441 } 442 #endif 443 444 struct ShellInfo { 445 ShellInfo() : process_reaped(false) {} 446 447 lldb_private::Predicate<bool> process_reaped; 448 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 449 int signo = -1; 450 int status = -1; 451 }; 452 453 static bool 454 MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid, 455 bool exited, // True if the process did exit 456 int signo, // Zero for no signal 457 int status) // Exit value of process if signal is zero 458 { 459 shell_info->pid = pid; 460 shell_info->signo = signo; 461 shell_info->status = status; 462 // Let the thread running Host::RunShellCommand() know that the process 463 // exited and that ShellInfo has been filled in by broadcasting to it 464 shell_info->process_reaped.SetValue(true, eBroadcastAlways); 465 return true; 466 } 467 468 Status Host::RunShellCommand(llvm::StringRef command, 469 const FileSpec &working_dir, int *status_ptr, 470 int *signo_ptr, std::string *command_output_ptr, 471 const Timeout<std::micro> &timeout, 472 bool run_in_shell, bool hide_stderr) { 473 return RunShellCommand(llvm::StringRef(), Args(command), working_dir, 474 status_ptr, signo_ptr, command_output_ptr, timeout, 475 run_in_shell, hide_stderr); 476 } 477 478 Status Host::RunShellCommand(llvm::StringRef shell_path, 479 llvm::StringRef command, 480 const FileSpec &working_dir, int *status_ptr, 481 int *signo_ptr, std::string *command_output_ptr, 482 const Timeout<std::micro> &timeout, 483 bool run_in_shell, bool hide_stderr) { 484 return RunShellCommand(shell_path, Args(command), working_dir, status_ptr, 485 signo_ptr, command_output_ptr, timeout, run_in_shell, 486 hide_stderr); 487 } 488 489 Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, 490 int *status_ptr, int *signo_ptr, 491 std::string *command_output_ptr, 492 const Timeout<std::micro> &timeout, 493 bool run_in_shell, bool hide_stderr) { 494 return RunShellCommand(llvm::StringRef(), args, working_dir, status_ptr, 495 signo_ptr, command_output_ptr, timeout, run_in_shell, 496 hide_stderr); 497 } 498 499 Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args, 500 const FileSpec &working_dir, int *status_ptr, 501 int *signo_ptr, std::string *command_output_ptr, 502 const Timeout<std::micro> &timeout, 503 bool run_in_shell, bool hide_stderr) { 504 Status error; 505 ProcessLaunchInfo launch_info; 506 launch_info.SetArchitecture(HostInfo::GetArchitecture()); 507 if (run_in_shell) { 508 // Run the command in a shell 509 FileSpec shell = HostInfo::GetDefaultShell(); 510 if (!shell_path.empty()) 511 shell.SetPath(shell_path); 512 513 launch_info.SetShell(shell); 514 launch_info.GetArguments().AppendArguments(args); 515 const bool will_debug = false; 516 const bool first_arg_is_full_shell_command = false; 517 launch_info.ConvertArgumentsForLaunchingInShell( 518 error, will_debug, first_arg_is_full_shell_command, 0); 519 } else { 520 // No shell, just run it 521 const bool first_arg_is_executable = true; 522 launch_info.SetArguments(args, first_arg_is_executable); 523 } 524 525 launch_info.GetEnvironment() = Host::GetEnvironment(); 526 527 if (working_dir) 528 launch_info.SetWorkingDirectory(working_dir); 529 llvm::SmallString<64> output_file_path; 530 531 if (command_output_ptr) { 532 // Create a temporary file to get the stdout/stderr and redirect the output 533 // of the command into this file. We will later read this file if all goes 534 // well and fill the data into "command_output_ptr" 535 if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) { 536 tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); 537 llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(), 538 output_file_path); 539 } else { 540 llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", 541 output_file_path); 542 } 543 } 544 545 FileSpec output_file_spec(output_file_path.str()); 546 // Set up file descriptors. 547 launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); 548 if (output_file_spec) 549 launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, 550 true); 551 else 552 launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); 553 554 if (output_file_spec && !hide_stderr) 555 launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); 556 else 557 launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); 558 559 std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo()); 560 const bool monitor_signals = false; 561 launch_info.SetMonitorProcessCallback( 562 std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1, 563 std::placeholders::_2, std::placeholders::_3, 564 std::placeholders::_4), 565 monitor_signals); 566 567 error = LaunchProcess(launch_info); 568 const lldb::pid_t pid = launch_info.GetProcessID(); 569 570 if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) 571 error.SetErrorString("failed to get process ID"); 572 573 if (error.Success()) { 574 if (!shell_info_sp->process_reaped.WaitForValueEqualTo(true, timeout)) { 575 error.SetErrorString("timed out waiting for shell command to complete"); 576 577 // Kill the process since it didn't complete within the timeout specified 578 Kill(pid, SIGKILL); 579 // Wait for the monitor callback to get the message 580 shell_info_sp->process_reaped.WaitForValueEqualTo( 581 true, std::chrono::seconds(1)); 582 } else { 583 if (status_ptr) 584 *status_ptr = shell_info_sp->status; 585 586 if (signo_ptr) 587 *signo_ptr = shell_info_sp->signo; 588 589 if (command_output_ptr) { 590 command_output_ptr->clear(); 591 uint64_t file_size = 592 FileSystem::Instance().GetByteSize(output_file_spec); 593 if (file_size > 0) { 594 if (file_size > command_output_ptr->max_size()) { 595 error.SetErrorStringWithFormat( 596 "shell command output is too large to fit into a std::string"); 597 } else { 598 auto Buffer = 599 FileSystem::Instance().CreateDataBuffer(output_file_spec); 600 if (error.Success()) 601 command_output_ptr->assign(Buffer->GetChars(), 602 Buffer->GetByteSize()); 603 } 604 } 605 } 606 } 607 } 608 609 llvm::sys::fs::remove(output_file_spec.GetPath()); 610 return error; 611 } 612 613 // The functions below implement process launching for non-Apple-based 614 // platforms 615 #if !defined(__APPLE__) 616 Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { 617 std::unique_ptr<ProcessLauncher> delegate_launcher; 618 #if defined(_WIN32) 619 delegate_launcher.reset(new ProcessLauncherWindows()); 620 #else 621 delegate_launcher.reset(new ProcessLauncherPosixFork()); 622 #endif 623 MonitoringProcessLauncher launcher(std::move(delegate_launcher)); 624 625 Status error; 626 HostProcess process = launcher.LaunchProcess(launch_info, error); 627 628 // TODO(zturner): It would be better if the entire HostProcess were returned 629 // instead of writing it into this structure. 630 launch_info.SetProcessID(process.GetProcessId()); 631 632 return error; 633 } 634 #endif // !defined(__APPLE__) 635 636 #ifndef _WIN32 637 void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); } 638 639 #endif 640 641 #if !defined(__APPLE__) 642 bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, 643 uint32_t line_no) { 644 return false; 645 } 646 647 #endif 648 649 std::unique_ptr<Connection> Host::CreateDefaultConnection(llvm::StringRef url) { 650 #if defined(_WIN32) 651 if (url.startswith("file://")) 652 return std::unique_ptr<Connection>(new ConnectionGenericFile()); 653 #endif 654 return std::unique_ptr<Connection>(new ConnectionFileDescriptor()); 655 } 656 657 #if defined(LLVM_ON_UNIX) 658 WaitStatus WaitStatus::Decode(int wstatus) { 659 if (WIFEXITED(wstatus)) 660 return {Exit, uint8_t(WEXITSTATUS(wstatus))}; 661 else if (WIFSIGNALED(wstatus)) 662 return {Signal, uint8_t(WTERMSIG(wstatus))}; 663 else if (WIFSTOPPED(wstatus)) 664 return {Stop, uint8_t(WSTOPSIG(wstatus))}; 665 llvm_unreachable("Unknown wait status"); 666 } 667 #endif 668 669 void llvm::format_provider<WaitStatus>::format(const WaitStatus &WS, 670 raw_ostream &OS, 671 StringRef Options) { 672 if (Options == "g") { 673 char type; 674 switch (WS.type) { 675 case WaitStatus::Exit: 676 type = 'W'; 677 break; 678 case WaitStatus::Signal: 679 type = 'X'; 680 break; 681 case WaitStatus::Stop: 682 type = 'S'; 683 break; 684 } 685 OS << formatv("{0}{1:x-2}", type, WS.status); 686 return; 687 } 688 689 assert(Options.empty()); 690 const char *desc; 691 switch(WS.type) { 692 case WaitStatus::Exit: 693 desc = "Exited with status"; 694 break; 695 case WaitStatus::Signal: 696 desc = "Killed by signal"; 697 break; 698 case WaitStatus::Stop: 699 desc = "Stopped by signal"; 700 break; 701 } 702 OS << desc << " " << int(WS.status); 703 } 704 705 uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, 706 ProcessInstanceInfoList &process_infos) { 707 708 if (llvm::Optional<ProcessInstanceInfoList> infos = 709 repro::GetReplayProcessInstanceInfoList()) { 710 process_infos = *infos; 711 return process_infos.size(); 712 } 713 714 uint32_t result = FindProcessesImpl(match_info, process_infos); 715 716 if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { 717 g->GetOrCreate<repro::ProcessInfoProvider>() 718 .GetNewProcessInfoRecorder() 719 ->Record(process_infos); 720 } 721 722 return result; 723 } 724