LLDB  mainline
ProcessLaunchInfo.cpp
Go to the documentation of this file.
1 //===-- ProcessLaunchInfo.cpp ---------------------------------------------===//
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 #include <climits>
10 
11 #include "lldb/Host/Config.h"
12 #include "lldb/Host/FileAction.h"
13 #include "lldb/Host/FileSystem.h"
14 #include "lldb/Host/HostInfo.h"
16 #include "lldb/Utility/Log.h"
18 
19 #include "llvm/Support/ConvertUTF.h"
20 #include "llvm/Support/FileSystem.h"
21 
22 #if !defined(_WIN32)
23 #include <limits.h>
24 #endif
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 // ProcessLaunchInfo member functions
30 
31 ProcessLaunchInfo::ProcessLaunchInfo()
32  : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
33  m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0),
34  m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr),
35  m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(),
36  m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {}
37 
39  const FileSpec &stdout_file_spec,
40  const FileSpec &stderr_file_spec,
41  const FileSpec &working_directory,
42  uint32_t launch_flags)
43  : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
44  m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0),
45  m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr),
46  m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(),
47  m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {
48  if (stdin_file_spec) {
49  FileAction file_action;
50  const bool read = true;
51  const bool write = false;
52  if (file_action.Open(STDIN_FILENO, stdin_file_spec, read, write))
53  AppendFileAction(file_action);
54  }
55  if (stdout_file_spec) {
56  FileAction file_action;
57  const bool read = false;
58  const bool write = true;
59  if (file_action.Open(STDOUT_FILENO, stdout_file_spec, read, write))
60  AppendFileAction(file_action);
61  }
62  if (stderr_file_spec) {
63  FileAction file_action;
64  const bool read = false;
65  const bool write = true;
66  if (file_action.Open(STDERR_FILENO, stderr_file_spec, read, write))
67  AppendFileAction(file_action);
68  }
69  if (working_directory)
70  SetWorkingDirectory(working_directory);
71 }
72 
74  FileAction file_action;
75  if (file_action.Close(fd)) {
76  AppendFileAction(file_action);
77  return true;
78  }
79  return false;
80 }
81 
83  FileAction file_action;
84  if (file_action.Duplicate(fd, dup_fd)) {
85  AppendFileAction(file_action);
86  return true;
87  }
88  return false;
89 }
90 
91 bool ProcessLaunchInfo::AppendOpenFileAction(int fd, const FileSpec &file_spec,
92  bool read, bool write) {
93  FileAction file_action;
94  if (file_action.Open(fd, file_spec, read, write)) {
95  AppendFileAction(file_action);
96  return true;
97  }
98  return false;
99 }
100 
102  bool write) {
103  FileAction file_action;
104  if (file_action.Open(fd, FileSpec(FileSystem::DEV_NULL), read, write)) {
105  AppendFileAction(file_action);
106  return true;
107  }
108  return false;
109 }
110 
112  if (idx < m_file_actions.size())
113  return &m_file_actions[idx];
114  return nullptr;
115 }
116 
118  for (size_t idx = 0, count = m_file_actions.size(); idx < count; ++idx) {
119  if (m_file_actions[idx].GetFD() == fd)
120  return &m_file_actions[idx];
121  }
122  return nullptr;
123 }
124 
126  return m_working_dir;
127 }
128 
130  m_working_dir = working_dir;
131 }
132 
134  return (m_plugin_name.empty() ? nullptr : m_plugin_name.c_str());
135 }
136 
137 void ProcessLaunchInfo::SetProcessPluginName(llvm::StringRef plugin) {
138  m_plugin_name = std::string(plugin);
139 }
140 
141 const FileSpec &ProcessLaunchInfo::GetShell() const { return m_shell; }
142 
144  m_shell = shell;
145  if (m_shell) {
147  m_flags.Set(lldb::eLaunchFlagLaunchInShell);
148  } else
149  m_flags.Clear(lldb::eLaunchFlagLaunchInShell);
150 }
151 
153  if (separate)
154  m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
155  else
156  m_flags.Clear(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
157 }
158 
160  if (expand)
161  m_flags.Set(lldb::eLaunchFlagShellExpandArguments);
162  else
163  m_flags.Clear(lldb::eLaunchFlagShellExpandArguments);
164 }
165 
169  m_plugin_name.clear();
170  m_shell.Clear();
171  m_flags.Clear();
172  m_file_actions.clear();
173  m_resume_count = 0;
174  m_listener_sp.reset();
175  m_hijack_listener_sp.reset();
178 }
179 
181  const Host::MonitorChildProcessCallback &callback, bool monitor_signals) {
182  m_monitor_callback = callback;
183  m_monitor_signals = monitor_signals;
184 }
185 
186 bool ProcessLaunchInfo::NoOpMonitorCallback(lldb::pid_t pid, bool exited, int signal, int status) {
188  LLDB_LOG(log, "pid = {0}, exited = {1}, signal = {2}, status = {3}", pid,
189  exited, signal, status);
190  return true;
191 }
192 
195  llvm::Expected<HostThread> maybe_thread =
198  if (!maybe_thread)
200  "failed to launch host thread: {}",
201  llvm::toString(maybe_thread.takeError()));
202  return true;
203  }
204  return false;
205 }
206 
208  if (enable)
209  m_flags.Set(lldb::eLaunchFlagDetachOnError);
210  else
211  m_flags.Clear(lldb::eLaunchFlagDetachOnError);
212 }
213 
216  LLDB_LOG(log, "Generating a pty to use for stdin/out/err");
217 
218  int open_flags = O_RDWR | O_NOCTTY;
219 #if !defined(_WIN32)
220  // We really shouldn't be specifying platform specific flags that are
221  // intended for a system call in generic code. But this will have to
222  // do for now.
223  open_flags |= O_CLOEXEC;
224 #endif
225  if (llvm::Error Err = m_pty->OpenFirstAvailablePrimary(open_flags))
226  return Err;
227 
228  const FileSpec secondary_file_spec(m_pty->GetSecondaryName());
229 
230  // Only use the secondary tty if we don't have anything specified for
231  // input and don't have an action for stdin
232  if (GetFileActionForFD(STDIN_FILENO) == nullptr)
233  AppendOpenFileAction(STDIN_FILENO, secondary_file_spec, true, false);
234 
235  // Only use the secondary tty if we don't have anything specified for
236  // output and don't have an action for stdout
237  if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
238  AppendOpenFileAction(STDOUT_FILENO, secondary_file_spec, false, true);
239 
240  // Only use the secondary tty if we don't have anything specified for
241  // error and don't have an action for stderr
242  if (GetFileActionForFD(STDERR_FILENO) == nullptr)
243  AppendOpenFileAction(STDERR_FILENO, secondary_file_spec, false, true);
244  return llvm::Error::success();
245 }
246 
248  Status &error, bool will_debug, bool first_arg_is_full_shell_command,
249  uint32_t num_resumes) {
250  error.Clear();
251 
252  if (GetFlags().Test(eLaunchFlagLaunchInShell)) {
253  if (m_shell) {
254  std::string shell_executable = m_shell.GetPath();
255 
256  const char **argv = GetArguments().GetConstArgumentVector();
257  if (argv == nullptr || argv[0] == nullptr)
258  return false;
259  Args shell_arguments;
260  shell_arguments.AppendArgument(shell_executable);
261  const llvm::Triple &triple = GetArchitecture().GetTriple();
262  if (triple.getOS() == llvm::Triple::Win32 &&
263  !triple.isWindowsCygwinEnvironment())
264  shell_arguments.AppendArgument(llvm::StringRef("/C"));
265  else
266  shell_arguments.AppendArgument(llvm::StringRef("-c"));
267 
268  StreamString shell_command;
269  if (will_debug) {
270  // Add a modified PATH environment variable in case argv[0] is a
271  // relative path.
272  const char *argv0 = argv[0];
273  FileSpec arg_spec(argv0);
274  if (arg_spec.IsRelative()) {
275  // We have a relative path to our executable which may not work if we
276  // just try to run "a.out" (without it being converted to "./a.out")
277  FileSpec working_dir = GetWorkingDirectory();
278  // Be sure to put quotes around PATH's value in case any paths have
279  // spaces...
280  std::string new_path("PATH=\"");
281  const size_t empty_path_len = new_path.size();
282 
283  if (working_dir) {
284  new_path += working_dir.GetPath();
285  } else {
286  llvm::SmallString<64> cwd;
287  if (! llvm::sys::fs::current_path(cwd))
288  new_path += cwd;
289  }
290  std::string curr_path;
291  if (HostInfo::GetEnvironmentVar("PATH", curr_path)) {
292  if (new_path.size() > empty_path_len)
293  new_path += ':';
294  new_path += curr_path;
295  }
296  new_path += "\" ";
297  shell_command.PutCString(new_path);
298  }
299 
300  if (triple.getOS() != llvm::Triple::Win32 ||
301  triple.isWindowsCygwinEnvironment())
302  shell_command.PutCString("exec");
303 
304  // Only Apple supports /usr/bin/arch being able to specify the
305  // architecture
306  if (GetArchitecture().IsValid() && // Valid architecture
307  GetArchitecture().GetTriple().getVendor() ==
308  llvm::Triple::Apple && // Apple only
309  GetArchitecture().GetCore() !=
310  ArchSpec::eCore_x86_64_x86_64h) // Don't do this for x86_64h
311  {
312  shell_command.Printf(" /usr/bin/arch -arch %s",
313  GetArchitecture().GetArchitectureName());
314  // Set the resume count to 2:
315  // 1 - stop in shell
316  // 2 - stop in /usr/bin/arch
317  // 3 - then we will stop in our program
318  SetResumeCount(num_resumes + 1);
319  } else {
320  // Set the resume count to 1:
321  // 1 - stop in shell
322  // 2 - then we will stop in our program
323  SetResumeCount(num_resumes);
324  }
325  }
326 
327  if (first_arg_is_full_shell_command) {
328  // There should only be one argument that is the shell command itself
329  // to be used as is
330  if (argv[0] && !argv[1])
331  shell_command.Printf("%s", argv[0]);
332  else
333  return false;
334  } else {
335  for (size_t i = 0; argv[i] != nullptr; ++i) {
336  std::string safe_arg = Args::GetShellSafeArgument(m_shell, argv[i]);
337  // Add a space to separate this arg from the previous one.
338  shell_command.PutCString(" ");
339  shell_command.PutCString(safe_arg);
340  }
341  }
342  shell_arguments.AppendArgument(shell_command.GetString());
344  m_arguments = shell_arguments;
345  return true;
346  } else {
347  error.SetErrorString("invalid shell path");
348  }
349  } else {
350  error.SetErrorString("not launching in shell");
351  }
352  return false;
353 }
lldb_private::PseudoTerminal
Definition: PseudoTerminal.h:24
lldb_private::ProcessInfo::GetArguments
Args & GetArguments()
Definition: ProcessInfo.h:75
separate
static bool separate(size_t count)
Definition: UUID.cpp:24
lldb_private::ProcessLaunchInfo::AppendDuplicateFileAction
bool AppendDuplicateFileAction(int fd, int dup_fd)
Definition: ProcessLaunchInfo.cpp:82
lldb_private::ProcessLaunchInfo::m_pty
std::shared_ptr< PseudoTerminal > m_pty
Definition: ProcessLaunchInfo.h:178
FileSystem.h
lldb_private::ProcessInfo::ProcessIDIsValid
bool ProcessIDIsValid() const
Definition: ProcessInfo.h:71
lldb_private::ProcessLaunchInfo::SetWorkingDirectory
void SetWorkingDirectory(const FileSpec &working_dir)
Definition: ProcessLaunchInfo.cpp:129
lldb_private::Host::MonitorChildProcessCallback
std::function< bool(lldb::pid_t pid, bool exited, int signal, int status)> MonitorChildProcessCallback
Definition: Host.h:68
lldb_private::ProcessInfo::m_executable
FileSpec m_executable
Definition: ProcessInfo.h:92
lldb_private::ProcessLaunchInfo::SetShell
void SetShell(const FileSpec &shell)
Definition: ProcessLaunchInfo.cpp:143
ProcessLaunchInfo.h
lldb_private::FileAction::Close
bool Close(int fd)
Definition: FileAction.cpp:52
lldb_private::Flags::Clear
ValueType Clear(ValueType mask=~static_cast< ValueType >(0))
Clear one or more flags.
Definition: Flags.h:61
lldb_private::Args::AppendArgument
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition: Args.cpp:318
lldb_private::ProcessLaunchInfo::m_scripted_process_class_name
std::string m_scripted_process_class_name
Definition: ProcessLaunchInfo.h:187
lldb_private::ProcessLaunchInfo::m_working_dir
FileSpec m_working_dir
Definition: ProcessLaunchInfo.h:173
lldb_private::ProcessLaunchInfo::GetFileActionForFD
const FileAction * GetFileActionForFD(int fd) const
Definition: ProcessLaunchInfo.cpp:117
lldb_private::ProcessInfo::GetProcessID
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:67
lldb_private::FileSystem::ResolveExecutableLocation
bool ResolveExecutableLocation(FileSpec &file_spec)
Call into the Host to see if it can help find the file.
Definition: common/FileSystem.cpp:330
lldb_private::ProcessLaunchInfo::SetShellExpandArguments
void SetShellExpandArguments(bool expand)
Definition: ProcessLaunchInfo.cpp:159
lldb_private::ProcessLaunchInfo::GetFlags
Flags & GetFlags()
Definition: ProcessLaunchInfo.h:64
lldb_private::Args
Definition: Args.h:33
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:444
lldb_private::ProcessLaunchInfo::NoOpMonitorCallback
static bool NoOpMonitorCallback(lldb::pid_t pid, bool exited, int signal, int status)
A Monitor callback which does not take any action on process events.
Definition: ProcessLaunchInfo.cpp:186
lldb_private::FileAction::Duplicate
bool Duplicate(int fd, int dup_fd)
Definition: FileAction.cpp:61
lldb_private::FileSystem::DEV_NULL
static const char * DEV_NULL
Definition: FileSystem.h:31
lldb_private::ProcessLaunchInfo::AppendFileAction
void AppendFileAction(const FileAction &info)
Definition: ProcessLaunchInfo.h:40
lldb_private::FileAction
Definition: FileAction.h:17
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
lldb_private::ProcessLaunchInfo::m_flags
Flags m_flags
Definition: ProcessLaunchInfo.h:176
lldb_private::ProcessLaunchInfo::AppendCloseFileAction
bool AppendCloseFileAction(int fd)
Definition: ProcessLaunchInfo.cpp:73
lldb_private::ProcessLaunchInfo::m_monitor_signals
bool m_monitor_signals
Definition: ProcessLaunchInfo.h:182
lldb_private::FileAction::Open
bool Open(int fd, const FileSpec &file_spec, bool read, bool write)
Definition: FileAction.cpp:33
LIBLLDB_LOG_HOST
#define LIBLLDB_LOG_HOST
Definition: Logging.h:28
lldb_private::FileSpec
Definition: FileSpec.h:56
O_NOCTTY
#define O_NOCTTY
Definition: windows/PosixApi.h:28
lldb_private::ProcessLaunchInfo::AppendSuppressFileAction
bool AppendSuppressFileAction(int fd, bool read, bool write)
Definition: ProcessLaunchInfo.cpp:101
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::ProcessLaunchInfo::m_monitor_callback
Host::MonitorChildProcessCallback m_monitor_callback
Definition: ProcessLaunchInfo.h:180
lldb_private::ProcessInfo::m_arguments
Args m_arguments
Definition: ProcessInfo.h:96
lldb_private::ProcessInfo::Clear
void Clear()
Definition: ProcessInfo.cpp:33
lldb_private::Host::StartMonitoringChildProcess
static llvm::Expected< HostThread > StartMonitoringChildProcess(const MonitorChildProcessCallback &callback, lldb::pid_t pid, bool monitor_signals)
Start monitoring a child process.
Definition: common/Host.cpp:103
lldb_private::ProcessLaunchInfo::Clear
void Clear()
Definition: ProcessLaunchInfo.cpp:166
lldb_private::breakpad::toString
llvm::StringRef toString(Record::Kind K)
Definition: BreakpadRecords.cpp:483
Log.h
lldb_private::ProcessInfo
Definition: ProcessInfo.h:30
lldb_private::ArchSpec::eCore_x86_64_x86_64h
@ eCore_x86_64_x86_64h
Definition: ArchSpec.h:189
lldb_private::ProcessLaunchInfo::SetDetachOnError
void SetDetachOnError(bool enable)
Definition: ProcessLaunchInfo.cpp:207
StreamString.h
lldb_private::ProcessLaunchInfo::SetProcessPluginName
void SetProcessPluginName(llvm::StringRef plugin)
Definition: ProcessLaunchInfo.cpp:137
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::ProcessLaunchInfo::SetUpPtyRedirection
llvm::Error SetUpPtyRedirection()
Definition: ProcessLaunchInfo.cpp:214
lldb_private::GetLogIfAllCategoriesSet
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
lldb_private::ProcessLaunchInfo::GetFileActionAtIndex
const FileAction * GetFileActionAtIndex(size_t idx) const
Definition: ProcessLaunchInfo.cpp:111
lldb_private::ProcessLaunchInfo::m_scripted_process_dictionary_sp
StructuredData::DictionarySP m_scripted_process_dictionary_sp
Definition: ProcessLaunchInfo.h:190
lldb_private::Args::GetShellSafeArgument
static std::string GetShellSafeArgument(const FileSpec &shell, llvm::StringRef unsafe_arg)
Definition: Args.cpp:380
HostInfo.h
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:38
lldb_private::ProcessLaunchInfo::GetWorkingDirectory
const FileSpec & GetWorkingDirectory() const
Definition: ProcessLaunchInfo.cpp:125
lldb_private::ProcessLaunchInfo::SetLaunchInSeparateProcessGroup
void SetLaunchInSeparateProcessGroup(bool separate)
Definition: ProcessLaunchInfo.cpp:152
lldb_private::ProcessLaunchInfo::m_resume_count
uint32_t m_resume_count
Definition: ProcessLaunchInfo.h:179
lldb_private::ProcessLaunchInfo::ProcessLaunchInfo
ProcessLaunchInfo()
Definition: ProcessLaunchInfo.cpp:31
lldb_private::FileSpec::Clear
void Clear()
Clears the object state.
Definition: FileSpec.cpp:261
lldb_private::ProcessLaunchInfo::SetMonitorProcessCallback
void SetMonitorProcessCallback(const Host::MonitorChildProcessCallback &callback, bool monitor_signals)
Definition: ProcessLaunchInfo.cpp:180
lldb_private::ProcessLaunchInfo::GetProcessPluginName
const char * GetProcessPluginName() const
Definition: ProcessLaunchInfo.cpp:133
lldb_private::Status
Definition: Status.h:44
lldb_private::FileSpec::IsRelative
bool IsRelative() const
Returns true if the filespec represents a relative path.
Definition: FileSpec.cpp:475
uint32_t
lldb_private::Args::GetConstArgumentVector
const char ** GetConstArgumentVector() const
Gets the argument vector.
Definition: Args.cpp:275
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
lldb_private::ProcessLaunchInfo::GetShell
const FileSpec & GetShell() const
Definition: ProcessLaunchInfo.cpp:141
lldb_private::ProcessLaunchInfo::m_shell
FileSpec m_shell
Definition: ProcessLaunchInfo.h:175
lldb_private::ProcessLaunchInfo::m_hijack_listener_sp
lldb::ListenerSP m_hijack_listener_sp
Definition: ProcessLaunchInfo.h:186
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:242
lldb_private::ProcessLaunchInfo::AppendOpenFileAction
bool AppendOpenFileAction(int fd, const FileSpec &file_spec, bool read, bool write)
Definition: ProcessLaunchInfo.cpp:91
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private::FileSystem::Instance
static FileSystem & Instance()
Definition: common/FileSystem.cpp:45
lldb_private::ProcessInfo::GetArchitecture
ArchSpec & GetArchitecture()
Definition: ProcessInfo.h:61
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
lldb_private::ProcessLaunchInfo::MonitorProcess
bool MonitorProcess() const
Definition: ProcessLaunchInfo.cpp:193
lldb_private::Flags::Set
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
Definition: Flags.h:73
lldb_private::ProcessLaunchInfo::SetResumeCount
void SetResumeCount(uint32_t c)
Definition: ProcessLaunchInfo.h:82
lldb_private::Log
Definition: Log.h:49
lldb_private::Stream::PutCString
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
lldb_private::ProcessLaunchInfo::m_plugin_name
std::string m_plugin_name
Definition: ProcessLaunchInfo.h:174
FileAction.h
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
lldb_private::ProcessLaunchInfo::m_file_actions
std::vector< FileAction > m_file_actions
Definition: ProcessLaunchInfo.h:177
lldb
Definition: SBAddress.h:15
LIBLLDB_LOG_PROCESS
#define LIBLLDB_LOG_PROCESS
Definition: Logging.h:15
lldb_private::ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell
bool ConvertArgumentsForLaunchingInShell(Status &error, bool will_debug, bool first_arg_is_full_shell_command, uint32_t num_resumes)
Definition: ProcessLaunchInfo.cpp:247
lldb_private::ProcessLaunchInfo::m_listener_sp
lldb::ListenerSP m_listener_sp
Definition: ProcessLaunchInfo.h:185