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