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