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