Coverage Report

Created: 2022-01-18 06:27

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