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 <errno.h> 11 #include <limits.h> 12 #include <stdlib.h> 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 (1) { 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() 446 : process_reaped(false), pid(LLDB_INVALID_PROCESS_ID), signo(-1), 447 status(-1) {} 448 449 lldb_private::Predicate<bool> process_reaped; 450 lldb::pid_t pid; 451 int signo; 452 int status; 453 }; 454 455 static bool 456 MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid, 457 bool exited, // True if the process did exit 458 int signo, // Zero for no signal 459 int status) // Exit value of process if signal is zero 460 { 461 shell_info->pid = pid; 462 shell_info->signo = signo; 463 shell_info->status = status; 464 // Let the thread running Host::RunShellCommand() know that the process 465 // exited and that ShellInfo has been filled in by broadcasting to it 466 shell_info->process_reaped.SetValue(true, eBroadcastAlways); 467 return true; 468 } 469 470 Status Host::RunShellCommand(llvm::StringRef command, 471 const FileSpec &working_dir, int *status_ptr, 472 int *signo_ptr, std::string *command_output_ptr, 473 const Timeout<std::micro> &timeout, 474 bool run_in_shell, bool hide_stderr) { 475 return RunShellCommand(llvm::StringRef(), Args(command), working_dir, 476 status_ptr, signo_ptr, command_output_ptr, timeout, 477 run_in_shell, hide_stderr); 478 } 479 480 Status Host::RunShellCommand(llvm::StringRef shell_path, 481 llvm::StringRef command, 482 const FileSpec &working_dir, int *status_ptr, 483 int *signo_ptr, std::string *command_output_ptr, 484 const Timeout<std::micro> &timeout, 485 bool run_in_shell, bool hide_stderr) { 486 return RunShellCommand(shell_path, Args(command), working_dir, status_ptr, 487 signo_ptr, command_output_ptr, timeout, run_in_shell, 488 hide_stderr); 489 } 490 491 Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir, 492 int *status_ptr, int *signo_ptr, 493 std::string *command_output_ptr, 494 const Timeout<std::micro> &timeout, 495 bool run_in_shell, bool hide_stderr) { 496 return RunShellCommand(llvm::StringRef(), args, working_dir, status_ptr, 497 signo_ptr, command_output_ptr, timeout, run_in_shell, 498 hide_stderr); 499 } 500 501 Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args, 502 const FileSpec &working_dir, int *status_ptr, 503 int *signo_ptr, std::string *command_output_ptr, 504 const Timeout<std::micro> &timeout, 505 bool run_in_shell, bool hide_stderr) { 506 Status error; 507 ProcessLaunchInfo launch_info; 508 launch_info.SetArchitecture(HostInfo::GetArchitecture()); 509 if (run_in_shell) { 510 // Run the command in a shell 511 FileSpec shell = HostInfo::GetDefaultShell(); 512 if (!shell_path.empty()) 513 shell.SetPath(shell_path); 514 515 launch_info.SetShell(shell); 516 launch_info.GetArguments().AppendArguments(args); 517 const bool will_debug = false; 518 const bool first_arg_is_full_shell_command = false; 519 launch_info.ConvertArgumentsForLaunchingInShell( 520 error, will_debug, first_arg_is_full_shell_command, 0); 521 } else { 522 // No shell, just run it 523 const bool first_arg_is_executable = true; 524 launch_info.SetArguments(args, first_arg_is_executable); 525 } 526 527 launch_info.GetEnvironment() = Host::GetEnvironment(); 528 529 if (working_dir) 530 launch_info.SetWorkingDirectory(working_dir); 531 llvm::SmallString<64> output_file_path; 532 533 if (command_output_ptr) { 534 // Create a temporary file to get the stdout/stderr and redirect the output 535 // of the command into this file. We will later read this file if all goes 536 // well and fill the data into "command_output_ptr" 537 if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) { 538 tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); 539 llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(), 540 output_file_path); 541 } else { 542 llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", 543 output_file_path); 544 } 545 } 546 547 FileSpec output_file_spec(output_file_path.str()); 548 // Set up file descriptors. 549 launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); 550 if (output_file_spec) 551 launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, 552 true); 553 else 554 launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); 555 556 if (output_file_spec && !hide_stderr) 557 launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); 558 else 559 launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); 560 561 std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo()); 562 const bool monitor_signals = false; 563 launch_info.SetMonitorProcessCallback( 564 std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1, 565 std::placeholders::_2, std::placeholders::_3, 566 std::placeholders::_4), 567 monitor_signals); 568 569 error = LaunchProcess(launch_info); 570 const lldb::pid_t pid = launch_info.GetProcessID(); 571 572 if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) 573 error.SetErrorString("failed to get process ID"); 574 575 if (error.Success()) { 576 if (!shell_info_sp->process_reaped.WaitForValueEqualTo(true, timeout)) { 577 error.SetErrorString("timed out waiting for shell command to complete"); 578 579 // Kill the process since it didn't complete within the timeout specified 580 Kill(pid, SIGKILL); 581 // Wait for the monitor callback to get the message 582 shell_info_sp->process_reaped.WaitForValueEqualTo( 583 true, std::chrono::seconds(1)); 584 } else { 585 if (status_ptr) 586 *status_ptr = shell_info_sp->status; 587 588 if (signo_ptr) 589 *signo_ptr = shell_info_sp->signo; 590 591 if (command_output_ptr) { 592 command_output_ptr->clear(); 593 uint64_t file_size = 594 FileSystem::Instance().GetByteSize(output_file_spec); 595 if (file_size > 0) { 596 if (file_size > command_output_ptr->max_size()) { 597 error.SetErrorStringWithFormat( 598 "shell command output is too large to fit into a std::string"); 599 } else { 600 auto Buffer = 601 FileSystem::Instance().CreateDataBuffer(output_file_spec); 602 if (error.Success()) 603 command_output_ptr->assign(Buffer->GetChars(), 604 Buffer->GetByteSize()); 605 } 606 } 607 } 608 } 609 } 610 611 llvm::sys::fs::remove(output_file_spec.GetPath()); 612 return error; 613 } 614 615 // The functions below implement process launching for non-Apple-based 616 // platforms 617 #if !defined(__APPLE__) 618 Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { 619 std::unique_ptr<ProcessLauncher> delegate_launcher; 620 #if defined(_WIN32) 621 delegate_launcher.reset(new ProcessLauncherWindows()); 622 #else 623 delegate_launcher.reset(new ProcessLauncherPosixFork()); 624 #endif 625 MonitoringProcessLauncher launcher(std::move(delegate_launcher)); 626 627 Status error; 628 HostProcess process = launcher.LaunchProcess(launch_info, error); 629 630 // TODO(zturner): It would be better if the entire HostProcess were returned 631 // instead of writing it into this structure. 632 launch_info.SetProcessID(process.GetProcessId()); 633 634 return error; 635 } 636 #endif // !defined(__APPLE__) 637 638 #ifndef _WIN32 639 void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); } 640 641 #endif 642 643 #if !defined(__APPLE__) 644 bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, 645 uint32_t line_no) { 646 return false; 647 } 648 649 #endif 650 651 std::unique_ptr<Connection> Host::CreateDefaultConnection(llvm::StringRef url) { 652 #if defined(_WIN32) 653 if (url.startswith("file://")) 654 return std::unique_ptr<Connection>(new ConnectionGenericFile()); 655 #endif 656 return std::unique_ptr<Connection>(new ConnectionFileDescriptor()); 657 } 658 659 #if defined(LLVM_ON_UNIX) 660 WaitStatus WaitStatus::Decode(int wstatus) { 661 if (WIFEXITED(wstatus)) 662 return {Exit, uint8_t(WEXITSTATUS(wstatus))}; 663 else if (WIFSIGNALED(wstatus)) 664 return {Signal, uint8_t(WTERMSIG(wstatus))}; 665 else if (WIFSTOPPED(wstatus)) 666 return {Stop, uint8_t(WSTOPSIG(wstatus))}; 667 llvm_unreachable("Unknown wait status"); 668 } 669 #endif 670 671 void llvm::format_provider<WaitStatus>::format(const WaitStatus &WS, 672 raw_ostream &OS, 673 StringRef Options) { 674 if (Options == "g") { 675 char type; 676 switch (WS.type) { 677 case WaitStatus::Exit: 678 type = 'W'; 679 break; 680 case WaitStatus::Signal: 681 type = 'X'; 682 break; 683 case WaitStatus::Stop: 684 type = 'S'; 685 break; 686 } 687 OS << formatv("{0}{1:x-2}", type, WS.status); 688 return; 689 } 690 691 assert(Options.empty()); 692 const char *desc; 693 switch(WS.type) { 694 case WaitStatus::Exit: 695 desc = "Exited with status"; 696 break; 697 case WaitStatus::Signal: 698 desc = "Killed by signal"; 699 break; 700 case WaitStatus::Stop: 701 desc = "Stopped by signal"; 702 break; 703 } 704 OS << desc << " " << int(WS.status); 705 } 706 707 uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, 708 ProcessInstanceInfoList &process_infos) { 709 710 if (llvm::Optional<ProcessInstanceInfoList> infos = 711 repro::GetReplayProcessInstanceInfoList()) { 712 process_infos = *infos; 713 return process_infos.size(); 714 } 715 716 uint32_t result = FindProcessesImpl(match_info, process_infos); 717 718 if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { 719 g->GetOrCreate<repro::ProcessInfoProvider>() 720 .GetNewProcessInfoRecorder() 721 ->Record(process_infos); 722 } 723 724 return result; 725 } 726