• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Timeout.h"
17 #include "lldb/lldb-private-forward.h"
18 #include "lldb/lldb-private.h"
19 #include <cerrno>
20 #include <map>
21 #include <stdarg.h>
22 #include <string>
23 #include <type_traits>
24 
25 namespace lldb_private {
26 
27 class FileAction;
28 class ProcessLaunchInfo;
29 class ProcessInstanceInfo;
30 class ProcessInstanceInfoMatch;
31 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
32 
33 // Exit Type for inferior processes
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 /// \class Host Host.h "lldb/Host/Host.h"
59 /// A class that provides host computer information.
60 ///
61 /// Host is a class that answers information about the host operating system.
62 class Host {
63 public:
64   typedef std::function<bool(
65       lldb::pid_t pid, bool exited,
66       int signal,  // Zero for no signal
67       int status)> // Exit value of process if signal is zero
68       MonitorChildProcessCallback;
69 
70   /// Start monitoring a child process.
71   ///
72   /// Allows easy monitoring of child processes. \a callback will be called
73   /// when the child process exits or if it gets a signal. The callback will
74   /// only be called with signals if \a monitor_signals is \b true. \a
75   /// callback will usually be called from another thread so the callback
76   /// function must be thread safe.
77   ///
78   /// When the callback gets called, the return value indicates if monitoring
79   /// should stop. If \b true is returned from \a callback the information
80   /// will be removed. If \b false is returned then monitoring will continue.
81   /// If the child process exits, the monitoring will automatically stop after
82   /// the callback returned regardless of the callback return value.
83   ///
84   /// \param[in] callback
85   ///     A function callback to call when a child receives a signal
86   ///     (if \a monitor_signals is true) or a child exits.
87   ///
88   /// \param[in] pid
89   ///     The process ID of a child process to monitor, -1 for all
90   ///     processes.
91   ///
92   /// \param[in] monitor_signals
93   ///     If \b true the callback will get called when the child
94   ///     process gets a signal. If \b false, the callback will only
95   ///     get called if the child process exits.
96   ///
97   /// \return
98   ///     A thread handle that can be used to cancel the thread that
99   ///     was spawned to monitor \a pid.
100   ///
101   /// \see static void Host::StopMonitoringChildProcess (uint32_t)
102   static llvm::Expected<HostThread>
103   StartMonitoringChildProcess(const MonitorChildProcessCallback &callback,
104                               lldb::pid_t pid, bool monitor_signals);
105 
106   enum SystemLogType { eSystemLogWarning, eSystemLogError };
107 
108   static void SystemLog(SystemLogType type, const char *format, ...)
109       __attribute__((format(printf, 2, 3)));
110 
111   static void SystemLog(SystemLogType type, const char *format, va_list args);
112 
113   /// Get the process ID for the calling process.
114   ///
115   /// \return
116   ///     The process ID for the current process.
117   static lldb::pid_t GetCurrentProcessID();
118 
119   static void Kill(lldb::pid_t pid, int signo);
120 
121   /// Get the thread token (the one returned by ThreadCreate when the thread
122   /// was created) for the calling thread in the current process.
123   ///
124   /// \return
125   ///     The thread token for the calling thread in the current process.
126   static lldb::thread_t GetCurrentThread();
127 
128   static const char *GetSignalAsCString(int signo);
129 
130   /// Given an address in the current process (the process that is running the
131   /// LLDB code), return the name of the module that it comes from. This can
132   /// be useful when you need to know the path to the shared library that your
133   /// code is running in for loading resources that are relative to your
134   /// binary.
135   ///
136   /// \param[in] host_addr
137   ///     The pointer to some code in the current process.
138   ///
139   /// \return
140   ///     \b A file spec with the module that contains \a host_addr,
141   ///     which may be invalid if \a host_addr doesn't fall into
142   ///     any valid module address range.
143   static FileSpec GetModuleFileSpecForHostAddress(const void *host_addr);
144 
145   /// If you have an executable that is in a bundle and want to get back to
146   /// the bundle directory from the path itself, this function will change a
147   /// path to a file within a bundle to the bundle directory itself.
148   ///
149   /// \param[in] file
150   ///     A file spec that might point to a file in a bundle.
151   ///
152   /// \param[out] bundle_directory
153   ///     An object will be filled in with the bundle directory for
154   ///     the bundle when \b true is returned. Otherwise \a file is
155   ///     left untouched and \b false is returned.
156   ///
157   /// \return
158   ///     \b true if \a file was resolved in \a bundle_directory,
159   ///     \b false otherwise.
160   static bool GetBundleDirectory(const FileSpec &file,
161                                  FileSpec &bundle_directory);
162 
163   /// When executable files may live within a directory, where the directory
164   /// represents an executable bundle (like the MacOSX app bundles), then
165   /// locate the executable within the containing bundle.
166   ///
167   /// \param[in,out] file
168   ///     A file spec that currently points to the bundle that will
169   ///     be filled in with the executable path within the bundle
170   ///     if \b true is returned. Otherwise \a file is left untouched.
171   ///
172   /// \return
173   ///     \b true if \a file was resolved, \b false if this function
174   ///     was not able to resolve the path.
175   static bool ResolveExecutableInBundle(FileSpec &file);
176 
177   static uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info,
178                                 ProcessInstanceInfoList &proc_infos);
179 
180   typedef std::map<lldb::pid_t, bool> TidMap;
181   typedef std::pair<lldb::pid_t, bool> TidPair;
182   static bool FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach);
183 
184   static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info);
185 
186   /// Launch the process specified in launch_info. The monitoring callback in
187   /// launch_info must be set, and it will be called when the process
188   /// terminates.
189   static Status LaunchProcess(ProcessLaunchInfo &launch_info);
190 
191   /// Perform expansion of the command-line for this launch info This can
192   /// potentially involve wildcard expansion
193   /// environment variable replacement, and whatever other
194   /// argument magic the platform defines as part of its typical
195   /// user experience
196   static Status ShellExpandArguments(ProcessLaunchInfo &launch_info);
197 
198   /// Run a shell command.
199   /// \arg command  shouldn't be empty
200   /// \arg working_dir Pass empty FileSpec to use the current working directory
201   /// \arg status_ptr  Pass NULL if you don't want the process exit status
202   /// \arg signo_ptr   Pass NULL if you don't want the signal that caused the
203   ///                  process to exit
204   /// \arg command_output  Pass NULL if you don't want the command output
205   /// \arg hide_stderr if this is false, redirect stderr to stdout
206   static Status RunShellCommand(llvm::StringRef command,
207                                 const FileSpec &working_dir, int *status_ptr,
208                                 int *signo_ptr, std::string *command_output,
209                                 const Timeout<std::micro> &timeout,
210                                 bool run_in_shell = true,
211                                 bool hide_stderr = false);
212 
213   /// Run a shell command.
214   /// \arg shell  Pass an empty string if you want to use the default shell
215   /// interpreter \arg command \arg working_dir  Pass empty FileSpec to use the
216   /// current working directory \arg status_ptr   Pass NULL if you don't want
217   /// the process exit status \arg signo_ptr    Pass NULL if you don't want the
218   /// signal that caused
219   ///                   the process to exit
220   /// \arg command_output  Pass NULL if you don't want the command output
221   /// \arg hide_stderr  If this is \b false, redirect stderr to stdout
222   static Status RunShellCommand(llvm::StringRef shell, llvm::StringRef command,
223                                 const FileSpec &working_dir, int *status_ptr,
224                                 int *signo_ptr, std::string *command_output,
225                                 const Timeout<std::micro> &timeout,
226                                 bool run_in_shell = true,
227                                 bool hide_stderr = false);
228 
229   /// Run a shell command.
230   /// \arg working_dir Pass empty FileSpec to use the current working directory
231   /// \arg status_ptr  Pass NULL if you don't want the process exit status
232   /// \arg signo_ptr   Pass NULL if you don't want the signal that caused the
233   ///                  process to exit
234   /// \arg command_output  Pass NULL if you don't want the command output
235   /// \arg hide_stderr if this is false, redirect stderr to stdout
236   static Status RunShellCommand(const Args &args, const FileSpec &working_dir,
237                                 int *status_ptr, int *signo_ptr,
238                                 std::string *command_output,
239                                 const Timeout<std::micro> &timeout,
240                                 bool run_in_shell = true,
241                                 bool hide_stderr = false);
242 
243   /// Run a shell command.
244   /// \arg shell            Pass an empty string if you want to use the default
245   /// shell interpreter \arg command \arg working_dir Pass empty FileSpec to use
246   /// the current working directory \arg status_ptr    Pass NULL if you don't
247   /// want the process exit status \arg signo_ptr     Pass NULL if you don't
248   /// want the signal that caused the
249   ///               process to exit
250   /// \arg command_output  Pass NULL if you don't want the command output
251   /// \arg hide_stderr If this is \b false, redirect stderr to stdout
252   static Status RunShellCommand(llvm::StringRef shell, const Args &args,
253                                 const FileSpec &working_dir, int *status_ptr,
254                                 int *signo_ptr, std::string *command_output,
255                                 const Timeout<std::micro> &timeout,
256                                 bool run_in_shell = true,
257                                 bool hide_stderr = false);
258 
259   static bool OpenFileInExternalEditor(const FileSpec &file_spec,
260                                        uint32_t line_no);
261 
262   static Environment GetEnvironment();
263 
264   static std::unique_ptr<Connection>
265   CreateDefaultConnection(llvm::StringRef url);
266 
267 protected:
268   static uint32_t FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
269                                     ProcessInstanceInfoList &proc_infos);
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