| //===-- 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 <cstdarg> |
| #include <map> |
| #include <string> |
| #include <type_traits> |
| |
| namespace lldb_private { |
| |
| class FileAction; |
| class ProcessLaunchInfo; |
| class ProcessInstanceInfo; |
| class ProcessInstanceInfoMatch; |
| typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList; |
| |
| // 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 empty |
| /// \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(llvm::StringRef command, |
| const FileSpec &working_dir, int *status_ptr, |
| int *signo_ptr, std::string *command_output, |
| const Timeout<std::micro> &timeout, |
| bool run_in_shell = true, |
| bool hide_stderr = false); |
| |
| /// Run a shell command. |
| /// \arg shell Pass an empty string if you want to use the default shell |
| /// interpreter \arg 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 \b false, redirect stderr to stdout |
| static Status RunShellCommand(llvm::StringRef shell, llvm::StringRef command, |
| const FileSpec &working_dir, int *status_ptr, |
| int *signo_ptr, std::string *command_output, |
| const Timeout<std::micro> &timeout, |
| bool run_in_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_shell = true, |
| bool hide_stderr = false); |
| |
| /// Run a shell command. |
| /// \arg shell Pass an empty string if you want to use the default |
| /// shell interpreter \arg 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 \b false, redirect stderr to stdout |
| static Status RunShellCommand(llvm::StringRef shell, 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_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); |
| |
| protected: |
| static uint32_t FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, |
| ProcessInstanceInfoList &proc_infos); |
| }; |
| |
| } // 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 |