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 <climits>
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_monitor_callback(nullptr),
34  m_listener_sp(), m_hijack_listener_sp(), m_scripted_process_class_name(),
35  m_scripted_process_dictionary_sp() {}
36 
38  const FileSpec &stdout_file_spec,
39  const FileSpec &stderr_file_spec,
40  const FileSpec &working_directory,
41  uint32_t launch_flags)
42  : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
43  m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0),
44  m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr),
45  m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(),
46  m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {
47  if (stdin_file_spec) {
48  FileAction file_action;
49  const bool read = true;
50  const bool write = false;
51  if (file_action.Open(STDIN_FILENO, stdin_file_spec, read, write))
52  AppendFileAction(file_action);
53  }
54  if (stdout_file_spec) {
55  FileAction file_action;
56  const bool read = false;
57  const bool write = true;
58  if (file_action.Open(STDOUT_FILENO, stdout_file_spec, read, write))
59  AppendFileAction(file_action);
60  }
61  if (stderr_file_spec) {
62  FileAction file_action;
63  const bool read = false;
64  const bool write = true;
65  if (file_action.Open(STDERR_FILENO, stderr_file_spec, read, write))
66  AppendFileAction(file_action);
67  }
68  if (working_directory)
69  SetWorkingDirectory(working_directory);
70 }
71 
73  FileAction file_action;
74  if (file_action.Close(fd)) {
75  AppendFileAction(file_action);
76  return true;
77  }
78  return false;
79 }
80 
82  FileAction file_action;
83  if (file_action.Duplicate(fd, dup_fd)) {
84  AppendFileAction(file_action);
85  return true;
86  }
87  return false;
88 }
89 
90 bool ProcessLaunchInfo::AppendOpenFileAction(int fd, const FileSpec &file_spec,
91  bool read, bool write) {
92  FileAction file_action;
93  if (file_action.Open(fd, file_spec, read, write)) {
94  AppendFileAction(file_action);
95  return true;
96  }
97  return false;
98 }
99 
101  bool write) {
102  FileAction file_action;
103  if (file_action.Open(fd, FileSpec(FileSystem::DEV_NULL), read, write)) {
104  AppendFileAction(file_action);
105  return true;
106  }
107  return false;
108 }
109 
111  if (idx < m_file_actions.size())
112  return &m_file_actions[idx];
113  return nullptr;
114 }
115 
117  for (size_t idx = 0, count = m_file_actions.size(); idx < count; ++idx) {
118  if (m_file_actions[idx].GetFD() == fd)
119  return &m_file_actions[idx];
120  }
121  return nullptr;
122 }
123 
125  return m_working_dir;
126 }
127 
129  m_working_dir = working_dir;
130 }
131 
133  return (m_plugin_name.empty() ? nullptr : m_plugin_name.c_str());
134 }
135 
136 void ProcessLaunchInfo::SetProcessPluginName(llvm::StringRef plugin) {
137  m_plugin_name = std::string(plugin);
138 }
139 
140 const FileSpec &ProcessLaunchInfo::GetShell() const { return m_shell; }
141 
143  m_shell = shell;
144  if (m_shell) {
146  m_flags.Set(lldb::eLaunchFlagLaunchInShell);
147  } else
148  m_flags.Clear(lldb::eLaunchFlagLaunchInShell);
149 }
150 
152  if (separate)
153  m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
154  else
155  m_flags.Clear(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
156 }
157 
159  if (expand)
160  m_flags.Set(lldb::eLaunchFlagShellExpandArguments);
161  else
162  m_flags.Clear(lldb::eLaunchFlagShellExpandArguments);
163 }
164 
168  m_plugin_name.clear();
169  m_shell.Clear();
170  m_flags.Clear();
171  m_file_actions.clear();
172  m_resume_count = 0;
173  m_listener_sp.reset();
174  m_hijack_listener_sp.reset();
177 }
178 
180  const Host::MonitorChildProcessCallback &callback, bool monitor_signals) {
181  m_monitor_callback = callback;
182  m_monitor_signals = monitor_signals;
183 }
184 
185 bool ProcessLaunchInfo::NoOpMonitorCallback(lldb::pid_t pid, bool exited, int signal, int status) {
187  LLDB_LOG(log, "pid = {0}, exited = {1}, signal = {2}, status = {3}", pid,
188  exited, signal, status);
189  return true;
190 }
191 
194  llvm::Expected<HostThread> maybe_thread =
197  if (!maybe_thread)
199  "failed to launch host thread: {}",
200  llvm::toString(maybe_thread.takeError()));
201  return true;
202  }
203  return false;
204 }
205 
207  if (enable)
208  m_flags.Set(lldb::eLaunchFlagDetachOnError);
209  else
210  m_flags.Clear(lldb::eLaunchFlagDetachOnError);
211 }
212 
215  LLDB_LOG(log, "Generating a pty to use for stdin/out/err");
216 
217  int open_flags = O_RDWR | O_NOCTTY;
218 #if !defined(_WIN32)
219  // We really shouldn't be specifying platform specific flags that are
220  // intended for a system call in generic code. But this will have to
221  // do for now.
222  open_flags |= O_CLOEXEC;
223 #endif
224  if (llvm::Error Err = m_pty->OpenFirstAvailablePrimary(open_flags))
225  return Err;
226 
227  const FileSpec secondary_file_spec(m_pty->GetSecondaryName());
228 
229  // Only use the secondary tty if we don't have anything specified for
230  // input and don't have an action for stdin
231  if (GetFileActionForFD(STDIN_FILENO) == nullptr)
232  AppendOpenFileAction(STDIN_FILENO, secondary_file_spec, true, false);
233 
234  // Only use the secondary tty if we don't have anything specified for
235  // output and don't have an action for stdout
236  if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
237  AppendOpenFileAction(STDOUT_FILENO, secondary_file_spec, false, true);
238 
239  // Only use the secondary tty if we don't have anything specified for
240  // error and don't have an action for stderr
241  if (GetFileActionForFD(STDERR_FILENO) == nullptr)
242  AppendOpenFileAction(STDERR_FILENO, secondary_file_spec, false, true);
243  return llvm::Error::success();
244 }
245 
247  Status &error, bool will_debug, bool first_arg_is_full_shell_command,
248  uint32_t num_resumes) {
249  error.Clear();
250 
251  if (GetFlags().Test(eLaunchFlagLaunchInShell)) {
252  if (m_shell) {
253  std::string shell_executable = m_shell.GetPath();
254 
255  const char **argv = GetArguments().GetConstArgumentVector();
256  if (argv == nullptr || argv[0] == nullptr)
257  return false;
258  Args shell_arguments;
259  shell_arguments.AppendArgument(shell_executable);
260  const llvm::Triple &triple = GetArchitecture().GetTriple();
261  if (triple.getOS() == llvm::Triple::Win32 &&
262  !triple.isWindowsCygwinEnvironment())
263  shell_arguments.AppendArgument(llvm::StringRef("/C"));
264  else
265  shell_arguments.AppendArgument(llvm::StringRef("-c"));
266 
267  StreamString shell_command;
268  if (will_debug) {
269  // Add a modified PATH environment variable in case argv[0] is a
270  // relative path.
271  const char *argv0 = argv[0];
272  FileSpec arg_spec(argv0);
273  if (arg_spec.IsRelative()) {
274  // We have a relative path to our executable which may not work if we
275  // just try to run "a.out" (without it being converted to "./a.out")
276  FileSpec working_dir = GetWorkingDirectory();
277  // Be sure to put quotes around PATH's value in case any paths have
278  // spaces...
279  std::string new_path("PATH=\"");
280  const size_t empty_path_len = new_path.size();
281 
282  if (working_dir) {
283  new_path += working_dir.GetPath();
284  } else {
285  llvm::SmallString<64> cwd;
286  if (! llvm::sys::fs::current_path(cwd))
287  new_path += cwd;
288  }
289  std::string curr_path;
290  if (HostInfo::GetEnvironmentVar("PATH", curr_path)) {
291  if (new_path.size() > empty_path_len)
292  new_path += ':';
293  new_path += curr_path;
294  }
295  new_path += "\" ";
296  shell_command.PutCString(new_path);
297  }
298 
299  if (triple.getOS() != llvm::Triple::Win32 ||
300  triple.isWindowsCygwinEnvironment())
301  shell_command.PutCString("exec");
302 
303  // Only Apple supports /usr/bin/arch being able to specify the
304  // architecture
305  if (GetArchitecture().IsValid() && // Valid architecture
306  GetArchitecture().GetTriple().getVendor() ==
307  llvm::Triple::Apple && // Apple only
308  GetArchitecture().GetCore() !=
309  ArchSpec::eCore_x86_64_x86_64h) // Don't do this for x86_64h
310  {
311  shell_command.Printf(" /usr/bin/arch -arch %s",
312  GetArchitecture().GetArchitectureName());
313  // Set the resume count to 2:
314  // 1 - stop in shell
315  // 2 - stop in /usr/bin/arch
316  // 3 - then we will stop in our program
317  SetResumeCount(num_resumes + 1);
318  } else {
319  // Set the resume count to 1:
320  // 1 - stop in shell
321  // 2 - then we will stop in our program
322  SetResumeCount(num_resumes);
323  }
324  }
325 
326  if (first_arg_is_full_shell_command) {
327  // There should only be one argument that is the shell command itself
328  // to be used as is
329  if (argv[0] && !argv[1])
330  shell_command.Printf("%s", argv[0]);
331  else
332  return false;
333  } else {
334  for (size_t i = 0; argv[i] != nullptr; ++i) {
335  std::string safe_arg = Args::GetShellSafeArgument(m_shell, argv[i]);
336  // Add a space to separate this arg from the previous one.
337  shell_command.PutCString(" ");
338  shell_command.PutCString(safe_arg);
339  }
340  }
341  shell_arguments.AppendArgument(shell_command.GetString());
343  m_arguments = shell_arguments;
344  return true;
345  } else {
346  error.SetErrorString("invalid shell path");
347  }
348  } else {
349  error.SetErrorString("not launching in shell");
350  }
351  return false;
352 }
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:81
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:128
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:142
ProcessLaunchInfo.h
lldb_private::FileAction::Close
bool Close(int fd)
Definition: FileAction.cpp:51
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:116
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:158
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:185
lldb_private::FileAction::Duplicate
bool Duplicate(int fd, int dup_fd)
Definition: FileAction.cpp:60
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:72
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:32
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:100
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:32
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:165
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:206
StreamString.h
lldb_private::ProcessLaunchInfo::SetProcessPluginName
void SetProcessPluginName(llvm::StringRef plugin)
Definition: ProcessLaunchInfo.cpp:136
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::ProcessLaunchInfo::SetUpPtyRedirection
llvm::Error SetUpPtyRedirection()
Definition: ProcessLaunchInfo.cpp:213
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:110
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:39
lldb_private::ProcessLaunchInfo::GetWorkingDirectory
const FileSpec & GetWorkingDirectory() const
Definition: ProcessLaunchInfo.cpp:124
lldb_private::ProcessLaunchInfo::SetLaunchInSeparateProcessGroup
void SetLaunchInSeparateProcessGroup(bool separate)
Definition: ProcessLaunchInfo.cpp:151
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:179
lldb_private::ProcessLaunchInfo::GetProcessPluginName
const char * GetProcessPluginName() const
Definition: ProcessLaunchInfo.cpp:132
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:140
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:90
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:192
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:246
lldb_private::ProcessLaunchInfo::m_listener_sp
lldb::ListenerSP m_listener_sp
Definition: ProcessLaunchInfo.h:185