LLDB  mainline
DarwinProcessLauncher.cpp
Go to the documentation of this file.
1 //===-- DarwinProcessLauncher.cpp -------------------------------*- 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 //
10 // DarwinProcessLauncher.cpp
11 // lldb
12 //
13 // Created by Todd Fiala on 8/30/16.
14 //
15 //
16 
17 #include "DarwinProcessLauncher.h"
18 
19 // C includes
20 #include <spawn.h>
21 #include <sys/ptrace.h>
22 #include <sys/stat.h>
23 #include <sys/sysctl.h>
24 
25 #ifndef _POSIX_SPAWN_DISABLE_ASLR
26 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
27 #endif
28 
29 // LLDB includes
30 #include "lldb/lldb-enumerations.h"
31 
33 #include "lldb/Target/ProcessLaunchInfo.h"
34 #include "lldb/Utility/Log.h"
35 #include "lldb/Utility/Status.h"
37 #include "llvm/Support/Errno.h"
38 
39 #include "CFBundle.h"
40 #include "CFString.h"
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 using namespace lldb_private::process_darwin;
46 
47 namespace {
48 static LaunchFlavor g_launch_flavor = LaunchFlavor::Default;
49 }
50 
51 namespace lldb_private {
52 namespace darwin_process_launcher {
53 
55  int mib[CTL_MAXNAME] = {
56  0,
57  };
58  size_t len = CTL_MAXNAME;
59  if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
60  return 0;
61 
62  mib[len] = pid;
63  len++;
64 
65  cpu_type_t cpu;
66  size_t cpu_len = sizeof(cpu);
67  if (::sysctl(mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0))
68  cpu = 0;
69  return cpu;
70 }
71 
72 static bool ResolveExecutablePath(const char *path, char *resolved_path,
73  size_t resolved_path_size) {
74  if (path == NULL || path[0] == '\0')
75  return false;
76 
77  char max_path[PATH_MAX];
78  std::string result;
79  CFString::GlobPath(path, result);
80 
81  if (result.empty())
82  result = path;
83 
84  struct stat path_stat;
85  if (::stat(path, &path_stat) == 0) {
86  if ((path_stat.st_mode & S_IFMT) == S_IFDIR) {
87  CFBundle bundle(path);
89  if (url.get()) {
90  if (::CFURLGetFileSystemRepresentation(
91  url.get(), true, (UInt8 *)resolved_path, resolved_path_size))
92  return true;
93  }
94  }
95  }
96 
97  if (realpath(path, max_path)) {
98  // Found the path relatively...
99  ::strncpy(resolved_path, max_path, resolved_path_size);
100  return strlen(resolved_path) + 1 < resolved_path_size;
101  } else {
102  // Not a relative path, check the PATH environment variable if the
103  const char *PATH = getenv("PATH");
104  if (PATH) {
105  const char *curr_path_start = PATH;
106  const char *curr_path_end;
107  while (curr_path_start && *curr_path_start) {
108  curr_path_end = strchr(curr_path_start, ':');
109  if (curr_path_end == NULL) {
110  result.assign(curr_path_start);
111  curr_path_start = NULL;
112  } else if (curr_path_end > curr_path_start) {
113  size_t len = curr_path_end - curr_path_start;
114  result.assign(curr_path_start, len);
115  curr_path_start += len + 1;
116  } else
117  break;
118 
119  result += '/';
120  result += path;
121  struct stat s;
122  if (stat(result.c_str(), &s) == 0) {
123  ::strncpy(resolved_path, result.c_str(), resolved_path_size);
124  return result.size() + 1 < resolved_path_size;
125  }
126  }
127  }
128  }
129  return false;
130 }
131 
132 // TODO check if we have a general purpose fork and exec. We may be
133 // able to get rid of this entirely.
134 static Status ForkChildForPTraceDebugging(const char *path, char const *argv[],
135  char const *envp[], ::pid_t *pid,
136  int *pty_fd) {
137  Status error;
138  if (!path || !argv || !envp || !pid || !pty_fd) {
139  error.SetErrorString("invalid arguments");
140  return error;
141  }
142 
143  // Use a fork that ties the child process's stdin/out/err to a pseudo
144  // terminal so we can read it in our MachProcess::STDIOThread as unbuffered
145  // io.
146  PseudoTerminal pty;
147  char fork_error[256];
148  memset(fork_error, 0, sizeof(fork_error));
149  *pid = static_cast<::pid_t>(pty.Fork(fork_error, sizeof(fork_error)));
150  if (*pid < 0) {
151  // Status during fork.
152  *pid = static_cast<::pid_t>(LLDB_INVALID_PROCESS_ID);
153  error.SetErrorStringWithFormat("%s(): fork failed: %s", __FUNCTION__,
154  fork_error);
155  return error;
156  } else if (pid == 0) {
157  // Child process
158 
159  // Debug this process.
160  ::ptrace(PT_TRACE_ME, 0, 0, 0);
161 
162  // Get BSD signals as mach exceptions.
163  ::ptrace(PT_SIGEXC, 0, 0, 0);
164 
165  // If our parent is setgid, lets make sure we don't inherit those extra
166  // powers due to nepotism.
167  if (::setgid(getgid()) == 0) {
168  // Let the child have its own process group. We need to execute this call
169  // in both the child and parent to avoid a race condition between the two
170  // processes.
171 
172  // Set the child process group to match its pid.
173  ::setpgid(0, 0);
174 
175  // Sleep a bit to before the exec call.
176  ::sleep(1);
177 
178  // Turn this process into the given executable.
179  ::execv(path, (char *const *)argv);
180  }
181  // Exit with error code. Child process should have taken over in above exec
182  // call and if the exec fails it will exit the child process below.
183  ::exit(127);
184  } else {
185  // Parent process
186  // Let the child have its own process group. We need to execute this call
187  // in both the child and parent to avoid a race condition between the two
188  // processes.
189 
190  // Set the child process group to match its pid
191  ::setpgid(*pid, *pid);
192  if (pty_fd) {
193  // Release our master pty file descriptor so the pty class doesn't close
194  // it and so we can continue to use it in our STDIO thread
195  *pty_fd = pty.ReleaseMasterFileDescriptor();
196  }
197  }
198  return error;
199 }
200 
201 static Status
203  posix_spawn_file_actions_t *file_actions) {
204  Status error;
205 
206  // Log it.
208  if (log) {
209  StreamString stream;
210  stream.PutCString("converting file action for posix_spawn(): ");
211  action.Dump(stream);
212  stream.Flush();
213  log->PutCString(stream.GetString().c_str());
214  }
215 
216  // Validate args.
217  if (!file_actions) {
218  error.SetErrorString("mandatory file_actions arg is null");
219  return error;
220  }
221 
222  // Build the posix file action.
223  switch (action.GetAction()) {
224  case FileAction::eFileActionOpen: {
225  const int error_code = ::posix_spawn_file_actions_addopen(
226  file_actions, action.GetFD(), action.GetPath(),
227  action.GetActionArgument(), 0);
228  if (error_code != 0) {
229  error.SetError(error_code, eErrorTypePOSIX);
230  return error;
231  }
232  break;
233  }
234 
235  case FileAction::eFileActionClose: {
236  const int error_code =
237  ::posix_spawn_file_actions_addclose(file_actions, action.GetFD());
238  if (error_code != 0) {
239  error.SetError(error_code, eErrorTypePOSIX);
240  return error;
241  }
242  break;
243  }
244 
245  case FileAction::eFileActionDuplicate: {
246  const int error_code = ::posix_spawn_file_actions_adddup2(
247  file_actions, action.GetFD(), action.GetActionArgument());
248  if (error_code != 0) {
249  error.SetError(error_code, eErrorTypePOSIX);
250  return error;
251  }
252  break;
253  }
254 
255  case FileAction::eFileActionNone:
256  default:
257  if (log)
258  log->Printf("%s(): unsupported file action %u", __FUNCTION__,
259  action.GetAction());
260  break;
261  }
262 
263  return error;
264 }
265 
267  ProcessLaunchInfo &launch_info,
268  ::pid_t *pid,
269  cpu_type_t *actual_cpu_type) {
270  Status error;
272 
273  if (!pid) {
274  error.SetErrorStringWithFormat("%s(): pid arg cannot be null",
275  __FUNCTION__);
276  return error;
277  }
278 
279  posix_spawnattr_t attr;
280  short flags;
281  if (log) {
282  StreamString stream;
283  stream.Printf("%s(path='%s',...)\n", __FUNCTION__, path);
284  launch_info.Dump(stream, nullptr);
285  stream.Flush();
286  log->PutCString(stream.GetString().c_str());
287  }
288 
289  int error_code;
290  if ((error_code = ::posix_spawnattr_init(&attr)) != 0) {
291  if (log)
292  log->Printf("::posix_spawnattr_init(&attr) failed");
293  error.SetError(error_code, eErrorTypePOSIX);
294  return error;
295  }
296 
297  // Ensure we clean up the spawnattr structure however we exit this function.
298  std::unique_ptr<posix_spawnattr_t, int (*)(posix_spawnattr_t *)> spawnattr_up(
299  &attr, ::posix_spawnattr_destroy);
300 
301  flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF |
302  POSIX_SPAWN_SETSIGMASK;
303  if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR))
304  flags |= _POSIX_SPAWN_DISABLE_ASLR;
305 
306  sigset_t no_signals;
307  sigset_t all_signals;
308  sigemptyset(&no_signals);
309  sigfillset(&all_signals);
310  ::posix_spawnattr_setsigmask(&attr, &no_signals);
311  ::posix_spawnattr_setsigdefault(&attr, &all_signals);
312 
313  if ((error_code = ::posix_spawnattr_setflags(&attr, flags)) != 0) {
314  LLDB_LOG(log,
315  "::posix_spawnattr_setflags(&attr, "
316  "POSIX_SPAWN_START_SUSPENDED{0}) failed: {1}",
317  flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR"
318  : "",
319  llvm::sys::StrError(error_code));
320  error.SetError(error_code, eErrorTypePOSIX);
321  return error;
322  }
323 
324 #if !defined(__arm__)
325 
326  // We don't need to do this for ARM, and we really shouldn't now that we have
327  // multiple CPU subtypes and no posix_spawnattr call that allows us to set
328  // which CPU subtype to launch...
329  cpu_type_t desired_cpu_type = launch_info.GetArchitecture().GetMachOCPUType();
330  if (desired_cpu_type != LLDB_INVALID_CPUTYPE) {
331  size_t ocount = 0;
332  error_code =
333  ::posix_spawnattr_setbinpref_np(&attr, 1, &desired_cpu_type, &ocount);
334  if (error_code != 0) {
335  LLDB_LOG(log,
336  "::posix_spawnattr_setbinpref_np(&attr, 1, "
337  "cpu_type = {0:x8}, count => {1}): {2}",
338  desired_cpu_type, ocount, llvm::sys::StrError(error_code));
339  error.SetError(error_code, eErrorTypePOSIX);
340  return error;
341  }
342  if (ocount != 1) {
343  error.SetErrorStringWithFormat("posix_spawnattr_setbinpref_np "
344  "did not set the expected number "
345  "of cpu_type entries: expected 1 "
346  "but was %zu",
347  ocount);
348  return error;
349  }
350  }
351 #endif
352 
353  posix_spawn_file_actions_t file_actions;
354  if ((error_code = ::posix_spawn_file_actions_init(&file_actions)) != 0) {
355  LLDB_LOG(log, "::posix_spawn_file_actions_init(&file_actions) failed: {0}",
356  llvm::sys::StrError(error_code));
357  error.SetError(error_code, eErrorTypePOSIX);
358  return error;
359  }
360 
361  // Ensure we clean up file actions however we exit this. When the
362  // file_actions_up below goes out of scope, we'll get our file action
363  // cleanup.
364  std::unique_ptr<posix_spawn_file_actions_t,
365  int (*)(posix_spawn_file_actions_t *)>
366  file_actions_up(&file_actions, ::posix_spawn_file_actions_destroy);
367 
368  // We assume the caller has setup the file actions appropriately. We are not
369  // in the business of figuring out what we really need here. lldb-server will
370  // have already called FinalizeFileActions() as well to button these up
371  // properly.
372  const size_t num_actions = launch_info.GetNumFileActions();
373  for (size_t action_index = 0; action_index < num_actions; ++action_index) {
374  const FileAction *const action =
375  launch_info.GetFileActionAtIndex(action_index);
376  if (!action)
377  continue;
378 
379  error = CreatePosixSpawnFileAction(*action, &file_actions);
380  if (!error.Success()) {
381  if (log)
382  log->Printf("%s(): error converting FileAction to posix_spawn "
383  "file action: %s",
384  __FUNCTION__, error.AsCString());
385  return error;
386  }
387  }
388 
389  // TODO: Verify if we can set the working directory back immediately
390  // after the posix_spawnp call without creating a race condition???
391  const char *const working_directory =
392  launch_info.GetWorkingDirectory().GetCString();
393  if (working_directory && working_directory[0])
394  ::chdir(working_directory);
395 
396  auto argv = launch_info.GetArguments().GetArgumentVector();
397  auto envp = launch_info.GetEnvironmentEntries().GetArgumentVector();
398  error_code = ::posix_spawnp(pid, path, &file_actions, &attr,
399  (char *const *)argv, (char *const *)envp);
400  if (error_code != 0) {
401  LLDB_LOG(log,
402  "::posix_spawnp(pid => {0}, path = '{1}', file_actions "
403  "= {2}, attr = {3}, argv = {4}, envp = {5}) failed: {6}",
404  pid, path, &file_actions, &attr, argv, envp,
405  llvm::sys::StrError(error_code));
406  error.SetError(error_code, eErrorTypePOSIX);
407  return error;
408  }
409 
410  // Validate we got a pid.
411  if (pid == LLDB_INVALID_PROCESS_ID) {
412  error.SetErrorString("posix_spawn() did not indicate a failure but it "
413  "failed to return a pid, aborting.");
414  return error;
415  }
416 
417  if (actual_cpu_type) {
418  *actual_cpu_type = GetCPUTypeForLocalProcess(*pid);
419  if (log)
420  log->Printf("%s(): cpu type for launched process pid=%i: "
421  "cpu_type=0x%8.8x",
422  __FUNCTION__, *pid, *actual_cpu_type);
423  }
424 
425  return error;
426 }
427 
428 Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
429  LaunchFlavor *launch_flavor) {
430  Status error;
432 
433  if (!launch_flavor) {
434  error.SetErrorString("mandatory launch_flavor field was null");
435  return error;
436  }
437 
438  if (log) {
439  StreamString stream;
440  stream.Printf("NativeProcessDarwin::%s(): launching with the "
441  "following launch info:",
442  __FUNCTION__);
443  launch_info.Dump(stream, nullptr);
444  stream.Flush();
445  log->PutCString(stream.GetString().c_str());
446  }
447 
448  // Retrieve the binary name given to us.
449  char given_path[PATH_MAX];
450  given_path[0] = '\0';
451  launch_info.GetExecutableFile().GetPath(given_path, sizeof(given_path));
452 
453  // Determine the manner in which we'll launch.
454  *launch_flavor = g_launch_flavor;
455  if (*launch_flavor == LaunchFlavor::Default) {
456  // Our default launch method is posix spawn
457  *launch_flavor = LaunchFlavor::PosixSpawn;
458 #if defined WITH_FBS
459  // Check if we have an app bundle, if so launch using BackBoard Services.
460  if (strstr(given_path, ".app")) {
461  *launch_flavor = eLaunchFlavorFBS;
462  }
463 #elif defined WITH_BKS
464  // Check if we have an app bundle, if so launch using BackBoard Services.
465  if (strstr(given_path, ".app")) {
466  *launch_flavor = eLaunchFlavorBKS;
467  }
468 #elif defined WITH_SPRINGBOARD
469  // Check if we have an app bundle, if so launch using SpringBoard.
470  if (strstr(given_path, ".app")) {
471  *launch_flavor = eLaunchFlavorSpringBoard;
472  }
473 #endif
474  }
475 
476  // Attempt to resolve the binary name to an absolute path.
477  char resolved_path[PATH_MAX];
478  resolved_path[0] = '\0';
479 
480  if (log)
481  log->Printf("%s(): attempting to resolve given binary path: \"%s\"",
482  __FUNCTION__, given_path);
483 
484  // If we fail to resolve the path to our executable, then just use what we
485  // were given and hope for the best
486  if (!ResolveExecutablePath(given_path, resolved_path,
487  sizeof(resolved_path))) {
488  if (log)
489  log->Printf("%s(): failed to resolve binary path, using "
490  "what was given verbatim and hoping for the best",
491  __FUNCTION__);
492  ::strncpy(resolved_path, given_path, sizeof(resolved_path));
493  } else {
494  if (log)
495  log->Printf("%s(): resolved given binary path to: \"%s\"", __FUNCTION__,
496  resolved_path);
497  }
498 
499  char launch_err_str[PATH_MAX];
500  launch_err_str[0] = '\0';
501 
502  // TODO figure out how to handle QSetProcessEvent
503  // const char *process_event = ctx.GetProcessEvent();
504 
505  // Ensure the binary is there.
506  struct stat path_stat;
507  if (::stat(resolved_path, &path_stat) == -1) {
508  error.SetErrorToErrno();
509  return error;
510  }
511 
512  // Fork a child process for debugging
513  // state_callback(eStateLaunching);
514 
515  const auto argv = launch_info.GetArguments().GetConstArgumentVector();
516  const auto envp =
517  launch_info.GetEnvironmentEntries().GetConstArgumentVector();
518 
519  switch (*launch_flavor) {
520  case LaunchFlavor::ForkExec: {
522  error = ForkChildForPTraceDebugging(resolved_path, argv, envp, &pid,
523  pty_master_fd);
524  if (error.Success()) {
525  launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
526  } else {
527  // Reset any variables that might have been set during a failed launch
528  // attempt.
529  if (pty_master_fd)
530  *pty_master_fd = -1;
531 
532  // We're done.
533  return error;
534  }
535  } break;
536 
537 #ifdef WITH_FBS
538  case LaunchFlavor::FBS: {
539  const char *app_ext = strstr(path, ".app");
540  if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) {
541  std::string app_bundle_path(path, app_ext + strlen(".app"));
542  m_flags |= eMachProcessFlagsUsingFBS;
543  if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp,
544  no_stdio, disable_aslr, event_data,
545  launch_err) != 0)
546  return m_pid; // A successful SBLaunchForDebug() returns and assigns a
547  // non-zero m_pid.
548  else
549  break; // We tried a FBS launch, but didn't succeed lets get out
550  }
551  } break;
552 #endif
553 
554 #ifdef WITH_BKS
555  case LaunchFlavor::BKS: {
556  const char *app_ext = strstr(path, ".app");
557  if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) {
558  std::string app_bundle_path(path, app_ext + strlen(".app"));
559  m_flags |= eMachProcessFlagsUsingBKS;
560  if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp,
561  no_stdio, disable_aslr, event_data,
562  launch_err) != 0)
563  return m_pid; // A successful SBLaunchForDebug() returns and assigns a
564  // non-zero m_pid.
565  else
566  break; // We tried a BKS launch, but didn't succeed lets get out
567  }
568  } break;
569 #endif
570 
571 #ifdef WITH_SPRINGBOARD
572  case LaunchFlavor::SpringBoard: {
573  // .../whatever.app/whatever ?
574  // Or .../com.apple.whatever.app/whatever -- be careful of ".app" in
575  // "com.apple.whatever" here
576  const char *app_ext = strstr(path, ".app/");
577  if (app_ext == NULL) {
578  // .../whatever.app ?
579  int len = strlen(path);
580  if (len > 5) {
581  if (strcmp(path + len - 4, ".app") == 0) {
582  app_ext = path + len - 4;
583  }
584  }
585  }
586  if (app_ext) {
587  std::string app_bundle_path(path, app_ext + strlen(".app"));
588  if (SBLaunchForDebug(app_bundle_path.c_str(), argv, envp, no_stdio,
589  disable_aslr, launch_err) != 0)
590  return m_pid; // A successful SBLaunchForDebug() returns and assigns a
591  // non-zero m_pid.
592  else
593  break; // We tried a springboard launch, but didn't succeed lets get out
594  }
595  } break;
596 #endif
597 
598  case LaunchFlavor::PosixSpawn: {
600 
601  // Retrieve paths for stdin/stdout/stderr.
602  cpu_type_t actual_cpu_type = 0;
603  error = PosixSpawnChildForPTraceDebugging(resolved_path, launch_info, &pid,
604  &actual_cpu_type);
605  if (error.Success()) {
606  launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
607  if (pty_master_fd)
608  *pty_master_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
609  } else {
610  // Reset any variables that might have been set during a failed launch
611  // attempt.
612  if (pty_master_fd)
613  *pty_master_fd = -1;
614 
615  // We're done.
616  return error;
617  }
618  break;
619  }
620 
621  default:
622  // Invalid launch flavor.
623  error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): unknown "
624  "launch flavor %d",
625  __FUNCTION__, (int)*launch_flavor);
626  return error;
627  }
628 
629  if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
630  // If we don't have a valid process ID and no one has set the error, then
631  // return a generic error.
632  if (error.Success())
633  error.SetErrorStringWithFormat("%s(): failed to launch, no reason "
634  "specified",
635  __FUNCTION__);
636  }
637 
638  // We're done with the launch side of the operation.
639  return error;
640 }
641 }
642 } // namespaces
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
void Flush() override
Flush the stream.
#define LIBLLDB_LOG_PROCESS
Definition: Logging.h:15
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd, LaunchFlavor *launch_flavor)
Launches a process for debugging.
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:92
void Dump(Stream &stream) const
Definition: FileAction.cpp:71
char ** GetArgumentVector()
Gets the argument vector.
Definition: Args.cpp:268
lldb::pid_t Fork(char *error_str, size_t error_len)
Fork a child process that uses pseudo terminals for its stdio.
void SetProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:70
static Status ForkChildForPTraceDebugging(const char *path, char const *argv[], char const *envp[], ::pid_t *pid, int *pty_fd)
A pseudo terminal helper class.
Action GetAction() const
Definition: FileAction.h:38
static uint32_t GetCPUTypeForLocalProcess(::pid_t pid)
POSIX error codes.
#define LLDB_LOG(log,...)
Definition: Log.h:209
int ReleaseMasterFileDescriptor()
Release the master file descriptor.
char * realpath(const char *name, char *resolved)
Definition: Windows.cpp:90
void SetErrorToErrno()
Set the current error to errno.
Definition: Status.cpp:223
#define LLDB_INVALID_CPUTYPE
Definition: lldb-defines.h:104
int cpu_type_t
#define _POSIX_SPAWN_DISABLE_ASLR
bool Test(ValueType bit) const
Test a single flag bit.
Definition: Flags.h:107
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
uint32_t GetMachOCPUType() const
Definition: ArchSpec.cpp:694
llvm::StringRef GetString() const
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
FileSpec & GetExecutableFile()
Definition: ProcessInfo.h:43
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
ArchSpec & GetArchitecture()
Definition: ProcessInfo.h:62
bool Success() const
Test for success condition.
Definition: Status.cpp:287
llvm::StringRef GetPath() const
Definition: FileAction.cpp:29
const char * GetCString(bool denormalize=true) const
Definition: FileSpec.cpp:392
void Dump(Stream &s, Platform *platform) const
Definition: ProcessInfo.cpp:49
static const char * GlobPath(const char *path, std::string &expanded_path)
Definition: CFString.cpp:144
const FileSpec & GetWorkingDirectory() const
int void SetError(ValueType err, lldb::ErrorType type)
Set accesssor with an error value and type.
Definition: Status.cpp:216
void PutCString(const char *cstr)
Definition: Log.cpp:109
static Status CreatePosixSpawnFileAction(const FileAction &action, posix_spawn_file_actions_t *file_actions)
Definition: SBAddress.h:15
uint64_t pid_t
Definition: lldb-types.h:85
static Status PosixSpawnChildForPTraceDebugging(const char *path, ProcessLaunchInfo &launch_info, ::pid_t *pid, cpu_type_t *actual_cpu_type)
#define PATH_MAX
const char ** GetConstArgumentVector() const
Gets the argument vector.
Definition: Args.cpp:278
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
static bool ResolveExecutablePath(const char *path, char *resolved_path, size_t resolved_path_size)
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
int GetActionArgument() const
Definition: FileAction.h:40
const FileAction * GetFileActionAtIndex(size_t idx) const
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
CFURLRef CopyExecutableURL() const
Definition: CFBundle.cpp:63
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:68
An error handling class.
Definition: Status.h:44