xref: /openbsd-src/gnu/llvm/lldb/source/Host/common/Host.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- Host.cpp ----------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick // C includes
10be691f3bSpatrick #include <cerrno>
11be691f3bSpatrick #include <climits>
12be691f3bSpatrick #include <cstdlib>
13061da546Spatrick #include <sys/types.h>
14061da546Spatrick #ifndef _WIN32
15061da546Spatrick #include <dlfcn.h>
16061da546Spatrick #include <grp.h>
17061da546Spatrick #include <netdb.h>
18061da546Spatrick #include <pwd.h>
19061da546Spatrick #include <sys/stat.h>
20061da546Spatrick #include <unistd.h>
21061da546Spatrick #endif
22061da546Spatrick 
23061da546Spatrick #if defined(__APPLE__)
24061da546Spatrick #include <mach-o/dyld.h>
25061da546Spatrick #include <mach/mach_init.h>
26061da546Spatrick #include <mach/mach_port.h>
27061da546Spatrick #endif
28061da546Spatrick 
29061da546Spatrick #if defined(__linux__) || defined(__FreeBSD__) ||                              \
30061da546Spatrick     defined(__FreeBSD_kernel__) || defined(__APPLE__) ||                       \
31dda28197Spatrick     defined(__NetBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
32061da546Spatrick #if !defined(__ANDROID__)
33061da546Spatrick #include <spawn.h>
34061da546Spatrick #endif
35061da546Spatrick #include <sys/syscall.h>
36061da546Spatrick #include <sys/wait.h>
37061da546Spatrick #endif
38061da546Spatrick 
39061da546Spatrick #if defined(__FreeBSD__)
40061da546Spatrick #include <pthread_np.h>
41061da546Spatrick #endif
42061da546Spatrick 
43061da546Spatrick #if defined(__NetBSD__)
44061da546Spatrick #include <lwp.h>
45061da546Spatrick #endif
46061da546Spatrick 
47061da546Spatrick #include <csignal>
48061da546Spatrick 
49061da546Spatrick #include "lldb/Host/FileAction.h"
50061da546Spatrick #include "lldb/Host/FileSystem.h"
51061da546Spatrick #include "lldb/Host/Host.h"
52061da546Spatrick #include "lldb/Host/HostInfo.h"
53061da546Spatrick #include "lldb/Host/HostProcess.h"
54061da546Spatrick #include "lldb/Host/MonitoringProcessLauncher.h"
55061da546Spatrick #include "lldb/Host/ProcessLaunchInfo.h"
56061da546Spatrick #include "lldb/Host/ProcessLauncher.h"
57061da546Spatrick #include "lldb/Host/ThreadLauncher.h"
58061da546Spatrick #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
59061da546Spatrick #include "lldb/Utility/FileSpec.h"
60*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
61061da546Spatrick #include "lldb/Utility/Log.h"
62061da546Spatrick #include "lldb/Utility/Predicate.h"
63061da546Spatrick #include "lldb/Utility/Status.h"
64061da546Spatrick #include "lldb/lldb-private-forward.h"
65061da546Spatrick #include "llvm/ADT/SmallString.h"
66061da546Spatrick #include "llvm/Support/Errno.h"
67061da546Spatrick #include "llvm/Support/FileSystem.h"
68061da546Spatrick 
69061da546Spatrick #if defined(_WIN32)
70061da546Spatrick #include "lldb/Host/windows/ConnectionGenericFileWindows.h"
71061da546Spatrick #include "lldb/Host/windows/ProcessLauncherWindows.h"
72061da546Spatrick #else
73061da546Spatrick #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
74061da546Spatrick #endif
75061da546Spatrick 
76061da546Spatrick #if defined(__APPLE__)
77061da546Spatrick #ifndef _POSIX_SPAWN_DISABLE_ASLR
78061da546Spatrick #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
79061da546Spatrick #endif
80061da546Spatrick 
81061da546Spatrick extern "C" {
82061da546Spatrick int __pthread_chdir(const char *path);
83061da546Spatrick int __pthread_fchdir(int fildes);
84061da546Spatrick }
85061da546Spatrick 
86061da546Spatrick #endif
87061da546Spatrick 
88061da546Spatrick using namespace lldb;
89061da546Spatrick using namespace lldb_private;
90061da546Spatrick 
91*f6aab3d8Srobert #if !defined(__APPLE__)
SystemLog(llvm::StringRef message)92*f6aab3d8Srobert void Host::SystemLog(llvm::StringRef message) { llvm::errs() << message; }
93*f6aab3d8Srobert #endif
94061da546Spatrick 
95*f6aab3d8Srobert #if !defined(__APPLE__) && !defined(_WIN32)
96*f6aab3d8Srobert static thread_result_t
97*f6aab3d8Srobert MonitorChildProcessThreadFunction(::pid_t pid,
98*f6aab3d8Srobert                                   Host::MonitorChildProcessCallback callback);
99061da546Spatrick 
StartMonitoringChildProcess(const Host::MonitorChildProcessCallback & callback,lldb::pid_t pid)100061da546Spatrick llvm::Expected<HostThread> Host::StartMonitoringChildProcess(
101*f6aab3d8Srobert     const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid) {
102061da546Spatrick   char thread_name[256];
103061da546Spatrick   ::snprintf(thread_name, sizeof(thread_name),
104061da546Spatrick              "<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
105*f6aab3d8Srobert   assert(pid <= UINT32_MAX);
106*f6aab3d8Srobert   return ThreadLauncher::LaunchThread(thread_name, [pid, callback] {
107*f6aab3d8Srobert     return MonitorChildProcessThreadFunction(pid, callback);
108*f6aab3d8Srobert   });
109061da546Spatrick }
110061da546Spatrick 
111061da546Spatrick #ifndef __linux__
112061da546Spatrick // Scoped class that will disable thread canceling when it is constructed, and
113061da546Spatrick // exception safely restore the previous value it when it goes out of scope.
114061da546Spatrick class ScopedPThreadCancelDisabler {
115061da546Spatrick public:
ScopedPThreadCancelDisabler()116061da546Spatrick   ScopedPThreadCancelDisabler() {
117061da546Spatrick     // Disable the ability for this thread to be cancelled
118061da546Spatrick     int err = ::pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &m_old_state);
119061da546Spatrick     if (err != 0)
120061da546Spatrick       m_old_state = -1;
121061da546Spatrick   }
122061da546Spatrick 
~ScopedPThreadCancelDisabler()123061da546Spatrick   ~ScopedPThreadCancelDisabler() {
124061da546Spatrick     // Restore the ability for this thread to be cancelled to what it
125061da546Spatrick     // previously was.
126061da546Spatrick     if (m_old_state != -1)
127061da546Spatrick       ::pthread_setcancelstate(m_old_state, 0);
128061da546Spatrick   }
129061da546Spatrick 
130061da546Spatrick private:
131061da546Spatrick   int m_old_state; // Save the old cancelability state.
132061da546Spatrick };
133061da546Spatrick #endif // __linux__
134061da546Spatrick 
135061da546Spatrick #ifdef __linux__
136061da546Spatrick #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
137061da546Spatrick static __thread volatile sig_atomic_t g_usr1_called;
138061da546Spatrick #else
139061da546Spatrick static thread_local volatile sig_atomic_t g_usr1_called;
140061da546Spatrick #endif
141061da546Spatrick 
SigUsr1Handler(int)142061da546Spatrick static void SigUsr1Handler(int) { g_usr1_called = 1; }
143061da546Spatrick #endif // __linux__
144061da546Spatrick 
CheckForMonitorCancellation()145061da546Spatrick static bool CheckForMonitorCancellation() {
146061da546Spatrick #ifdef __linux__
147061da546Spatrick   if (g_usr1_called) {
148061da546Spatrick     g_usr1_called = 0;
149061da546Spatrick     return true;
150061da546Spatrick   }
151061da546Spatrick #else
152061da546Spatrick   ::pthread_testcancel();
153061da546Spatrick #endif
154061da546Spatrick   return false;
155061da546Spatrick }
156061da546Spatrick 
157*f6aab3d8Srobert static thread_result_t
MonitorChildProcessThreadFunction(::pid_t pid,Host::MonitorChildProcessCallback callback)158*f6aab3d8Srobert MonitorChildProcessThreadFunction(::pid_t pid,
159*f6aab3d8Srobert                                   Host::MonitorChildProcessCallback callback) {
160*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Process);
161*f6aab3d8Srobert   LLDB_LOG(log, "pid = {0}", pid);
162061da546Spatrick 
163061da546Spatrick   int status = -1;
164061da546Spatrick 
165061da546Spatrick #ifdef __linux__
166061da546Spatrick   // This signal is only used to interrupt the thread from waitpid
167061da546Spatrick   struct sigaction sigUsr1Action;
168061da546Spatrick   memset(&sigUsr1Action, 0, sizeof(sigUsr1Action));
169061da546Spatrick   sigUsr1Action.sa_handler = SigUsr1Handler;
170061da546Spatrick   ::sigaction(SIGUSR1, &sigUsr1Action, nullptr);
171061da546Spatrick #endif // __linux__
172061da546Spatrick 
173*f6aab3d8Srobert   while (true) {
174*f6aab3d8Srobert     log = GetLog(LLDBLog::Process);
175*f6aab3d8Srobert     LLDB_LOG(log, "::waitpid({0}, &status, 0)...", pid);
176061da546Spatrick 
177061da546Spatrick     if (CheckForMonitorCancellation())
178*f6aab3d8Srobert       return nullptr;
179061da546Spatrick 
180*f6aab3d8Srobert     const ::pid_t wait_pid = ::waitpid(pid, &status, 0);
181*f6aab3d8Srobert 
182*f6aab3d8Srobert     LLDB_LOG(log, "::waitpid({0}, &status, 0) => pid = {1}, status = {2:x}", pid,
183*f6aab3d8Srobert              wait_pid, status);
184061da546Spatrick 
185061da546Spatrick     if (CheckForMonitorCancellation())
186*f6aab3d8Srobert       return nullptr;
187061da546Spatrick 
188*f6aab3d8Srobert     if (wait_pid != -1)
189061da546Spatrick       break;
190*f6aab3d8Srobert     if (errno != EINTR) {
191*f6aab3d8Srobert       LLDB_LOG(log, "pid = {0}, thread exiting because waitpid failed ({1})...",
192*f6aab3d8Srobert                pid, llvm::sys::StrError());
193*f6aab3d8Srobert       return nullptr;
194061da546Spatrick     }
195*f6aab3d8Srobert   }
196*f6aab3d8Srobert 
197061da546Spatrick   int signal = 0;
198061da546Spatrick   int exit_status = 0;
199*f6aab3d8Srobert   if (WIFEXITED(status)) {
200061da546Spatrick     exit_status = WEXITSTATUS(status);
201061da546Spatrick   } else if (WIFSIGNALED(status)) {
202061da546Spatrick     signal = WTERMSIG(status);
203061da546Spatrick     exit_status = -1;
204061da546Spatrick   } else {
205*f6aab3d8Srobert     llvm_unreachable("Unknown status");
206061da546Spatrick   }
207061da546Spatrick 
208061da546Spatrick   // Scope for pthread_cancel_disabler
209061da546Spatrick   {
210061da546Spatrick #ifndef __linux__
211061da546Spatrick     ScopedPThreadCancelDisabler pthread_cancel_disabler;
212061da546Spatrick #endif
213061da546Spatrick 
214061da546Spatrick     if (callback)
215*f6aab3d8Srobert       callback(pid, signal, exit_status);
216061da546Spatrick   }
217061da546Spatrick 
218*f6aab3d8Srobert   LLDB_LOG(GetLog(LLDBLog::Process), "pid = {0} thread exiting...", pid);
219061da546Spatrick   return nullptr;
220061da546Spatrick }
221061da546Spatrick 
222061da546Spatrick #endif // #if !defined (__APPLE__) && !defined (_WIN32)
223061da546Spatrick 
GetCurrentProcessID()224061da546Spatrick lldb::pid_t Host::GetCurrentProcessID() { return ::getpid(); }
225061da546Spatrick 
226061da546Spatrick #ifndef _WIN32
227061da546Spatrick 
GetCurrentThread()228061da546Spatrick lldb::thread_t Host::GetCurrentThread() {
229061da546Spatrick   return lldb::thread_t(pthread_self());
230061da546Spatrick }
231061da546Spatrick 
GetSignalAsCString(int signo)232061da546Spatrick const char *Host::GetSignalAsCString(int signo) {
233061da546Spatrick   switch (signo) {
234061da546Spatrick   case SIGHUP:
235061da546Spatrick     return "SIGHUP"; // 1    hangup
236061da546Spatrick   case SIGINT:
237061da546Spatrick     return "SIGINT"; // 2    interrupt
238061da546Spatrick   case SIGQUIT:
239061da546Spatrick     return "SIGQUIT"; // 3    quit
240061da546Spatrick   case SIGILL:
241061da546Spatrick     return "SIGILL"; // 4    illegal instruction (not reset when caught)
242061da546Spatrick   case SIGTRAP:
243061da546Spatrick     return "SIGTRAP"; // 5    trace trap (not reset when caught)
244061da546Spatrick   case SIGABRT:
245061da546Spatrick     return "SIGABRT"; // 6    abort()
246061da546Spatrick #if defined(SIGPOLL)
247061da546Spatrick #if !defined(SIGIO) || (SIGPOLL != SIGIO)
248061da546Spatrick   // Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to
249061da546Spatrick   // fail with 'multiple define cases with same value'
250061da546Spatrick   case SIGPOLL:
251061da546Spatrick     return "SIGPOLL"; // 7    pollable event ([XSR] generated, not supported)
252061da546Spatrick #endif
253061da546Spatrick #endif
254061da546Spatrick #if defined(SIGEMT)
255061da546Spatrick   case SIGEMT:
256061da546Spatrick     return "SIGEMT"; // 7    EMT instruction
257061da546Spatrick #endif
258061da546Spatrick   case SIGFPE:
259061da546Spatrick     return "SIGFPE"; // 8    floating point exception
260061da546Spatrick   case SIGKILL:
261061da546Spatrick     return "SIGKILL"; // 9    kill (cannot be caught or ignored)
262061da546Spatrick   case SIGBUS:
263061da546Spatrick     return "SIGBUS"; // 10    bus error
264061da546Spatrick   case SIGSEGV:
265061da546Spatrick     return "SIGSEGV"; // 11    segmentation violation
266061da546Spatrick   case SIGSYS:
267061da546Spatrick     return "SIGSYS"; // 12    bad argument to system call
268061da546Spatrick   case SIGPIPE:
269061da546Spatrick     return "SIGPIPE"; // 13    write on a pipe with no one to read it
270061da546Spatrick   case SIGALRM:
271061da546Spatrick     return "SIGALRM"; // 14    alarm clock
272061da546Spatrick   case SIGTERM:
273061da546Spatrick     return "SIGTERM"; // 15    software termination signal from kill
274061da546Spatrick   case SIGURG:
275061da546Spatrick     return "SIGURG"; // 16    urgent condition on IO channel
276061da546Spatrick   case SIGSTOP:
277061da546Spatrick     return "SIGSTOP"; // 17    sendable stop signal not from tty
278061da546Spatrick   case SIGTSTP:
279061da546Spatrick     return "SIGTSTP"; // 18    stop signal from tty
280061da546Spatrick   case SIGCONT:
281061da546Spatrick     return "SIGCONT"; // 19    continue a stopped process
282061da546Spatrick   case SIGCHLD:
283061da546Spatrick     return "SIGCHLD"; // 20    to parent on child stop or exit
284061da546Spatrick   case SIGTTIN:
285061da546Spatrick     return "SIGTTIN"; // 21    to readers pgrp upon background tty read
286061da546Spatrick   case SIGTTOU:
287061da546Spatrick     return "SIGTTOU"; // 22    like TTIN for output if (tp->t_local&LTOSTOP)
288061da546Spatrick #if defined(SIGIO)
289061da546Spatrick   case SIGIO:
290061da546Spatrick     return "SIGIO"; // 23    input/output possible signal
291061da546Spatrick #endif
292061da546Spatrick   case SIGXCPU:
293061da546Spatrick     return "SIGXCPU"; // 24    exceeded CPU time limit
294061da546Spatrick   case SIGXFSZ:
295061da546Spatrick     return "SIGXFSZ"; // 25    exceeded file size limit
296061da546Spatrick   case SIGVTALRM:
297061da546Spatrick     return "SIGVTALRM"; // 26    virtual time alarm
298061da546Spatrick   case SIGPROF:
299061da546Spatrick     return "SIGPROF"; // 27    profiling time alarm
300061da546Spatrick #if defined(SIGWINCH)
301061da546Spatrick   case SIGWINCH:
302061da546Spatrick     return "SIGWINCH"; // 28    window size changes
303061da546Spatrick #endif
304061da546Spatrick #if defined(SIGINFO)
305061da546Spatrick   case SIGINFO:
306061da546Spatrick     return "SIGINFO"; // 29    information request
307061da546Spatrick #endif
308061da546Spatrick   case SIGUSR1:
309061da546Spatrick     return "SIGUSR1"; // 30    user defined signal 1
310061da546Spatrick   case SIGUSR2:
311061da546Spatrick     return "SIGUSR2"; // 31    user defined signal 2
312061da546Spatrick   default:
313061da546Spatrick     break;
314061da546Spatrick   }
315061da546Spatrick   return nullptr;
316061da546Spatrick }
317061da546Spatrick 
318061da546Spatrick #endif
319061da546Spatrick 
320061da546Spatrick #if !defined(__APPLE__) // see Host.mm
321061da546Spatrick 
GetBundleDirectory(const FileSpec & file,FileSpec & bundle)322061da546Spatrick bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle) {
323061da546Spatrick   bundle.Clear();
324061da546Spatrick   return false;
325061da546Spatrick }
326061da546Spatrick 
ResolveExecutableInBundle(FileSpec & file)327061da546Spatrick bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; }
328061da546Spatrick #endif
329061da546Spatrick 
330061da546Spatrick #ifndef _WIN32
331061da546Spatrick 
GetModuleFileSpecForHostAddress(const void * host_addr)332061da546Spatrick FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
333061da546Spatrick   FileSpec module_filespec;
334061da546Spatrick #if !defined(__ANDROID__)
335061da546Spatrick   Dl_info info;
336061da546Spatrick   if (::dladdr(host_addr, &info)) {
337061da546Spatrick     if (info.dli_fname) {
338061da546Spatrick       module_filespec.SetFile(info.dli_fname, FileSpec::Style::native);
339061da546Spatrick       FileSystem::Instance().Resolve(module_filespec);
340061da546Spatrick     }
341061da546Spatrick   }
342061da546Spatrick #endif
343061da546Spatrick   return module_filespec;
344061da546Spatrick }
345061da546Spatrick 
346061da546Spatrick #endif
347061da546Spatrick 
348061da546Spatrick #if !defined(__linux__)
FindProcessThreads(const lldb::pid_t pid,TidMap & tids_to_attach)349061da546Spatrick bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) {
350061da546Spatrick   return false;
351061da546Spatrick }
352061da546Spatrick #endif
353061da546Spatrick 
354061da546Spatrick struct ShellInfo {
ShellInfoShellInfo355be691f3bSpatrick   ShellInfo() : process_reaped(false) {}
356061da546Spatrick 
357061da546Spatrick   lldb_private::Predicate<bool> process_reaped;
358be691f3bSpatrick   lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
359be691f3bSpatrick   int signo = -1;
360be691f3bSpatrick   int status = -1;
361061da546Spatrick };
362061da546Spatrick 
363*f6aab3d8Srobert static void
MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info,lldb::pid_t pid,int signo,int status)364061da546Spatrick MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid,
365061da546Spatrick                     int signo,  // Zero for no signal
366061da546Spatrick                     int status) // Exit value of process if signal is zero
367061da546Spatrick {
368061da546Spatrick   shell_info->pid = pid;
369061da546Spatrick   shell_info->signo = signo;
370061da546Spatrick   shell_info->status = status;
371061da546Spatrick   // Let the thread running Host::RunShellCommand() know that the process
372061da546Spatrick   // exited and that ShellInfo has been filled in by broadcasting to it
373061da546Spatrick   shell_info->process_reaped.SetValue(true, eBroadcastAlways);
374061da546Spatrick }
375061da546Spatrick 
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)376be691f3bSpatrick Status Host::RunShellCommand(llvm::StringRef command,
377be691f3bSpatrick                              const FileSpec &working_dir, int *status_ptr,
378be691f3bSpatrick                              int *signo_ptr, std::string *command_output_ptr,
379061da546Spatrick                              const Timeout<std::micro> &timeout,
380be691f3bSpatrick                              bool run_in_shell, bool hide_stderr) {
381be691f3bSpatrick   return RunShellCommand(llvm::StringRef(), Args(command), working_dir,
382be691f3bSpatrick                          status_ptr, signo_ptr, command_output_ptr, timeout,
383be691f3bSpatrick                          run_in_shell, hide_stderr);
384be691f3bSpatrick }
385be691f3bSpatrick 
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)386be691f3bSpatrick Status Host::RunShellCommand(llvm::StringRef shell_path,
387be691f3bSpatrick                              llvm::StringRef command,
388be691f3bSpatrick                              const FileSpec &working_dir, int *status_ptr,
389be691f3bSpatrick                              int *signo_ptr, std::string *command_output_ptr,
390be691f3bSpatrick                              const Timeout<std::micro> &timeout,
391be691f3bSpatrick                              bool run_in_shell, bool hide_stderr) {
392be691f3bSpatrick   return RunShellCommand(shell_path, Args(command), working_dir, status_ptr,
393be691f3bSpatrick                          signo_ptr, command_output_ptr, timeout, run_in_shell,
394061da546Spatrick                          hide_stderr);
395061da546Spatrick }
396061da546Spatrick 
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)397061da546Spatrick Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
398061da546Spatrick                              int *status_ptr, int *signo_ptr,
399061da546Spatrick                              std::string *command_output_ptr,
400061da546Spatrick                              const Timeout<std::micro> &timeout,
401be691f3bSpatrick                              bool run_in_shell, bool hide_stderr) {
402be691f3bSpatrick   return RunShellCommand(llvm::StringRef(), args, working_dir, status_ptr,
403be691f3bSpatrick                          signo_ptr, command_output_ptr, timeout, run_in_shell,
404be691f3bSpatrick                          hide_stderr);
405be691f3bSpatrick }
406be691f3bSpatrick 
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)407be691f3bSpatrick Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
408be691f3bSpatrick                              const FileSpec &working_dir, int *status_ptr,
409be691f3bSpatrick                              int *signo_ptr, std::string *command_output_ptr,
410be691f3bSpatrick                              const Timeout<std::micro> &timeout,
411be691f3bSpatrick                              bool run_in_shell, bool hide_stderr) {
412061da546Spatrick   Status error;
413061da546Spatrick   ProcessLaunchInfo launch_info;
414061da546Spatrick   launch_info.SetArchitecture(HostInfo::GetArchitecture());
415be691f3bSpatrick   if (run_in_shell) {
416061da546Spatrick     // Run the command in a shell
417be691f3bSpatrick     FileSpec shell = HostInfo::GetDefaultShell();
418be691f3bSpatrick     if (!shell_path.empty())
419be691f3bSpatrick       shell.SetPath(shell_path);
420be691f3bSpatrick 
421be691f3bSpatrick     launch_info.SetShell(shell);
422061da546Spatrick     launch_info.GetArguments().AppendArguments(args);
423061da546Spatrick     const bool will_debug = false;
424061da546Spatrick     const bool first_arg_is_full_shell_command = false;
425061da546Spatrick     launch_info.ConvertArgumentsForLaunchingInShell(
426be691f3bSpatrick         error, will_debug, first_arg_is_full_shell_command, 0);
427061da546Spatrick   } else {
428061da546Spatrick     // No shell, just run it
429061da546Spatrick     const bool first_arg_is_executable = true;
430061da546Spatrick     launch_info.SetArguments(args, first_arg_is_executable);
431061da546Spatrick   }
432061da546Spatrick 
433dda28197Spatrick   launch_info.GetEnvironment() = Host::GetEnvironment();
434dda28197Spatrick 
435061da546Spatrick   if (working_dir)
436061da546Spatrick     launch_info.SetWorkingDirectory(working_dir);
437061da546Spatrick   llvm::SmallString<64> output_file_path;
438061da546Spatrick 
439061da546Spatrick   if (command_output_ptr) {
440061da546Spatrick     // Create a temporary file to get the stdout/stderr and redirect the output
441061da546Spatrick     // of the command into this file. We will later read this file if all goes
442061da546Spatrick     // well and fill the data into "command_output_ptr"
443061da546Spatrick     if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
444061da546Spatrick       tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%");
445061da546Spatrick       llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(),
446061da546Spatrick                                       output_file_path);
447061da546Spatrick     } else {
448061da546Spatrick       llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "",
449061da546Spatrick                                          output_file_path);
450061da546Spatrick     }
451061da546Spatrick   }
452061da546Spatrick 
453dda28197Spatrick   FileSpec output_file_spec(output_file_path.str());
454061da546Spatrick   // Set up file descriptors.
455061da546Spatrick   launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false);
456061da546Spatrick   if (output_file_spec)
457061da546Spatrick     launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false,
458061da546Spatrick                                      true);
459061da546Spatrick   else
460061da546Spatrick     launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
461061da546Spatrick 
462061da546Spatrick   if (output_file_spec && !hide_stderr)
463061da546Spatrick     launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);
464061da546Spatrick   else
465061da546Spatrick     launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true);
466061da546Spatrick 
467061da546Spatrick   std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo());
468061da546Spatrick   launch_info.SetMonitorProcessCallback(
469061da546Spatrick       std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1,
470*f6aab3d8Srobert                 std::placeholders::_2, std::placeholders::_3));
471061da546Spatrick 
472061da546Spatrick   error = LaunchProcess(launch_info);
473061da546Spatrick   const lldb::pid_t pid = launch_info.GetProcessID();
474061da546Spatrick 
475061da546Spatrick   if (error.Success() && pid == LLDB_INVALID_PROCESS_ID)
476061da546Spatrick     error.SetErrorString("failed to get process ID");
477061da546Spatrick 
478061da546Spatrick   if (error.Success()) {
479061da546Spatrick     if (!shell_info_sp->process_reaped.WaitForValueEqualTo(true, timeout)) {
480061da546Spatrick       error.SetErrorString("timed out waiting for shell command to complete");
481061da546Spatrick 
482061da546Spatrick       // Kill the process since it didn't complete within the timeout specified
483061da546Spatrick       Kill(pid, SIGKILL);
484061da546Spatrick       // Wait for the monitor callback to get the message
485061da546Spatrick       shell_info_sp->process_reaped.WaitForValueEqualTo(
486061da546Spatrick           true, std::chrono::seconds(1));
487061da546Spatrick     } else {
488061da546Spatrick       if (status_ptr)
489061da546Spatrick         *status_ptr = shell_info_sp->status;
490061da546Spatrick 
491061da546Spatrick       if (signo_ptr)
492061da546Spatrick         *signo_ptr = shell_info_sp->signo;
493061da546Spatrick 
494061da546Spatrick       if (command_output_ptr) {
495061da546Spatrick         command_output_ptr->clear();
496061da546Spatrick         uint64_t file_size =
497061da546Spatrick             FileSystem::Instance().GetByteSize(output_file_spec);
498061da546Spatrick         if (file_size > 0) {
499061da546Spatrick           if (file_size > command_output_ptr->max_size()) {
500061da546Spatrick             error.SetErrorStringWithFormat(
501061da546Spatrick                 "shell command output is too large to fit into a std::string");
502061da546Spatrick           } else {
503*f6aab3d8Srobert             WritableDataBufferSP Buffer =
504*f6aab3d8Srobert                 FileSystem::Instance().CreateWritableDataBuffer(
505*f6aab3d8Srobert                     output_file_spec);
506061da546Spatrick             if (error.Success())
507*f6aab3d8Srobert               command_output_ptr->assign(
508*f6aab3d8Srobert                   reinterpret_cast<char *>(Buffer->GetBytes()),
509061da546Spatrick                   Buffer->GetByteSize());
510061da546Spatrick           }
511061da546Spatrick         }
512061da546Spatrick       }
513061da546Spatrick     }
514061da546Spatrick   }
515061da546Spatrick 
516061da546Spatrick   llvm::sys::fs::remove(output_file_spec.GetPath());
517061da546Spatrick   return error;
518061da546Spatrick }
519061da546Spatrick 
520061da546Spatrick // The functions below implement process launching for non-Apple-based
521061da546Spatrick // platforms
522061da546Spatrick #if !defined(__APPLE__)
LaunchProcess(ProcessLaunchInfo & launch_info)523061da546Spatrick Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
524061da546Spatrick   std::unique_ptr<ProcessLauncher> delegate_launcher;
525061da546Spatrick #if defined(_WIN32)
526061da546Spatrick   delegate_launcher.reset(new ProcessLauncherWindows());
527061da546Spatrick #else
528061da546Spatrick   delegate_launcher.reset(new ProcessLauncherPosixFork());
529061da546Spatrick #endif
530061da546Spatrick   MonitoringProcessLauncher launcher(std::move(delegate_launcher));
531061da546Spatrick 
532061da546Spatrick   Status error;
533061da546Spatrick   HostProcess process = launcher.LaunchProcess(launch_info, error);
534061da546Spatrick 
535061da546Spatrick   // TODO(zturner): It would be better if the entire HostProcess were returned
536061da546Spatrick   // instead of writing it into this structure.
537061da546Spatrick   launch_info.SetProcessID(process.GetProcessId());
538061da546Spatrick 
539061da546Spatrick   return error;
540061da546Spatrick }
541061da546Spatrick #endif // !defined(__APPLE__)
542061da546Spatrick 
543061da546Spatrick #ifndef _WIN32
Kill(lldb::pid_t pid,int signo)544061da546Spatrick void Host::Kill(lldb::pid_t pid, int signo) { ::kill(pid, signo); }
545061da546Spatrick 
546061da546Spatrick #endif
547061da546Spatrick 
548061da546Spatrick #if !defined(__APPLE__)
OpenFileInExternalEditor(const FileSpec & file_spec,uint32_t line_no)549061da546Spatrick bool Host::OpenFileInExternalEditor(const FileSpec &file_spec,
550061da546Spatrick                                     uint32_t line_no) {
551061da546Spatrick   return false;
552061da546Spatrick }
553061da546Spatrick 
IsInteractiveGraphicSession()554*f6aab3d8Srobert bool Host::IsInteractiveGraphicSession() { return false; }
555061da546Spatrick #endif
556061da546Spatrick 
CreateDefaultConnection(llvm::StringRef url)557061da546Spatrick std::unique_ptr<Connection> Host::CreateDefaultConnection(llvm::StringRef url) {
558061da546Spatrick #if defined(_WIN32)
559061da546Spatrick   if (url.startswith("file://"))
560061da546Spatrick     return std::unique_ptr<Connection>(new ConnectionGenericFile());
561061da546Spatrick #endif
562061da546Spatrick   return std::unique_ptr<Connection>(new ConnectionFileDescriptor());
563061da546Spatrick }
564061da546Spatrick 
565061da546Spatrick #if defined(LLVM_ON_UNIX)
Decode(int wstatus)566061da546Spatrick WaitStatus WaitStatus::Decode(int wstatus) {
567061da546Spatrick   if (WIFEXITED(wstatus))
568061da546Spatrick     return {Exit, uint8_t(WEXITSTATUS(wstatus))};
569061da546Spatrick   else if (WIFSIGNALED(wstatus))
570061da546Spatrick     return {Signal, uint8_t(WTERMSIG(wstatus))};
571061da546Spatrick   else if (WIFSTOPPED(wstatus))
572061da546Spatrick     return {Stop, uint8_t(WSTOPSIG(wstatus))};
573061da546Spatrick   llvm_unreachable("Unknown wait status");
574061da546Spatrick }
575061da546Spatrick #endif
576061da546Spatrick 
format(const WaitStatus & WS,raw_ostream & OS,StringRef Options)577061da546Spatrick void llvm::format_provider<WaitStatus>::format(const WaitStatus &WS,
578061da546Spatrick                                                raw_ostream &OS,
579061da546Spatrick                                                StringRef Options) {
580061da546Spatrick   if (Options == "g") {
581061da546Spatrick     char type;
582061da546Spatrick     switch (WS.type) {
583061da546Spatrick     case WaitStatus::Exit:
584061da546Spatrick       type = 'W';
585061da546Spatrick       break;
586061da546Spatrick     case WaitStatus::Signal:
587061da546Spatrick       type = 'X';
588061da546Spatrick       break;
589061da546Spatrick     case WaitStatus::Stop:
590061da546Spatrick       type = 'S';
591061da546Spatrick       break;
592061da546Spatrick     }
593061da546Spatrick     OS << formatv("{0}{1:x-2}", type, WS.status);
594061da546Spatrick     return;
595061da546Spatrick   }
596061da546Spatrick 
597061da546Spatrick   assert(Options.empty());
598061da546Spatrick   const char *desc;
599061da546Spatrick   switch(WS.type) {
600061da546Spatrick   case WaitStatus::Exit:
601061da546Spatrick     desc = "Exited with status";
602061da546Spatrick     break;
603061da546Spatrick   case WaitStatus::Signal:
604061da546Spatrick     desc = "Killed by signal";
605061da546Spatrick     break;
606061da546Spatrick   case WaitStatus::Stop:
607061da546Spatrick     desc = "Stopped by signal";
608061da546Spatrick     break;
609061da546Spatrick   }
610061da546Spatrick   OS << desc << " " << int(WS.status);
611061da546Spatrick }
612dda28197Spatrick 
FindProcesses(const ProcessInstanceInfoMatch & match_info,ProcessInstanceInfoList & process_infos)613dda28197Spatrick uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
614dda28197Spatrick                              ProcessInstanceInfoList &process_infos) {
615*f6aab3d8Srobert   return FindProcessesImpl(match_info, process_infos);
616dda28197Spatrick }
617dda28197Spatrick 
618*f6aab3d8Srobert char SystemLogHandler::ID;
619dda28197Spatrick 
SystemLogHandler()620*f6aab3d8Srobert SystemLogHandler::SystemLogHandler() {}
621dda28197Spatrick 
Emit(llvm::StringRef message)622*f6aab3d8Srobert void SystemLogHandler::Emit(llvm::StringRef message) {
623*f6aab3d8Srobert   Host::SystemLog(message);
624dda28197Spatrick }
625