1 //===-- Host.h --------------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLDB_HOST_HOST_H
11 #define LLDB_HOST_HOST_H
12 
13 #include "lldb/Host/File.h"
14 #include "lldb/Host/HostThread.h"
15 #include "lldb/Utility/Environment.h"
16 #include "lldb/Utility/FileSpec.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 <map>
22 #include <stdarg.h>
23 #include <string>
24 #include <type_traits>
25 
26 namespace lldb_private {
27 
28 class FileAction;
29 class ProcessLaunchInfo;
30 
31 //----------------------------------------------------------------------
32 // Exit Type for inferior processes
33 //----------------------------------------------------------------------
34 struct WaitStatus {
35   enum Type : uint8_t {
36     Exit,   // The status represents the return code from normal
37             // program exit (i.e. WIFEXITED() was true)
38     Signal, // The status represents the signal number that caused
39             // the program to exit (i.e. WIFSIGNALED() was true)
40     Stop,   // The status represents the signal number that caused the
41             // program to stop (i.e. WIFSTOPPED() was true)
42   };
43 
44   Type type;
45   uint8_t status;
46 
WaitStatusWaitStatus47   WaitStatus(Type type, uint8_t status) : type(type), status(status) {}
48 
49   static WaitStatus Decode(int wstatus);
50 };
51 
52 inline bool operator==(WaitStatus a, WaitStatus b) {
53   return a.type == b.type && a.status == b.status;
54 }
55 
56 inline bool operator!=(WaitStatus a, WaitStatus b) { return !(a == b); }
57 
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 //----------------------------------------------------------------------
64 class Host {
65 public:
66   typedef std::function<bool(
67       lldb::pid_t pid, bool exited,
68       int signal,  // Zero for no signal
69       int status)> // Exit value of process if signal is zero
70       MonitorChildProcessCallback;
71 
72   //------------------------------------------------------------------
73   /// Start monitoring a child process.
74   ///
75   /// Allows easy monitoring of child processes. \a callback will be called
76   /// when the child process exits or if it gets a signal. The callback will
77   /// only be called with signals if \a monitor_signals is \b true. \a
78   /// callback will usually be called from another thread so the callback
79   /// function must be thread safe.
80   ///
81   /// When the callback gets called, the return value indicates if monitoring
82   /// should stop. If \b true is returned from \a callback the information
83   /// will be removed. If \b false is returned then monitoring will continue.
84   /// If the child process exits, the monitoring will automatically stop after
85   /// the callback returned regardless of the callback return value.
86   ///
87   /// @param[in] callback
88   ///     A function callback to call when a child receives a signal
89   ///     (if \a monitor_signals is true) or a child exits.
90   ///
91   /// @param[in] pid
92   ///     The process ID of a child process to monitor, -1 for all
93   ///     processes.
94   ///
95   /// @param[in] monitor_signals
96   ///     If \b true the callback will get called when the child
97   ///     process gets a signal. If \b false, the callback will only
98   ///     get called if the child process exits.
99   ///
100   /// @return
101   ///     A thread handle that can be used to cancel the thread that
102   ///     was spawned to monitor \a pid.
103   ///
104   /// @see static void Host::StopMonitoringChildProcess (uint32_t)
105   //------------------------------------------------------------------
106   static HostThread
107   StartMonitoringChildProcess(const MonitorChildProcessCallback &callback,
108                               lldb::pid_t pid, bool monitor_signals);
109 
110   enum SystemLogType { eSystemLogWarning, eSystemLogError };
111 
112   static void SystemLog(SystemLogType type, const char *format, ...)
113       __attribute__((format(printf, 2, 3)));
114 
115   static void SystemLog(SystemLogType type, const char *format, va_list args);
116 
117   //------------------------------------------------------------------
118   /// Get the process ID for the calling process.
119   ///
120   /// @return
121   ///     The process ID for the current process.
122   //------------------------------------------------------------------
123   static lldb::pid_t GetCurrentProcessID();
124 
125   static void Kill(lldb::pid_t pid, int signo);
126 
127   //------------------------------------------------------------------
128   /// Get the thread token (the one returned by ThreadCreate when the thread
129   /// was created) for the calling thread in the current process.
130   ///
131   /// @return
132   ///     The thread token for the calling thread in the current process.
133   //------------------------------------------------------------------
134   static lldb::thread_t GetCurrentThread();
135 
136   static const char *GetSignalAsCString(int signo);
137 
138   //------------------------------------------------------------------
139   /// Given an address in the current process (the process that is running the
140   /// LLDB code), return the name of the module that it comes from. This can
141   /// be useful when you need to know the path to the shared library that your
142   /// code is running in for loading resources that are relative to your
143   /// binary.
144   ///
145   /// @param[in] host_addr
146   ///     The pointer to some code in the current process.
147   ///
148   /// @return
149   ///     \b A file spec with the module that contains \a host_addr,
150   ///     which may be invalid if \a host_addr doesn't fall into
151   ///     any valid module address range.
152   //------------------------------------------------------------------
153   static FileSpec GetModuleFileSpecForHostAddress(const void *host_addr);
154 
155   //------------------------------------------------------------------
156   /// If you have an executable that is in a bundle and want to get back to
157   /// the bundle directory from the path itself, this function will change a
158   /// path to a file within a bundle to the bundle directory itself.
159   ///
160   /// @param[in] file
161   ///     A file spec that might point to a file in a bundle.
162   ///
163   /// @param[out] bundle_directory
164   ///     An object will be filled in with the bundle directory for
165   ///     the bundle when \b true is returned. Otherwise \a file is
166   ///     left untouched and \b false is returned.
167   ///
168   /// @return
169   ///     \b true if \a file was resolved in \a bundle_directory,
170   ///     \b false otherwise.
171   //------------------------------------------------------------------
172   static bool GetBundleDirectory(const FileSpec &file,
173                                  FileSpec &bundle_directory);
174 
175   //------------------------------------------------------------------
176   /// When executable files may live within a directory, where the directory
177   /// represents an executable bundle (like the MacOSX app bundles), then
178   /// locate the executable within the containing bundle.
179   ///
180   /// @param[in,out] file
181   ///     A file spec that currently points to the bundle that will
182   ///     be filled in with the executable path within the bundle
183   ///     if \b true is returned. Otherwise \a file is left untouched.
184   ///
185   /// @return
186   ///     \b true if \a file was resolved, \b false if this function
187   ///     was not able to resolve the path.
188   //------------------------------------------------------------------
189   static bool ResolveExecutableInBundle(FileSpec &file);
190 
191   static uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info,
192                                 ProcessInstanceInfoList &proc_infos);
193 
194   typedef std::map<lldb::pid_t, bool> TidMap;
195   typedef std::pair<lldb::pid_t, bool> TidPair;
196   static bool FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach);
197 
198   static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info);
199 
200   static const lldb::UnixSignalsSP &GetUnixSignals();
201 
202   /// Launch the process specified in launch_info. The monitoring callback in
203   /// launch_info must be set, and it will be called when the process
204   /// terminates.
205   static Status LaunchProcess(ProcessLaunchInfo &launch_info);
206 
207   //------------------------------------------------------------------
208   /// Perform expansion of the command-line for this launch info This can
209   /// potentially involve wildcard expansion
210   //  environment variable replacement, and whatever other
211   //  argument magic the platform defines as part of its typical
212   //  user experience
213   //------------------------------------------------------------------
214   static Status ShellExpandArguments(ProcessLaunchInfo &launch_info);
215 
216   // TODO: Convert this function to take a StringRef.
217   static Status RunShellCommand(
218       const char *command,         // Shouldn't be NULL
219       const FileSpec &working_dir, // Pass empty FileSpec to use the current
220                                    // working directory
221       int *status_ptr, // Pass NULL if you don't want the process exit status
222       int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
223                        // process to exit
224       std::string
225           *command_output, // Pass NULL if you don't want the command output
226       const Timeout<std::micro> &timeout, bool run_in_default_shell = true);
227 
228   static Status RunShellCommand(
229       const Args &args,
230       const FileSpec &working_dir, // Pass empty FileSpec to use the current
231                                    // working directory
232       int *status_ptr, // Pass NULL if you don't want the process exit status
233       int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
234                        // process to exit
235       std::string
236           *command_output, // Pass NULL if you don't want the command output
237       const Timeout<std::micro> &timeout, bool run_in_default_shell = true);
238 
239   static bool OpenFileInExternalEditor(const FileSpec &file_spec,
240                                        uint32_t line_no);
241 
242   static Environment GetEnvironment();
243 
244   static std::unique_ptr<Connection>
245   CreateDefaultConnection(llvm::StringRef url);
246 };
247 
248 } // namespace lldb_private
249 
250 namespace llvm {
251 template <> struct format_provider<lldb_private::WaitStatus> {
252   /// Options = "" gives a human readable description of the status Options =
253   /// "g" gives a gdb-remote protocol status (e.g., X09)
254   static void format(const lldb_private::WaitStatus &WS, raw_ostream &OS,
255                      llvm::StringRef Options);
256 };
257 } // namespace llvm
258 
259 #endif // LLDB_HOST_HOST_H
260