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