1 //===-- Host.h --------------------------------------------------*- C++ -*-===// 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 #ifndef LLDB_HOST_HOST_H 10 #define LLDB_HOST_HOST_H 11 12 #include "lldb/Host/File.h" 13 #include "lldb/Host/HostThread.h" 14 #include "lldb/Utility/Environment.h" 15 #include "lldb/Utility/FileSpec.h" 16 #include "lldb/Utility/Log.h" 17 #include "lldb/Utility/Timeout.h" 18 #include "lldb/lldb-private-forward.h" 19 #include "lldb/lldb-private.h" 20 #include <cerrno> 21 #include <cstdarg> 22 #include <map> 23 #include <string> 24 #include <type_traits> 25 26 namespace lldb_private { 27 28 class FileAction; 29 class ProcessLaunchInfo; 30 class ProcessInstanceInfo; 31 class ProcessInstanceInfoMatch; 32 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList; 33 34 // Exit Type for inferior processes 35 struct WaitStatus { 36 enum Type : uint8_t { 37 Exit, // The status represents the return code from normal 38 // program exit (i.e. WIFEXITED() was true) 39 Signal, // The status represents the signal number that caused 40 // the program to exit (i.e. WIFSIGNALED() was true) 41 Stop, // The status represents the signal number that caused the 42 // program to stop (i.e. WIFSTOPPED() was true) 43 }; 44 45 Type type; 46 uint8_t status; 47 WaitStatusWaitStatus48 WaitStatus(Type type, uint8_t status) : type(type), status(status) {} 49 50 static WaitStatus Decode(int wstatus); 51 }; 52 53 inline bool operator==(WaitStatus a, WaitStatus b) { 54 return a.type == b.type && a.status == b.status; 55 } 56 57 inline bool operator!=(WaitStatus a, WaitStatus b) { return !(a == b); } 58 59 /// \class Host Host.h "lldb/Host/Host.h" 60 /// A class that provides host computer information. 61 /// 62 /// Host is a class that answers information about the host operating system. 63 class Host { 64 public: 65 typedef std::function<void(lldb::pid_t pid, 66 int signal, // Zero for no signal 67 int status)> // Exit value of process if signal is 68 // zero 69 MonitorChildProcessCallback; 70 71 /// Start monitoring a child process. 72 /// 73 /// Allows easy monitoring of child processes. \a callback will be called 74 /// when the child process exits or if it dies from a signal. 75 /// 76 /// \param[in] callback 77 /// A function callback to call when a child receives a signal 78 /// or exits. 79 /// 80 /// \param[in] pid 81 /// The process ID of a child process to monitor. 82 /// 83 /// \return 84 /// A thread handle that can be used to cancel the thread that 85 /// was spawned to monitor \a pid. 86 static llvm::Expected<HostThread> 87 StartMonitoringChildProcess(const MonitorChildProcessCallback &callback, 88 lldb::pid_t pid); 89 90 /// Emit the given message to the operating system log. 91 static void SystemLog(llvm::StringRef message); 92 93 /// Get the process ID for the calling process. 94 /// 95 /// \return 96 /// The process ID for the current process. 97 static lldb::pid_t GetCurrentProcessID(); 98 99 static void Kill(lldb::pid_t pid, int signo); 100 101 /// Get the thread token (the one returned by ThreadCreate when the thread 102 /// was created) for the calling thread in the current process. 103 /// 104 /// \return 105 /// The thread token for the calling thread in the current process. 106 static lldb::thread_t GetCurrentThread(); 107 108 static const char *GetSignalAsCString(int signo); 109 110 /// Given an address in the current process (the process that is running the 111 /// LLDB code), return the name of the module that it comes from. This can 112 /// be useful when you need to know the path to the shared library that your 113 /// code is running in for loading resources that are relative to your 114 /// binary. 115 /// 116 /// \param[in] host_addr 117 /// The pointer to some code in the current process. 118 /// 119 /// \return 120 /// \b A file spec with the module that contains \a host_addr, 121 /// which may be invalid if \a host_addr doesn't fall into 122 /// any valid module address range. 123 static FileSpec GetModuleFileSpecForHostAddress(const void *host_addr); 124 125 /// If you have an executable that is in a bundle and want to get back to 126 /// the bundle directory from the path itself, this function will change a 127 /// path to a file within a bundle to the bundle directory itself. 128 /// 129 /// \param[in] file 130 /// A file spec that might point to a file in a bundle. 131 /// 132 /// \param[out] bundle_directory 133 /// An object will be filled in with the bundle directory for 134 /// the bundle when \b true is returned. Otherwise \a file is 135 /// left untouched and \b false is returned. 136 /// 137 /// \return 138 /// \b true if \a file was resolved in \a bundle_directory, 139 /// \b false otherwise. 140 static bool GetBundleDirectory(const FileSpec &file, 141 FileSpec &bundle_directory); 142 143 /// When executable files may live within a directory, where the directory 144 /// represents an executable bundle (like the MacOSX app bundles), then 145 /// locate the executable within the containing bundle. 146 /// 147 /// \param[in,out] file 148 /// A file spec that currently points to the bundle that will 149 /// be filled in with the executable path within the bundle 150 /// if \b true is returned. Otherwise \a file is left untouched. 151 /// 152 /// \return 153 /// \b true if \a file was resolved, \b false if this function 154 /// was not able to resolve the path. 155 static bool ResolveExecutableInBundle(FileSpec &file); 156 157 static uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info, 158 ProcessInstanceInfoList &proc_infos); 159 160 typedef std::map<lldb::pid_t, bool> TidMap; 161 typedef std::pair<lldb::pid_t, bool> TidPair; 162 static bool FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach); 163 164 static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info); 165 166 /// Launch the process specified in launch_info. The monitoring callback in 167 /// launch_info must be set, and it will be called when the process 168 /// terminates. 169 static Status LaunchProcess(ProcessLaunchInfo &launch_info); 170 171 /// Perform expansion of the command-line for this launch info This can 172 /// potentially involve wildcard expansion 173 /// environment variable replacement, and whatever other 174 /// argument magic the platform defines as part of its typical 175 /// user experience 176 static Status ShellExpandArguments(ProcessLaunchInfo &launch_info); 177 178 /// Run a shell command. 179 /// \arg command shouldn't be empty 180 /// \arg working_dir Pass empty FileSpec to use the current working directory 181 /// \arg status_ptr Pass NULL if you don't want the process exit status 182 /// \arg signo_ptr Pass NULL if you don't want the signal that caused the 183 /// process to exit 184 /// \arg command_output Pass NULL if you don't want the command output 185 /// \arg hide_stderr if this is false, redirect stderr to stdout 186 static Status RunShellCommand(llvm::StringRef command, 187 const FileSpec &working_dir, int *status_ptr, 188 int *signo_ptr, std::string *command_output, 189 const Timeout<std::micro> &timeout, 190 bool run_in_shell = true, 191 bool hide_stderr = false); 192 193 /// Run a shell command. 194 /// \arg shell Pass an empty string if you want to use the default shell 195 /// interpreter \arg command \arg working_dir Pass empty FileSpec to use the 196 /// current working directory \arg status_ptr Pass NULL if you don't want 197 /// the process exit status \arg signo_ptr Pass NULL if you don't want the 198 /// signal that caused 199 /// the process to exit 200 /// \arg command_output Pass NULL if you don't want the command output 201 /// \arg hide_stderr If this is \b false, redirect stderr to stdout 202 static Status RunShellCommand(llvm::StringRef shell, llvm::StringRef command, 203 const FileSpec &working_dir, int *status_ptr, 204 int *signo_ptr, std::string *command_output, 205 const Timeout<std::micro> &timeout, 206 bool run_in_shell = true, 207 bool hide_stderr = false); 208 209 /// Run a shell command. 210 /// \arg working_dir Pass empty FileSpec to use the current working directory 211 /// \arg status_ptr Pass NULL if you don't want the process exit status 212 /// \arg signo_ptr Pass NULL if you don't want the signal that caused the 213 /// process to exit 214 /// \arg command_output Pass NULL if you don't want the command output 215 /// \arg hide_stderr if this is false, redirect stderr to stdout 216 static Status RunShellCommand(const Args &args, const FileSpec &working_dir, 217 int *status_ptr, int *signo_ptr, 218 std::string *command_output, 219 const Timeout<std::micro> &timeout, 220 bool run_in_shell = true, 221 bool hide_stderr = false); 222 223 /// Run a shell command. 224 /// \arg shell Pass an empty string if you want to use the default 225 /// shell interpreter \arg command \arg working_dir Pass empty FileSpec to use 226 /// the current working directory \arg status_ptr Pass NULL if you don't 227 /// want the process exit status \arg signo_ptr Pass NULL if you don't 228 /// want the signal that caused the 229 /// process to exit 230 /// \arg command_output Pass NULL if you don't want the command output 231 /// \arg hide_stderr If this is \b false, redirect stderr to stdout 232 static Status RunShellCommand(llvm::StringRef shell, const Args &args, 233 const FileSpec &working_dir, int *status_ptr, 234 int *signo_ptr, std::string *command_output, 235 const Timeout<std::micro> &timeout, 236 bool run_in_shell = true, 237 bool hide_stderr = false); 238 239 static bool OpenFileInExternalEditor(const FileSpec &file_spec, 240 uint32_t line_no); 241 242 /// Check if we're running in an interactive graphical session. 243 /// 244 /// \return 245 /// True if we're running in an interactive graphical session. False if 246 /// we're not or don't know. 247 static bool IsInteractiveGraphicSession(); 248 249 static Environment GetEnvironment(); 250 251 static std::unique_ptr<Connection> 252 CreateDefaultConnection(llvm::StringRef url); 253 254 protected: 255 static uint32_t FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, 256 ProcessInstanceInfoList &proc_infos); 257 }; 258 259 /// Log handler that emits log messages to the operating system log. 260 class SystemLogHandler : public LogHandler { 261 public: 262 SystemLogHandler(); 263 void Emit(llvm::StringRef message) override; 264 isA(const void * ClassID)265 bool isA(const void *ClassID) const override { return ClassID == &ID; } classof(const LogHandler * obj)266 static bool classof(const LogHandler *obj) { return obj->isA(&ID); } 267 268 private: 269 static char ID; 270 }; 271 272 } // namespace lldb_private 273 274 namespace llvm { 275 template <> struct format_provider<lldb_private::WaitStatus> { 276 /// Options = "" gives a human readable description of the status Options = 277 /// "g" gives a gdb-remote protocol status (e.g., X09) 278 static void format(const lldb_private::WaitStatus &WS, raw_ostream &OS, 279 llvm::StringRef Options); 280 }; 281 } // namespace llvm 282 283 #endif // LLDB_HOST_HOST_H 284