reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
//===-- Host.h --------------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_HOST_HOST_H
#define LLDB_HOST_HOST_H

#include "lldb/Host/File.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Utility/Environment.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-private.h"
#include <cerrno>
#include <map>
#include <stdarg.h>
#include <string>
#include <type_traits>

namespace lldb_private {

class FileAction;
class ProcessLaunchInfo;
class ProcessInstanceInfo;
class ProcessInstanceInfoList;
class ProcessInstanceInfoMatch;

// Exit Type for inferior processes
struct WaitStatus {
  enum Type : uint8_t {
    Exit,   // The status represents the return code from normal
            // program exit (i.e. WIFEXITED() was true)
    Signal, // The status represents the signal number that caused
            // the program to exit (i.e. WIFSIGNALED() was true)
    Stop,   // The status represents the signal number that caused the
            // program to stop (i.e. WIFSTOPPED() was true)
  };

  Type type;
  uint8_t status;

  WaitStatus(Type type, uint8_t status) : type(type), status(status) {}

  static WaitStatus Decode(int wstatus);
};

inline bool operator==(WaitStatus a, WaitStatus b) {
  return a.type == b.type && a.status == b.status;
}

inline bool operator!=(WaitStatus a, WaitStatus b) { return !(a == b); }

/// \class Host Host.h "lldb/Host/Host.h"
/// A class that provides host computer information.
///
/// Host is a class that answers information about the host operating system.
class Host {
public:
  typedef std::function<bool(
      lldb::pid_t pid, bool exited,
      int signal,  // Zero for no signal
      int status)> // Exit value of process if signal is zero
      MonitorChildProcessCallback;

  /// Start monitoring a child process.
  ///
  /// Allows easy monitoring of child processes. \a callback will be called
  /// when the child process exits or if it gets a signal. The callback will
  /// only be called with signals if \a monitor_signals is \b true. \a
  /// callback will usually be called from another thread so the callback
  /// function must be thread safe.
  ///
  /// When the callback gets called, the return value indicates if monitoring
  /// should stop. If \b true is returned from \a callback the information
  /// will be removed. If \b false is returned then monitoring will continue.
  /// If the child process exits, the monitoring will automatically stop after
  /// the callback returned regardless of the callback return value.
  ///
  /// \param[in] callback
  ///     A function callback to call when a child receives a signal
  ///     (if \a monitor_signals is true) or a child exits.
  ///
  /// \param[in] pid
  ///     The process ID of a child process to monitor, -1 for all
  ///     processes.
  ///
  /// \param[in] monitor_signals
  ///     If \b true the callback will get called when the child
  ///     process gets a signal. If \b false, the callback will only
  ///     get called if the child process exits.
  ///
  /// \return
  ///     A thread handle that can be used to cancel the thread that
  ///     was spawned to monitor \a pid.
  ///
  /// \see static void Host::StopMonitoringChildProcess (uint32_t)
  static llvm::Expected<HostThread>
  StartMonitoringChildProcess(const MonitorChildProcessCallback &callback,
                              lldb::pid_t pid, bool monitor_signals);

  enum SystemLogType { eSystemLogWarning, eSystemLogError };

  static void SystemLog(SystemLogType type, const char *format, ...)
      __attribute__((format(printf, 2, 3)));

  static void SystemLog(SystemLogType type, const char *format, va_list args);

  /// Get the process ID for the calling process.
  ///
  /// \return
  ///     The process ID for the current process.
  static lldb::pid_t GetCurrentProcessID();

  static void Kill(lldb::pid_t pid, int signo);

  /// Get the thread token (the one returned by ThreadCreate when the thread
  /// was created) for the calling thread in the current process.
  ///
  /// \return
  ///     The thread token for the calling thread in the current process.
  static lldb::thread_t GetCurrentThread();

  static const char *GetSignalAsCString(int signo);

  /// Given an address in the current process (the process that is running the
  /// LLDB code), return the name of the module that it comes from. This can
  /// be useful when you need to know the path to the shared library that your
  /// code is running in for loading resources that are relative to your
  /// binary.
  ///
  /// \param[in] host_addr
  ///     The pointer to some code in the current process.
  ///
  /// \return
  ///     \b A file spec with the module that contains \a host_addr,
  ///     which may be invalid if \a host_addr doesn't fall into
  ///     any valid module address range.
  static FileSpec GetModuleFileSpecForHostAddress(const void *host_addr);

  /// If you have an executable that is in a bundle and want to get back to
  /// the bundle directory from the path itself, this function will change a
  /// path to a file within a bundle to the bundle directory itself.
  ///
  /// \param[in] file
  ///     A file spec that might point to a file in a bundle.
  ///
  /// \param[out] bundle_directory
  ///     An object will be filled in with the bundle directory for
  ///     the bundle when \b true is returned. Otherwise \a file is
  ///     left untouched and \b false is returned.
  ///
  /// \return
  ///     \b true if \a file was resolved in \a bundle_directory,
  ///     \b false otherwise.
  static bool GetBundleDirectory(const FileSpec &file,
                                 FileSpec &bundle_directory);

  /// When executable files may live within a directory, where the directory
  /// represents an executable bundle (like the MacOSX app bundles), then
  /// locate the executable within the containing bundle.
  ///
  /// \param[in,out] file
  ///     A file spec that currently points to the bundle that will
  ///     be filled in with the executable path within the bundle
  ///     if \b true is returned. Otherwise \a file is left untouched.
  ///
  /// \return
  ///     \b true if \a file was resolved, \b false if this function
  ///     was not able to resolve the path.
  static bool ResolveExecutableInBundle(FileSpec &file);

  static uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info,
                                ProcessInstanceInfoList &proc_infos);

  typedef std::map<lldb::pid_t, bool> TidMap;
  typedef std::pair<lldb::pid_t, bool> TidPair;
  static bool FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach);

  static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info);

  /// Launch the process specified in launch_info. The monitoring callback in
  /// launch_info must be set, and it will be called when the process
  /// terminates.
  static Status LaunchProcess(ProcessLaunchInfo &launch_info);

  /// Perform expansion of the command-line for this launch info This can
  /// potentially involve wildcard expansion
  /// environment variable replacement, and whatever other
  /// argument magic the platform defines as part of its typical
  /// user experience
  static Status ShellExpandArguments(ProcessLaunchInfo &launch_info);

  /// Run a shell command.
  /// \arg command  shouldn't be NULL
  /// \arg working_dir Pass empty FileSpec to use the current working directory
  /// \arg status_ptr  Pass NULL if you don't want the process exit status
  /// \arg signo_ptr   Pass NULL if you don't want the signal that caused the
  ///                  process to exit
  /// \arg command_output  Pass NULL if you don't want the command output
  /// \arg hide_stderr if this is false, redirect stderr to stdout
  /// TODO: Convert this function to take a StringRef.
  static Status RunShellCommand(const char *command,
                                const FileSpec &working_dir, int *status_ptr,
                                int *signo_ptr, std::string *command_output,
                                const Timeout<std::micro> &timeout,
                                bool run_in_default_shell = true,
                                bool hide_stderr = false);

  /// Run a shell command.
  /// \arg working_dir Pass empty FileSpec to use the current working directory
  /// \arg status_ptr  Pass NULL if you don't want the process exit status
  /// \arg signo_ptr   Pass NULL if you don't want the signal that caused the
  ///                  process to exit
  /// \arg command_output  Pass NULL if you don't want the command output
  /// \arg hide_stderr if this is false, redirect stderr to stdout
  static Status RunShellCommand(const Args &args, const FileSpec &working_dir,
                                int *status_ptr, int *signo_ptr,
                                std::string *command_output,
                                const Timeout<std::micro> &timeout,
                                bool run_in_default_shell = true,
                                bool hide_stderr = false);

  static bool OpenFileInExternalEditor(const FileSpec &file_spec,
                                       uint32_t line_no);

  static Environment GetEnvironment();

  static std::unique_ptr<Connection>
  CreateDefaultConnection(llvm::StringRef url);
};

} // namespace lldb_private

namespace llvm {
template <> struct format_provider<lldb_private::WaitStatus> {
  /// Options = "" gives a human readable description of the status Options =
  /// "g" gives a gdb-remote protocol status (e.g., X09)
  static void format(const lldb_private::WaitStatus &WS, raw_ostream &OS,
                     llvm::StringRef Options);
};
} // namespace llvm

#endif // LLDB_HOST_HOST_H