LLDB  mainline
Host.mm
Go to the documentation of this file.
1 //===-- Host.mm -------------------------------------------------*- 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 #include "lldb/Host/Host.h"
10 #include "PosixSpawnResponsible.h"
11 
12 #include <AvailabilityMacros.h>
13 #include <TargetConditionals.h>
14 
15 #if TARGET_OS_OSX
16 #define __XPC_PRIVATE_H__
17 #include <xpc/xpc.h>
18 
19 #define LaunchUsingXPCRightName "com.apple.lldb.RootDebuggingXPCService"
20 
21 // These XPC messaging keys are used for communication between Host.mm and the
22 // XPC service.
23 #define LauncherXPCServiceAuthKey "auth-key"
24 #define LauncherXPCServiceArgPrefxKey "arg"
25 #define LauncherXPCServiceEnvPrefxKey "env"
26 #define LauncherXPCServiceCPUTypeKey "cpuType"
27 #define LauncherXPCServicePosixspawnFlagsKey "posixspawnFlags"
28 #define LauncherXPCServiceStdInPathKeyKey "stdInPath"
29 #define LauncherXPCServiceStdOutPathKeyKey "stdOutPath"
30 #define LauncherXPCServiceStdErrPathKeyKey "stdErrPath"
31 #define LauncherXPCServiceChildPIDKey "childPID"
32 #define LauncherXPCServiceErrorTypeKey "errorType"
33 #define LauncherXPCServiceCodeTypeKey "errorCode"
34 
35 #include <bsm/audit.h>
36 #include <bsm/audit_session.h>
37 #endif
38 
39 #include "llvm/Support/Host.h"
40 
41 #include <asl.h>
42 #include <crt_externs.h>
43 #include <cstdio>
44 #include <cstdlib>
45 #include <dlfcn.h>
46 #include <grp.h>
47 #include <libproc.h>
48 #include <pwd.h>
49 #include <spawn.h>
50 #include <sys/proc.h>
51 #include <sys/stat.h>
52 #include <sys/sysctl.h>
53 #include <sys/types.h>
54 #include <unistd.h>
55 
57 #include "lldb/Host/FileSystem.h"
58 #include "lldb/Host/HostInfo.h"
61 #include "lldb/Utility/ArchSpec.h"
62 #include "lldb/Utility/LLDBLog.h"
65 #include "lldb/Utility/Endian.h"
66 #include "lldb/Utility/FileSpec.h"
67 #include "lldb/Utility/Log.h"
72 #include "lldb/lldb-defines.h"
73 
74 #include "llvm/ADT/ScopeExit.h"
75 #include "llvm/Support/Errno.h"
76 #include "llvm/Support/FileSystem.h"
77 
78 #include "../cfcpp/CFCBundle.h"
79 #include "../cfcpp/CFCMutableArray.h"
80 #include "../cfcpp/CFCMutableDictionary.h"
81 #include "../cfcpp/CFCReleaser.h"
82 #include "../cfcpp/CFCString.h"
83 
84 #include <objc/objc-auto.h>
85 #include <os/log.h>
86 
87 #include <CoreFoundation/CoreFoundation.h>
88 #include <Foundation/Foundation.h>
89 
90 #ifndef _POSIX_SPAWN_DISABLE_ASLR
91 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
92 #endif
93 
94 extern "C" {
95 int __pthread_chdir(const char *path);
96 int __pthread_fchdir(int fildes);
97 }
98 
99 using namespace lldb;
100 using namespace lldb_private;
101 
102 static os_log_t g_os_log;
103 static std::once_flag g_os_log_once;
104 
105 void Host::SystemLog(llvm::StringRef message) {
106  if (__builtin_available(macos 10.12, iOS 10, tvOS 10, watchOS 3, *)) {
107  std::call_once(g_os_log_once, []() {
108  g_os_log = os_log_create("com.apple.dt.lldb", "lldb");
109  });
110  os_log(g_os_log, "%{public}s", message.str().c_str());
111  } else {
112  llvm::errs() << message;
113  }
114 }
115 
116 bool Host::GetBundleDirectory(const FileSpec &file,
117  FileSpec &bundle_directory) {
118 #if defined(__APPLE__)
119  if (FileSystem::Instance().IsDirectory(file)) {
120  char path[PATH_MAX];
121  if (file.GetPath(path, sizeof(path))) {
122  CFCBundle bundle(path);
123  if (bundle.GetPath(path, sizeof(path))) {
124  bundle_directory.SetFile(path, FileSpec::Style::native);
125  return true;
126  }
127  }
128  }
129 #endif
130  bundle_directory.Clear();
131  return false;
132 }
133 
134 bool Host::ResolveExecutableInBundle(FileSpec &file) {
135 #if defined(__APPLE__)
136  if (FileSystem::Instance().IsDirectory(file)) {
137  char path[PATH_MAX];
138  if (file.GetPath(path, sizeof(path))) {
139  CFCBundle bundle(path);
140  CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL());
141  if (url.get()) {
142  if (::CFURLGetFileSystemRepresentation(url.get(), YES, (UInt8 *)path,
143  sizeof(path))) {
144  file.SetFile(path, FileSpec::Style::native);
145  return true;
146  }
147  }
148  }
149  }
150 #endif
151  return false;
152 }
153 
154 #if TARGET_OS_OSX
155 
156 static void *AcceptPIDFromInferior(const char *connect_url) {
157  ConnectionFileDescriptor file_conn;
158  Status error;
159  if (file_conn.Connect(connect_url, &error) == eConnectionStatusSuccess) {
160  char pid_str[256];
161  ::memset(pid_str, 0, sizeof(pid_str));
162  ConnectionStatus status;
163  const size_t pid_str_len = file_conn.Read(
164  pid_str, sizeof(pid_str), std::chrono::seconds(0), status, NULL);
165  if (pid_str_len > 0) {
166  int pid = atoi(pid_str);
167  return (void *)(intptr_t)pid;
168  }
169  }
170  return NULL;
171 }
172 
173 const char *applscript_in_new_tty = "tell application \"Terminal\"\n"
174  " activate\n"
175  " do script \"/bin/bash -c '%s';exit\"\n"
176  "end tell\n";
177 
178 const char *applscript_in_existing_tty = "\
179 set the_shell_script to \"/bin/bash -c '%s';exit\"\n\
180 tell application \"Terminal\"\n\
181  repeat with the_window in (get windows)\n\
182  repeat with the_tab in tabs of the_window\n\
183  set the_tty to tty in the_tab\n\
184  if the_tty contains \"%s\" then\n\
185  if the_tab is not busy then\n\
186  set selected of the_tab to true\n\
187  set frontmost of the_window to true\n\
188  do script the_shell_script in the_tab\n\
189  return\n\
190  end if\n\
191  end if\n\
192  end repeat\n\
193  end repeat\n\
194  do script the_shell_script\n\
195 end tell\n";
196 
197 static Status
198 LaunchInNewTerminalWithAppleScript(const char *exe_path,
199  ProcessLaunchInfo &launch_info) {
200  Status error;
201  char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
202  if (::mktemp(unix_socket_name) == NULL) {
203  error.SetErrorString("failed to make temporary path for a unix socket");
204  return error;
205  }
206 
207  StreamString command;
208  FileSpec darwin_debug_file_spec = HostInfo::GetSupportExeDir();
209  if (!darwin_debug_file_spec) {
210  error.SetErrorString("can't locate the 'darwin-debug' executable");
211  return error;
212  }
213 
214  darwin_debug_file_spec.SetFilename("darwin-debug");
215 
216  if (!FileSystem::Instance().Exists(darwin_debug_file_spec)) {
217  error.SetErrorStringWithFormat(
218  "the 'darwin-debug' executable doesn't exists at '%s'",
219  darwin_debug_file_spec.GetPath().c_str());
220  return error;
221  }
222 
223  char launcher_path[PATH_MAX];
224  darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
225 
226  const ArchSpec &arch_spec = launch_info.GetArchitecture();
227  // Only set the architecture if it is valid and if it isn't Haswell (x86_64h).
228  if (arch_spec.IsValid() &&
229  arch_spec.GetCore() != ArchSpec::eCore_x86_64_x86_64h)
230  command.Printf("arch -arch %s ", arch_spec.GetArchitectureName());
231 
232  command.Printf(R"(\"%s\" --unix-socket=%s)", launcher_path, unix_socket_name);
233 
234  if (arch_spec.IsValid())
235  command.Printf(" --arch=%s", arch_spec.GetArchitectureName());
236 
237  FileSpec working_dir{launch_info.GetWorkingDirectory()};
238  if (working_dir)
239  command.Printf(R"( --working-dir \"%s\")", working_dir.GetPath().c_str());
240  else {
241  char cwd[PATH_MAX];
242  if (getcwd(cwd, PATH_MAX))
243  command.Printf(R"( --working-dir \"%s\")", cwd);
244  }
245 
246  if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR))
247  command.PutCString(" --disable-aslr");
248 
249  // We are launching on this host in a terminal. So compare the environment on
250  // the host to what is supplied in the launch_info. Any items that aren't in
251  // the host environment need to be sent to darwin-debug. If we send all
252  // environment entries, we might blow the max command line length, so we only
253  // send user modified entries.
254  Environment host_env = Host::GetEnvironment();
255 
256  for (const auto &KV : launch_info.GetEnvironment()) {
257  auto host_entry = host_env.find(KV.first());
258  if (host_entry == host_env.end() || host_entry->second != KV.second)
259  command.Format(R"( --env=\"{0}\")", Environment::compose(KV));
260  }
261 
262  command.PutCString(" -- ");
263 
264  const char **argv = launch_info.GetArguments().GetConstArgumentVector();
265  if (argv) {
266  for (size_t i = 0; argv[i] != NULL; ++i) {
267  if (i == 0)
268  command.Printf(R"( \"%s\")", exe_path);
269  else
270  command.Printf(R"( \"%s\")", argv[i]);
271  }
272  } else {
273  command.Printf(R"( \"%s\")", exe_path);
274  }
275  command.PutCString(" ; echo Process exited with status $?");
276  if (launch_info.GetFlags().Test(lldb::eLaunchFlagCloseTTYOnExit))
277  command.PutCString(" ; exit");
278 
279  StreamString applescript_source;
280 
281  applescript_source.Printf(applscript_in_new_tty,
282  command.GetString().str().c_str());
283 
284  NSAppleScript *applescript = [[NSAppleScript alloc]
285  initWithSource:[NSString stringWithCString:applescript_source.GetString()
286  .str()
287  .c_str()
288  encoding:NSUTF8StringEncoding]];
289 
291 
292  Status lldb_error;
293  // Sleep and wait a bit for debugserver to start to listen...
294  ConnectionFileDescriptor file_conn;
295  char connect_url[128];
296  ::snprintf(connect_url, sizeof(connect_url), "unix-accept://%s",
297  unix_socket_name);
298 
299  // Spawn a new thread to accept incoming connection on the connect_url
300  // so we can grab the pid from the inferior. We have to do this because we
301  // are sending an AppleScript that will launch a process in Terminal.app,
302  // in a shell and the shell will fork/exec a couple of times before we get
303  // to the process that we wanted to launch. So when our process actually
304  // gets launched, we will handshake with it and get the process ID for it.
305  llvm::Expected<HostThread> accept_thread = ThreadLauncher::LaunchThread(
306  unix_socket_name, [&] { return AcceptPIDFromInferior(connect_url); });
307 
308  if (!accept_thread)
309  return Status(accept_thread.takeError());
310 
311  [applescript executeAndReturnError:nil];
312 
313  thread_result_t accept_thread_result = NULL;
314  lldb_error = accept_thread->Join(&accept_thread_result);
315  if (lldb_error.Success() && accept_thread_result) {
316  pid = (intptr_t)accept_thread_result;
317  }
318 
319  llvm::sys::fs::remove(unix_socket_name);
320  [applescript release];
321  if (pid != LLDB_INVALID_PROCESS_ID)
322  launch_info.SetProcessID(pid);
323  return error;
324 }
325 
326 #endif // TARGET_OS_OSX
327 
328 bool Host::OpenFileInExternalEditor(const FileSpec &file_spec,
329  uint32_t line_no) {
330 #if !TARGET_OS_OSX
331  return false;
332 #else // !TARGET_OS_OSX
333  // We attach this to an 'odoc' event to specify a particular selection
334  typedef struct {
335  int16_t reserved0; // must be zero
336  int16_t fLineNumber;
337  int32_t fSelStart;
338  int32_t fSelEnd;
339  uint32_t reserved1; // must be zero
340  uint32_t reserved2; // must be zero
341  } BabelAESelInfo;
342 
343  Log *log = GetLog(LLDBLog::Host);
344  char file_path[PATH_MAX];
345  file_spec.GetPath(file_path, PATH_MAX);
346  CFCString file_cfstr(file_path, kCFStringEncodingUTF8);
347  CFCReleaser<CFURLRef> file_URL(::CFURLCreateWithFileSystemPath(
348  NULL, file_cfstr.get(), kCFURLPOSIXPathStyle, false));
349 
350  LLDB_LOGF(log,
351  "Sending source file: \"%s\" and line: %d to external editor.\n",
352  file_path, line_no);
353 
354  long error;
355  BabelAESelInfo file_and_line_info = {
356  0, // reserved0
357  (int16_t)(line_no - 1), // fLineNumber (zero based line number)
358  1, // fSelStart
359  1024, // fSelEnd
360  0, // reserved1
361  0 // reserved2
362  };
363 
364  AEKeyDesc file_and_line_desc;
365 
366  error = ::AECreateDesc(typeUTF8Text, &file_and_line_info,
367  sizeof(file_and_line_info),
368  &(file_and_line_desc.descContent));
369 
370  if (error != noErr) {
371  LLDB_LOGF(log, "Error creating AEDesc: %ld.\n", error);
372  return false;
373  }
374 
375  file_and_line_desc.descKey = keyAEPosition;
376 
377  static std::string g_app_name;
378  static FSRef g_app_fsref;
379 
380  LSApplicationParameters app_params;
381  ::memset(&app_params, 0, sizeof(app_params));
382  app_params.flags =
383  kLSLaunchDefaults | kLSLaunchDontAddToRecents | kLSLaunchDontSwitch;
384 
385  char *external_editor = ::getenv("LLDB_EXTERNAL_EDITOR");
386 
387  if (external_editor) {
388  LLDB_LOGF(log, "Looking for external editor \"%s\".\n", external_editor);
389 
390  if (g_app_name.empty() ||
391  strcmp(g_app_name.c_str(), external_editor) != 0) {
392  CFCString editor_name(external_editor, kCFStringEncodingUTF8);
393  error = ::LSFindApplicationForInfo(kLSUnknownCreator, NULL,
394  editor_name.get(), &g_app_fsref, NULL);
395 
396  // If we found the app, then store away the name so we don't have to
397  // re-look it up.
398  if (error != noErr) {
399  LLDB_LOGF(log,
400  "Could not find External Editor application, error: %ld.\n",
401  error);
402  return false;
403  }
404  }
405  app_params.application = &g_app_fsref;
406  }
407 
408  ProcessSerialNumber psn;
409  CFCReleaser<CFArrayRef> file_array(
410  CFArrayCreate(NULL, (const void **)file_URL.ptr_address(false), 1, NULL));
411  error = ::LSOpenURLsWithRole(file_array.get(), kLSRolesAll,
412  &file_and_line_desc, &app_params, &psn, 1);
413 
414  AEDisposeDesc(&(file_and_line_desc.descContent));
415 
416  if (error != noErr) {
417  LLDB_LOGF(log, "LSOpenURLsWithRole failed, error: %ld.\n", error);
418 
419  return false;
420  }
421 
422  return true;
423 #endif // TARGET_OS_OSX
424 }
425 
426 bool Host::IsInteractiveGraphicSession() {
427 #if !TARGET_OS_OSX
428  return false;
429 #else
430  auditinfo_addr_t info;
431  getaudit_addr(&info, sizeof(info));
432  return info.ai_flags & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS;
433 #endif
434 }
435 
436 Environment Host::GetEnvironment() { return Environment(*_NSGetEnviron()); }
437 
438 static bool GetMacOSXProcessCPUType(ProcessInstanceInfo &process_info) {
439  if (process_info.ProcessIDIsValid()) {
440  // Make a new mib to stay thread safe
441  int mib[CTL_MAXNAME] = {
442  0,
443  };
444  size_t mib_len = CTL_MAXNAME;
445  if (::sysctlnametomib("sysctl.proc_cputype", mib, &mib_len))
446  return false;
447 
448  mib[mib_len] = process_info.GetProcessID();
449  mib_len++;
450 
451  cpu_type_t cpu, sub = 0;
452  size_t len = sizeof(cpu);
453  if (::sysctl(mib, mib_len, &cpu, &len, 0, 0) == 0) {
454  switch (cpu) {
455  case CPU_TYPE_I386:
456  sub = CPU_SUBTYPE_I386_ALL;
457  break;
458  case CPU_TYPE_X86_64:
459  sub = CPU_SUBTYPE_X86_64_ALL;
460  break;
461 
462 #if defined(CPU_TYPE_ARM64) && defined(CPU_SUBTYPE_ARM64_ALL)
463  case CPU_TYPE_ARM64:
464  sub = CPU_SUBTYPE_ARM64_ALL;
465  break;
466 #endif
467 
468 #if defined(CPU_TYPE_ARM64_32) && defined(CPU_SUBTYPE_ARM64_32_ALL)
469  case CPU_TYPE_ARM64_32:
470  sub = CPU_SUBTYPE_ARM64_32_ALL;
471  break;
472 #endif
473 
474  case CPU_TYPE_ARM: {
475  // Note that we fetched the cpu type from the PROCESS but we can't get a
476  // cpusubtype of the
477  // process -- we can only get the host's cpu subtype.
478  uint32_t cpusubtype = 0;
479  len = sizeof(cpusubtype);
480  if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
481  sub = cpusubtype;
482 
483  bool host_cpu_is_64bit;
484  uint32_t is64bit_capable;
485  size_t is64bit_capable_len = sizeof(is64bit_capable);
486  host_cpu_is_64bit =
487  sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
488  &is64bit_capable_len, NULL, 0) == 0;
489 
490  // if the host is an armv8 device, its cpusubtype will be in
491  // CPU_SUBTYPE_ARM64 numbering
492  // and we need to rewrite it to a reasonable CPU_SUBTYPE_ARM value
493  // instead.
494 
495  if (host_cpu_is_64bit) {
496  sub = CPU_SUBTYPE_ARM_V7;
497  }
498  } break;
499 
500  default:
501  break;
502  }
503  process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu, sub);
504  return true;
505  }
506  }
507  process_info.GetArchitecture().Clear();
508  return false;
509 }
510 
511 static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
512  ProcessInstanceInfo &process_info) {
513  if (process_info.ProcessIDIsValid()) {
514  int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2,
515  (int)process_info.GetProcessID()};
516 
517  size_t arg_data_size = 0;
518  if (::sysctl(proc_args_mib, 3, nullptr, &arg_data_size, NULL, 0) ||
519  arg_data_size == 0)
520  arg_data_size = 8192;
521 
522  // Add a few bytes to the calculated length, I know we need to add at least
523  // one byte
524  // to this number otherwise we get junk back, so add 128 just in case...
525  DataBufferHeap arg_data(arg_data_size + 128, 0);
526  arg_data_size = arg_data.GetByteSize();
527  if (::sysctl(proc_args_mib, 3, arg_data.GetBytes(), &arg_data_size, NULL,
528  0) == 0) {
529  DataExtractor data(arg_data.GetBytes(), arg_data_size,
530  endian::InlHostByteOrder(), sizeof(void *));
531  lldb::offset_t offset = 0;
532  uint32_t argc = data.GetU32(&offset);
533  llvm::Triple &triple = process_info.GetArchitecture().GetTriple();
534  const llvm::Triple::ArchType triple_arch = triple.getArch();
535  const bool check_for_ios_simulator =
536  (triple_arch == llvm::Triple::x86 ||
537  triple_arch == llvm::Triple::x86_64);
538  const char *cstr = data.GetCStr(&offset);
539  if (cstr) {
540  process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native);
541 
542  if (match_info_ptr == NULL ||
543  NameMatches(
544  process_info.GetExecutableFile().GetFilename().GetCString(),
545  match_info_ptr->GetNameMatchType(),
546  match_info_ptr->GetProcessInfo().GetName())) {
547  // Skip NULLs
548  while (true) {
549  const uint8_t *p = data.PeekData(offset, 1);
550  if ((p == NULL) || (*p != '\0'))
551  break;
552  ++offset;
553  }
554  // Now extract all arguments
555  Args &proc_args = process_info.GetArguments();
556  for (int i = 0; i < static_cast<int>(argc); ++i) {
557  cstr = data.GetCStr(&offset);
558  if (cstr)
559  proc_args.AppendArgument(llvm::StringRef(cstr));
560  }
561 
562  Environment &proc_env = process_info.GetEnvironment();
563  while ((cstr = data.GetCStr(&offset))) {
564  if (cstr[0] == '\0')
565  break;
566 
567  if (check_for_ios_simulator) {
568  if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
569  0)
570  process_info.GetArchitecture().GetTriple().setOS(
571  llvm::Triple::IOS);
572  else
573  process_info.GetArchitecture().GetTriple().setOS(
574  llvm::Triple::MacOSX);
575  }
576 
577  proc_env.insert(cstr);
578  }
579  return true;
580  }
581  }
582  }
583  }
584  return false;
585 }
586 
588  if (process_info.ProcessIDIsValid()) {
589  int mib[4];
590  mib[0] = CTL_KERN;
591  mib[1] = KERN_PROC;
592  mib[2] = KERN_PROC_PID;
593  mib[3] = process_info.GetProcessID();
594  struct kinfo_proc proc_kinfo;
595  size_t proc_kinfo_size = sizeof(struct kinfo_proc);
596 
597  if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
598  if (proc_kinfo_size > 0) {
599  process_info.SetParentProcessID(proc_kinfo.kp_eproc.e_ppid);
600  process_info.SetUserID(proc_kinfo.kp_eproc.e_pcred.p_ruid);
601  process_info.SetGroupID(proc_kinfo.kp_eproc.e_pcred.p_rgid);
602  process_info.SetEffectiveUserID(proc_kinfo.kp_eproc.e_ucred.cr_uid);
603  if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
604  process_info.SetEffectiveGroupID(
605  proc_kinfo.kp_eproc.e_ucred.cr_groups[0]);
606  else
607  process_info.SetEffectiveGroupID(UINT32_MAX);
608  return true;
609  }
610  }
611  }
613  process_info.SetUserID(UINT32_MAX);
614  process_info.SetGroupID(UINT32_MAX);
615  process_info.SetEffectiveUserID(UINT32_MAX);
616  process_info.SetEffectiveGroupID(UINT32_MAX);
617  return false;
618 }
619 
620 uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
621  ProcessInstanceInfoList &process_infos) {
622  std::vector<struct kinfo_proc> kinfos;
623 
624  int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
625 
626  size_t pid_data_size = 0;
627  if (::sysctl(mib, 3, nullptr, &pid_data_size, nullptr, 0) != 0)
628  return 0;
629 
630  // Add a few extra in case a few more show up
631  const size_t estimated_pid_count =
632  (pid_data_size / sizeof(struct kinfo_proc)) + 10;
633 
634  kinfos.resize(estimated_pid_count);
635  pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
636 
637  if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, nullptr, 0) != 0)
638  return 0;
639 
640  const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
641 
642  bool all_users = match_info.GetMatchAllUsers();
643  const lldb::pid_t our_pid = getpid();
644  const uid_t our_uid = getuid();
645  for (size_t i = 0; i < actual_pid_count; i++) {
646  const struct kinfo_proc &kinfo = kinfos[i];
647 
648  bool kinfo_user_matches = false;
649  if (all_users)
650  kinfo_user_matches = true;
651  else
652  kinfo_user_matches = kinfo.kp_eproc.e_pcred.p_ruid == our_uid;
653 
654  // Special case, if lldb is being run as root we can attach to anything.
655  if (our_uid == 0)
656  kinfo_user_matches = true;
657 
658  if (!kinfo_user_matches || // Make sure the user is acceptable
659  static_cast<lldb::pid_t>(kinfo.kp_proc.p_pid) ==
660  our_pid || // Skip this process
661  kinfo.kp_proc.p_pid == 0 || // Skip kernel (kernel pid is zero)
662  kinfo.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains...
663  kinfo.kp_proc.p_flag & P_TRACED || // Being debugged?
664  kinfo.kp_proc.p_flag & P_WEXIT)
665  continue;
666 
667  ProcessInstanceInfo process_info;
668  process_info.SetProcessID(kinfo.kp_proc.p_pid);
669  process_info.SetParentProcessID(kinfo.kp_eproc.e_ppid);
670  process_info.SetUserID(kinfo.kp_eproc.e_pcred.p_ruid);
671  process_info.SetGroupID(kinfo.kp_eproc.e_pcred.p_rgid);
672  process_info.SetEffectiveUserID(kinfo.kp_eproc.e_ucred.cr_uid);
673  if (kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
674  process_info.SetEffectiveGroupID(kinfo.kp_eproc.e_ucred.cr_groups[0]);
675  else
676  process_info.SetEffectiveGroupID(UINT32_MAX);
677 
678  // Make sure our info matches before we go fetch the name and cpu type
679  if (!match_info.UserIDsMatch(process_info) ||
680  !match_info.ProcessIDsMatch(process_info))
681  continue;
682 
683  // Get CPU type first so we can know to look for iOS simulator is we have
684  // x86 or x86_64
685  if (GetMacOSXProcessCPUType(process_info)) {
686  if (GetMacOSXProcessArgs(&match_info, process_info)) {
687  if (match_info.Matches(process_info))
688  process_infos.push_back(process_info);
689  }
690  }
691  }
692  return process_infos.size();
693 }
694 
695 bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
696  process_info.SetProcessID(pid);
697  bool success = false;
698 
699  // Get CPU type first so we can know to look for iOS simulator is we have x86
700  // or x86_64
701  if (GetMacOSXProcessCPUType(process_info))
702  success = true;
703 
704  if (GetMacOSXProcessArgs(NULL, process_info))
705  success = true;
706 
707  if (GetMacOSXProcessUserAndGroup(process_info))
708  success = true;
709 
710  if (success)
711  return true;
712 
713  process_info.Clear();
714  return false;
715 }
716 
717 #if TARGET_OS_OSX
718 static void PackageXPCArguments(xpc_object_t message, const char *prefix,
719  const Args &args) {
720  size_t count = args.GetArgumentCount();
721  char buf[50]; // long enough for 'argXXX'
722  memset(buf, 0, 50);
723  sprintf(buf, "%sCount", prefix);
724  xpc_dictionary_set_int64(message, buf, count);
725  for (size_t i = 0; i < count; i++) {
726  memset(buf, 0, 50);
727  sprintf(buf, "%s%zi", prefix, i);
728  xpc_dictionary_set_string(message, buf, args.GetArgumentAtIndex(i));
729  }
730 }
731 
732 static void PackageXPCEnvironment(xpc_object_t message, llvm::StringRef prefix,
733  const Environment &env) {
734  xpc_dictionary_set_int64(message, (prefix + "Count").str().c_str(),
735  env.size());
736  size_t i = 0;
737  for (const auto &KV : env) {
738  xpc_dictionary_set_string(message, (prefix + llvm::Twine(i)).str().c_str(),
739  Environment::compose(KV).c_str());
740  }
741 }
742 
743 /*
744  A valid authorizationRef means that
745  - there is the LaunchUsingXPCRightName rights in the /etc/authorization
746  - we have successfully copied the rights to be send over the XPC wire
747  Once obtained, it will be valid for as long as the process lives.
748  */
749 static AuthorizationRef authorizationRef = NULL;
750 static Status getXPCAuthorization(ProcessLaunchInfo &launch_info) {
751  Status error;
752  Log *log(GetLog(LLDBLog::Host | LLDBLog::Process));
753 
754  if ((launch_info.GetUserID() == 0) && !authorizationRef) {
755  OSStatus createStatus =
756  AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
757  kAuthorizationFlagDefaults, &authorizationRef);
758  if (createStatus != errAuthorizationSuccess) {
759  error.SetError(1, eErrorTypeGeneric);
760  error.SetErrorString("Can't create authorizationRef.");
761  LLDB_LOG(log, "error: {0}", error);
762  return error;
763  }
764 
765  OSStatus rightsStatus =
766  AuthorizationRightGet(LaunchUsingXPCRightName, NULL);
767  if (rightsStatus != errAuthorizationSuccess) {
768  // No rights in the security database, Create it with the right prompt.
769  CFStringRef prompt =
770  CFSTR("Xcode is trying to take control of a root process.");
771  CFStringRef keys[] = {CFSTR("en")};
772  CFTypeRef values[] = {prompt};
773  CFDictionaryRef promptDict = CFDictionaryCreate(
774  kCFAllocatorDefault, (const void **)keys, (const void **)values, 1,
775  &kCFCopyStringDictionaryKeyCallBacks,
776  &kCFTypeDictionaryValueCallBacks);
777 
778  CFStringRef keys1[] = {CFSTR("class"), CFSTR("group"), CFSTR("comment"),
779  CFSTR("default-prompt"), CFSTR("shared")};
780  CFTypeRef values1[] = {CFSTR("user"), CFSTR("admin"),
781  CFSTR(LaunchUsingXPCRightName), promptDict,
782  kCFBooleanFalse};
783  CFDictionaryRef dict = CFDictionaryCreate(
784  kCFAllocatorDefault, (const void **)keys1, (const void **)values1, 5,
785  &kCFCopyStringDictionaryKeyCallBacks,
786  &kCFTypeDictionaryValueCallBacks);
787  rightsStatus = AuthorizationRightSet(
788  authorizationRef, LaunchUsingXPCRightName, dict, NULL, NULL, NULL);
789  CFRelease(promptDict);
790  CFRelease(dict);
791  }
792 
793  OSStatus copyRightStatus = errAuthorizationDenied;
794  if (rightsStatus == errAuthorizationSuccess) {
795  AuthorizationItem item1 = {LaunchUsingXPCRightName, 0, NULL, 0};
796  AuthorizationItem items[] = {item1};
797  AuthorizationRights requestedRights = {1, items};
798  AuthorizationFlags authorizationFlags =
799  kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
800  copyRightStatus = AuthorizationCopyRights(
801  authorizationRef, &requestedRights, kAuthorizationEmptyEnvironment,
802  authorizationFlags, NULL);
803  }
804 
805  if (copyRightStatus != errAuthorizationSuccess) {
806  // Eventually when the commandline supports running as root and the user
807  // is not
808  // logged in in the current audit session, we will need the trick in gdb
809  // where
810  // we ask the user to type in the root passwd in the terminal.
811  error.SetError(2, eErrorTypeGeneric);
812  error.SetErrorStringWithFormat(
813  "Launching as root needs root authorization.");
814  LLDB_LOG(log, "error: {0}", error);
815 
816  if (authorizationRef) {
817  AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
818  authorizationRef = NULL;
819  }
820  }
821  }
822 
823  return error;
824 }
825 #endif
826 
827 static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) {
828  short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
829 
830  if (launch_info.GetFlags().Test(eLaunchFlagExec))
831  flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag
832 
833  if (launch_info.GetFlags().Test(eLaunchFlagDebug))
834  flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag
835 
836  if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR))
837  flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag
838 
839  if (launch_info.GetLaunchInSeparateProcessGroup())
840  flags |= POSIX_SPAWN_SETPGROUP;
841 
842 #ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
843 #if defined(__x86_64__) || defined(__i386__)
844  static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate;
845  if (g_use_close_on_exec_flag == eLazyBoolCalculate) {
846  g_use_close_on_exec_flag = eLazyBoolNo;
847 
848  llvm::VersionTuple version = HostInfo::GetOSVersion();
849  if (version > llvm::VersionTuple(10, 7)) {
850  // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or
851  // earlier
852  g_use_close_on_exec_flag = eLazyBoolYes;
853  }
854  }
855 #else
856  static LazyBool g_use_close_on_exec_flag = eLazyBoolYes;
857 #endif // defined(__x86_64__) || defined(__i386__)
858  // Close all files exception those with file actions if this is supported.
859  if (g_use_close_on_exec_flag == eLazyBoolYes)
860  flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
861 #endif // ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
862  return flags;
863 }
864 
865 static Status LaunchProcessXPC(const char *exe_path,
866  ProcessLaunchInfo &launch_info,
867  lldb::pid_t &pid) {
868 #if TARGET_OS_OSX
869  Status error = getXPCAuthorization(launch_info);
870  if (error.Fail())
871  return error;
872 
873  Log *log(GetLog(LLDBLog::Host | LLDBLog::Process));
874 
875  uid_t requested_uid = launch_info.GetUserID();
876  const char *xpc_service = nil;
877  bool send_auth = false;
878  AuthorizationExternalForm extForm;
879  if (requested_uid == 0) {
880  if (AuthorizationMakeExternalForm(authorizationRef, &extForm) ==
881  errAuthorizationSuccess) {
882  send_auth = true;
883  } else {
884  error.SetError(3, eErrorTypeGeneric);
885  error.SetErrorStringWithFormat("Launching root via XPC needs to "
886  "externalize authorization reference.");
887  LLDB_LOG(log, "error: {0}", error);
888  return error;
889  }
890  xpc_service = LaunchUsingXPCRightName;
891  } else {
892  error.SetError(4, eErrorTypeGeneric);
893  error.SetErrorStringWithFormat(
894  "Launching via XPC is only currently available for root.");
895  LLDB_LOG(log, "error: {0}", error);
896  return error;
897  }
898 
899  xpc_connection_t conn = xpc_connection_create(xpc_service, NULL);
900 
901  xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
902  xpc_type_t type = xpc_get_type(event);
903 
904  if (type == XPC_TYPE_ERROR) {
905  if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
906  // The service has either canceled itself, crashed, or been terminated.
907  // The XPC connection is still valid and sending a message to it will
908  // re-launch the service.
909  // If the service is state-full, this is the time to initialize the new
910  // service.
911  return;
912  } else if (event == XPC_ERROR_CONNECTION_INVALID) {
913  // The service is invalid. Either the service name supplied to
914  // xpc_connection_create() is incorrect
915  // or we (this process) have canceled the service; we can do any cleanup
916  // of application state at this point.
917  // printf("Service disconnected");
918  return;
919  } else {
920  // printf("Unexpected error from service: %s",
921  // xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
922  }
923 
924  } else {
925  // printf("Received unexpected event in handler");
926  }
927  });
928 
929  xpc_connection_set_finalizer_f(conn, xpc_finalizer_t(xpc_release));
930  xpc_connection_resume(conn);
931  xpc_object_t message = xpc_dictionary_create(nil, nil, 0);
932 
933  if (send_auth) {
934  xpc_dictionary_set_data(message, LauncherXPCServiceAuthKey, extForm.bytes,
935  sizeof(AuthorizationExternalForm));
936  }
937 
938  PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey,
939  launch_info.GetArguments());
940  PackageXPCEnvironment(message, LauncherXPCServiceEnvPrefxKey,
941  launch_info.GetEnvironment());
942 
943  // Posix spawn stuff.
944  xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey,
945  launch_info.GetArchitecture().GetMachOCPUType());
946  xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey,
947  GetPosixspawnFlags(launch_info));
948  const FileAction *file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
949  if (file_action && !file_action->GetPath().empty()) {
950  xpc_dictionary_set_string(message, LauncherXPCServiceStdInPathKeyKey,
951  file_action->GetPath().str().c_str());
952  }
953  file_action = launch_info.GetFileActionForFD(STDOUT_FILENO);
954  if (file_action && !file_action->GetPath().empty()) {
955  xpc_dictionary_set_string(message, LauncherXPCServiceStdOutPathKeyKey,
956  file_action->GetPath().str().c_str());
957  }
958  file_action = launch_info.GetFileActionForFD(STDERR_FILENO);
959  if (file_action && !file_action->GetPath().empty()) {
960  xpc_dictionary_set_string(message, LauncherXPCServiceStdErrPathKeyKey,
961  file_action->GetPath().str().c_str());
962  }
963 
964  xpc_object_t reply =
965  xpc_connection_send_message_with_reply_sync(conn, message);
966  xpc_type_t returnType = xpc_get_type(reply);
967  if (returnType == XPC_TYPE_DICTIONARY) {
968  pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey);
969  if (pid == 0) {
970  int errorType =
971  xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey);
972  int errorCode =
973  xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey);
974 
975  error.SetError(errorCode, eErrorTypeGeneric);
976  error.SetErrorStringWithFormat(
977  "Problems with launching via XPC. Error type : %i, code : %i",
978  errorType, errorCode);
979  LLDB_LOG(log, "error: {0}", error);
980 
981  if (authorizationRef) {
982  AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
983  authorizationRef = NULL;
984  }
985  }
986  } else if (returnType == XPC_TYPE_ERROR) {
987  error.SetError(5, eErrorTypeGeneric);
988  error.SetErrorStringWithFormat(
989  "Problems with launching via XPC. XPC error : %s",
990  xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION));
991  LLDB_LOG(log, "error: {0}", error);
992  }
993 
994  return error;
995 #else
996  Status error;
997  return error;
998 #endif
999 }
1000 
1001 static bool AddPosixSpawnFileAction(void *_file_actions, const FileAction *info,
1002  Log *log, Status &error) {
1003  if (info == NULL)
1004  return false;
1005 
1006  posix_spawn_file_actions_t *file_actions =
1007  static_cast<posix_spawn_file_actions_t *>(_file_actions);
1008 
1009  switch (info->GetAction()) {
1010  case FileAction::eFileActionNone:
1011  error.Clear();
1012  break;
1013 
1014  case FileAction::eFileActionClose:
1015  if (info->GetFD() == -1)
1016  error.SetErrorString(
1017  "invalid fd for posix_spawn_file_actions_addclose(...)");
1018  else {
1019  error.SetError(
1020  ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()),
1021  eErrorTypePOSIX);
1022  if (error.Fail())
1023  LLDB_LOG(log,
1024  "error: {0}, posix_spawn_file_actions_addclose "
1025  "(action={1}, fd={2})",
1026  error, file_actions, info->GetFD());
1027  }
1028  break;
1029 
1030  case FileAction::eFileActionDuplicate:
1031  if (info->GetFD() == -1)
1032  error.SetErrorString(
1033  "invalid fd for posix_spawn_file_actions_adddup2(...)");
1034  else if (info->GetActionArgument() == -1)
1035  error.SetErrorString(
1036  "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
1037  else {
1038  error.SetError(
1039  ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(),
1040  info->GetActionArgument()),
1041  eErrorTypePOSIX);
1042  if (error.Fail())
1043  LLDB_LOG(log,
1044  "error: {0}, posix_spawn_file_actions_adddup2 "
1045  "(action={1}, fd={2}, dup_fd={3})",
1046  error, file_actions, info->GetFD(), info->GetActionArgument());
1047  }
1048  break;
1049 
1050  case FileAction::eFileActionOpen:
1051  if (info->GetFD() == -1)
1052  error.SetErrorString(
1053  "invalid fd in posix_spawn_file_actions_addopen(...)");
1054  else {
1055  int oflag = info->GetActionArgument();
1056 
1057  mode_t mode = 0;
1058 
1059  if (oflag & O_CREAT)
1060  mode = 0640;
1061 
1062  error.SetError(::posix_spawn_file_actions_addopen(
1063  file_actions, info->GetFD(),
1064  info->GetPath().str().c_str(), oflag, mode),
1065  eErrorTypePOSIX);
1066  if (error.Fail())
1067  LLDB_LOG(log,
1068  "error: {0}, posix_spawn_file_actions_addopen (action={1}, "
1069  "fd={2}, path='{3}', oflag={4}, mode={5})",
1070  error, file_actions, info->GetFD(), info->GetPath(), oflag,
1071  mode);
1072  }
1073  break;
1074  }
1075  return error.Success();
1076 }
1077 
1078 static Status LaunchProcessPosixSpawn(const char *exe_path,
1079  const ProcessLaunchInfo &launch_info,
1080  lldb::pid_t &pid) {
1081  Status error;
1082  Log *log(GetLog(LLDBLog::Host | LLDBLog::Process));
1083 
1084  posix_spawnattr_t attr;
1085  error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX);
1086 
1087  if (error.Fail()) {
1088  LLDB_LOG(log, "error: {0}, ::posix_spawnattr_init ( &attr )", error);
1089  return error;
1090  }
1091 
1092  // Make sure we clean up the posix spawn attributes before exiting this scope.
1093  auto cleanup_attr =
1094  llvm::make_scope_exit([&]() { posix_spawnattr_destroy(&attr); });
1095 
1096  sigset_t no_signals;
1097  sigset_t all_signals;
1098  sigemptyset(&no_signals);
1099  sigfillset(&all_signals);
1100  ::posix_spawnattr_setsigmask(&attr, &no_signals);
1101  ::posix_spawnattr_setsigdefault(&attr, &all_signals);
1102 
1103  short flags = GetPosixspawnFlags(launch_info);
1104 
1105  error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX);
1106  if (error.Fail()) {
1107  LLDB_LOG(log,
1108  "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )",
1109  error, flags);
1110  return error;
1111  }
1112 
1113  bool is_graphical = true;
1114 
1115 #if TARGET_OS_OSX
1116  SecuritySessionId session_id;
1117  SessionAttributeBits session_attributes;
1118  OSStatus status =
1119  SessionGetInfo(callerSecuritySession, &session_id, &session_attributes);
1120  if (status == errSessionSuccess)
1121  is_graphical = session_attributes & sessionHasGraphicAccess;
1122 #endif
1123 
1124  // When lldb is ran through a graphical session, make the debuggee process
1125  // responsible for its own TCC permissions instead of inheriting them from
1126  // its parent.
1127  if (is_graphical && launch_info.GetFlags().Test(eLaunchFlagDebug) &&
1128  !launch_info.GetFlags().Test(eLaunchFlagInheritTCCFromParent)) {
1130  if (error.Fail()) {
1131  LLDB_LOG(log, "error: {0}, setup_posix_spawn_responsible_flag(&attr)",
1132  error);
1133  return error;
1134  }
1135  }
1136 
1137  // Don't set the binpref if a shell was provided. After all, that's only
1138  // going to affect what version of the shell is launched, not what fork of
1139  // the binary is launched. We insert "arch --arch <ARCH> as part of the
1140  // shell invocation to do that job on OSX.
1141  if (launch_info.GetShell() == FileSpec()) {
1142  const ArchSpec &arch_spec = launch_info.GetArchitecture();
1143  cpu_type_t cpu_type = arch_spec.GetMachOCPUType();
1144  cpu_type_t cpu_subtype = arch_spec.GetMachOCPUSubType();
1145  const bool set_cpu_type =
1146  cpu_type != 0 && cpu_type != static_cast<cpu_type_t>(UINT32_MAX) &&
1147  cpu_type != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE);
1148  const bool set_cpu_subtype =
1149  cpu_subtype != 0 &&
1150  cpu_subtype != static_cast<cpu_subtype_t>(UINT32_MAX) &&
1151  cpu_subtype != CPU_SUBTYPE_X86_64_H;
1152  if (set_cpu_type) {
1153  size_t ocount = 0;
1154  typedef int (*posix_spawnattr_setarchpref_np_t)(
1155  posix_spawnattr_t *, size_t, cpu_type_t *, cpu_subtype_t *, size_t *);
1156  posix_spawnattr_setarchpref_np_t posix_spawnattr_setarchpref_np_fn =
1157  (posix_spawnattr_setarchpref_np_t)dlsym(
1158  RTLD_DEFAULT, "posix_spawnattr_setarchpref_np");
1159  if (set_cpu_subtype && posix_spawnattr_setarchpref_np_fn) {
1160  error.SetError((*posix_spawnattr_setarchpref_np_fn)(
1161  &attr, 1, &cpu_type, &cpu_subtype, &ocount),
1162  eErrorTypePOSIX);
1163  if (error.Fail())
1164  LLDB_LOG(log,
1165  "error: {0}, ::posix_spawnattr_setarchpref_np ( &attr, 1, "
1166  "cpu_type = {1:x}, cpu_subtype = {1:x}, count => {2} )",
1167  error, cpu_type, cpu_subtype, ocount);
1168 
1169  if (error.Fail() || ocount != 1)
1170  return error;
1171  } else {
1172  error.SetError(
1173  ::posix_spawnattr_setbinpref_np(&attr, 1, &cpu_type, &ocount),
1174  eErrorTypePOSIX);
1175  if (error.Fail())
1176  LLDB_LOG(log,
1177  "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, "
1178  "cpu_type = {1:x}, count => {2} )",
1179  error, cpu_type, ocount);
1180  if (error.Fail() || ocount != 1)
1181  return error;
1182  }
1183  }
1184  }
1185 
1186  const char *tmp_argv[2];
1187  char *const *argv = const_cast<char *const *>(
1188  launch_info.GetArguments().GetConstArgumentVector());
1189  Environment::Envp envp = launch_info.GetEnvironment().getEnvp();
1190  if (argv == NULL) {
1191  // posix_spawn gets very unhappy if it doesn't have at least the program
1192  // name in argv[0]. One of the side affects I have noticed is the
1193  // environment
1194  // variables don't make it into the child process if "argv == NULL"!!!
1195  tmp_argv[0] = exe_path;
1196  tmp_argv[1] = NULL;
1197  argv = const_cast<char *const *>(tmp_argv);
1198  }
1199 
1200  FileSpec working_dir{launch_info.GetWorkingDirectory()};
1201  if (working_dir) {
1202  // Set the working directory on this thread only
1203  std::string working_dir_path = working_dir.GetPath();
1204  if (__pthread_chdir(working_dir_path.c_str()) < 0) {
1205  if (errno == ENOENT) {
1206  error.SetErrorStringWithFormat("No such file or directory: %s",
1207  working_dir_path.c_str());
1208  } else if (errno == ENOTDIR) {
1209  error.SetErrorStringWithFormat("Path doesn't name a directory: %s",
1210  working_dir_path.c_str());
1211  } else {
1212  error.SetErrorStringWithFormat("An unknown error occurred when "
1213  "changing directory for process "
1214  "execution.");
1215  }
1216  return error;
1217  }
1218  }
1219 
1220  ::pid_t result_pid = LLDB_INVALID_PROCESS_ID;
1221  const size_t num_file_actions = launch_info.GetNumFileActions();
1222  if (num_file_actions > 0) {
1223  posix_spawn_file_actions_t file_actions;
1224  error.SetError(::posix_spawn_file_actions_init(&file_actions),
1225  eErrorTypePOSIX);
1226  if (error.Fail()) {
1227  LLDB_LOG(log,
1228  "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )",
1229  error);
1230  return error;
1231  }
1232 
1233  // Make sure we clean up the posix file actions before exiting this scope.
1234  auto cleanup_fileact = llvm::make_scope_exit(
1235  [&]() { posix_spawn_file_actions_destroy(&file_actions); });
1236 
1237  for (size_t i = 0; i < num_file_actions; ++i) {
1238  const FileAction *launch_file_action =
1239  launch_info.GetFileActionAtIndex(i);
1240  if (launch_file_action) {
1241  if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log,
1242  error))
1243  return error;
1244  }
1245  }
1246 
1247  error.SetError(
1248  ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp),
1249  eErrorTypePOSIX);
1250 
1251  if (error.Fail()) {
1252  LLDB_LOG(log,
1253  "error: {0}, ::posix_spawnp(pid => {1}, path = '{2}', "
1254  "file_actions = {3}, "
1255  "attr = {4}, argv = {5}, envp = {6} )",
1256  error, result_pid, exe_path, &file_actions, &attr, argv,
1257  envp.get());
1258  if (log) {
1259  for (int ii = 0; argv[ii]; ++ii)
1260  LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]);
1261  }
1262  }
1263 
1264  } else {
1265  error.SetError(
1266  ::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp),
1267  eErrorTypePOSIX);
1268 
1269  if (error.Fail()) {
1270  LLDB_LOG(log,
1271  "error: {0}, ::posix_spawnp ( pid => {1}, path = '{2}', "
1272  "file_actions = NULL, attr = {3}, argv = {4}, envp = {5} )",
1273  error, result_pid, exe_path, &attr, argv, envp.get());
1274  if (log) {
1275  for (int ii = 0; argv[ii]; ++ii)
1276  LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]);
1277  }
1278  }
1279  }
1280  pid = result_pid;
1281 
1282  if (working_dir) {
1283  // No more thread specific current working directory
1284  __pthread_fchdir(-1);
1285  }
1286 
1287  return error;
1288 }
1289 
1290 static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) {
1291  bool result = false;
1292 
1293 #if TARGET_OS_OSX
1294  bool launchingAsRoot = launch_info.GetUserID() == 0;
1295  bool currentUserIsRoot = HostInfo::GetEffectiveUserID() == 0;
1296 
1297  if (launchingAsRoot && !currentUserIsRoot) {
1298  // If current user is already root, we don't need XPC's help.
1299  result = true;
1300  }
1301 #endif
1302 
1303  return result;
1304 }
1305 
1306 Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
1307  Status error;
1308 
1309  FileSystem &fs = FileSystem::Instance();
1310  FileSpec exe_spec(launch_info.GetExecutableFile());
1311 
1312  if (!fs.Exists(exe_spec))
1313  FileSystem::Instance().Resolve(exe_spec);
1314 
1315  if (!fs.Exists(exe_spec))
1316  FileSystem::Instance().ResolveExecutableLocation(exe_spec);
1317 
1318  if (!fs.Exists(exe_spec)) {
1319  error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'",
1320  exe_spec);
1321  return error;
1322  }
1323 
1324  if (launch_info.GetFlags().Test(eLaunchFlagLaunchInTTY)) {
1325 #if TARGET_OS_OSX
1326  return LaunchInNewTerminalWithAppleScript(exe_spec.GetPath().c_str(),
1327  launch_info);
1328 #else
1329  error.SetErrorString("launching a process in a new terminal is not "
1330  "supported on iOS devices");
1331  return error;
1332 #endif
1333  }
1334 
1336 
1337  auto exe_path = exe_spec.GetPath();
1338 
1339  if (ShouldLaunchUsingXPC(launch_info))
1340  error = LaunchProcessXPC(exe_path.c_str(), launch_info, pid);
1341  else
1342  error = LaunchProcessPosixSpawn(exe_path.c_str(), launch_info, pid);
1343 
1344  if (pid != LLDB_INVALID_PROCESS_ID) {
1345  // If all went well, then set the process ID into the launch info
1346  launch_info.SetProcessID(pid);
1347 
1348  // Make sure we reap any processes we spawn or we will have zombies.
1349  bool monitoring = launch_info.MonitorProcess();
1350  UNUSED_IF_ASSERT_DISABLED(monitoring);
1351  assert(monitoring);
1352  } else {
1353  // Invalid process ID, something didn't go well
1354  if (error.Success())
1355  error.SetErrorString("process launch failed for unknown reasons");
1356  }
1357  return error;
1358 }
1359 
1360 Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
1361  Status error;
1362  if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {
1363  FileSpec expand_tool_spec = HostInfo::GetSupportExeDir();
1364  if (!expand_tool_spec) {
1365  error.SetErrorString(
1366  "could not get support executable directory for lldb-argdumper tool");
1367  return error;
1368  }
1369  expand_tool_spec.AppendPathComponent("lldb-argdumper");
1370  if (!FileSystem::Instance().Exists(expand_tool_spec)) {
1371  error.SetErrorStringWithFormat(
1372  "could not find the lldb-argdumper tool: %s",
1373  expand_tool_spec.GetPath().c_str());
1374  return error;
1375  }
1376 
1377  StreamString expand_tool_spec_stream;
1378  expand_tool_spec_stream.Printf("\"%s\"",
1379  expand_tool_spec.GetPath().c_str());
1380 
1381  Args expand_command(expand_tool_spec_stream.GetData());
1382  expand_command.AppendArguments(launch_info.GetArguments());
1383 
1384  int status;
1385  std::string output;
1386  FileSpec cwd(launch_info.GetWorkingDirectory());
1387  if (!FileSystem::Instance().Exists(cwd)) {
1388  char *wd = getcwd(nullptr, 0);
1389  if (wd == nullptr) {
1390  error.SetErrorStringWithFormat(
1391  "cwd does not exist; cannot launch with shell argument expansion");
1392  return error;
1393  } else {
1394  FileSpec working_dir(wd);
1395  free(wd);
1396  launch_info.SetWorkingDirectory(working_dir);
1397  }
1398  }
1399  bool run_in_shell = true;
1400  bool hide_stderr = true;
1401  Status e =
1402  RunShellCommand(expand_command, cwd, &status, nullptr, &output,
1403  std::chrono::seconds(10), run_in_shell, hide_stderr);
1404 
1405  if (e.Fail())
1406  return e;
1407 
1408  if (status != 0) {
1409  error.SetErrorStringWithFormat("lldb-argdumper exited with error %d",
1410  status);
1411  return error;
1412  }
1413 
1414  auto data_sp = StructuredData::ParseJSON(output);
1415  if (!data_sp) {
1416  error.SetErrorString("invalid JSON");
1417  return error;
1418  }
1419 
1420  auto dict_sp = data_sp->GetAsDictionary();
1421  if (!data_sp) {
1422  error.SetErrorString("invalid JSON");
1423  return error;
1424  }
1425 
1426  auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments");
1427  if (!args_sp) {
1428  error.SetErrorString("invalid JSON");
1429  return error;
1430  }
1431 
1432  auto args_array_sp = args_sp->GetAsArray();
1433  if (!args_array_sp) {
1434  error.SetErrorString("invalid JSON");
1435  return error;
1436  }
1437 
1438  launch_info.GetArguments().Clear();
1439 
1440  for (size_t i = 0; i < args_array_sp->GetSize(); i++) {
1441  auto item_sp = args_array_sp->GetItemAtIndex(i);
1442  if (!item_sp)
1443  continue;
1444  auto str_sp = item_sp->GetAsString();
1445  if (!str_sp)
1446  continue;
1447 
1448  launch_info.GetArguments().AppendArgument(str_sp->GetValue());
1449  }
1450  }
1451 
1452  return error;
1453 }
1454 
1455 llvm::Expected<HostThread> Host::StartMonitoringChildProcess(
1456  const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid) {
1457  unsigned long mask = DISPATCH_PROC_EXIT;
1458 
1459  Log *log(GetLog(LLDBLog::Host | LLDBLog::Process));
1460 
1461  dispatch_source_t source = ::dispatch_source_create(
1462  DISPATCH_SOURCE_TYPE_PROC, pid, mask,
1463  ::dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
1464 
1465  LLDB_LOGF(log,
1466  "Host::StartMonitoringChildProcess(callback, pid=%i) source = %p\n",
1467  static_cast<int>(pid), static_cast<void *>(source));
1468 
1469  if (source) {
1470  Host::MonitorChildProcessCallback callback_copy = callback;
1471  ::dispatch_source_set_cancel_handler(source, ^{
1472  dispatch_release(source);
1473  });
1474  ::dispatch_source_set_event_handler(source, ^{
1475 
1476  int status = 0;
1477  int wait_pid = 0;
1478  wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &status, 0);
1479  if (wait_pid >= 0) {
1480  int signal = 0;
1481  int exit_status = 0;
1482  const char *status_cstr = NULL;
1483  if (WIFEXITED(status)) {
1484  exit_status = WEXITSTATUS(status);
1485  status_cstr = "EXITED";
1486  } else if (WIFSIGNALED(status)) {
1487  signal = WTERMSIG(status);
1488  status_cstr = "SIGNALED";
1489  exit_status = -1;
1490  } else {
1491  llvm_unreachable("Unknown status");
1492  }
1493 
1494  LLDB_LOGF(log,
1495  "::waitpid (pid = %llu, &status, 0) => pid = %i, status "
1496  "= 0x%8.8x (%s), signal = %i, exit_status = %i",
1497  pid, wait_pid, status, status_cstr, signal, exit_status);
1498 
1499  if (callback_copy)
1500  callback_copy(pid, signal, exit_status);
1501 
1502  ::dispatch_source_cancel(source);
1503  }
1504  });
1505 
1506  ::dispatch_resume(source);
1507  }
1508  return HostThread();
1509 }
lldb_private::ProcessInfo::GetArguments
Args & GetArguments()
Definition: ProcessInfo.h:74
lldb_private::Stream::Format
void Format(const char *format, Args &&... args)
Definition: Stream.h:309
lldb_private::ProcessInstanceInfo
Definition: ProcessInfo.h:106
lldb_private::DataBufferHeap::GetByteSize
lldb::offset_t GetByteSize() const override
Definition: DataBufferHeap.cpp:43
lldb_private::ArchSpec
Definition: ArchSpec.h:32
FileSystem.h
UNUSED_IF_ASSERT_DISABLED
#define UNUSED_IF_ASSERT_DISABLED(x)
Definition: lldb-defines.h:126
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::ProcessInstanceInfoMatch::GetMatchAllUsers
bool GetMatchAllUsers() const
Definition: ProcessInfo.h:175
LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:81
g_os_log_once
static std::once_flag g_os_log_once
Definition: Host.mm:103
lldb_private::ProcessInstanceInfo::Clear
void Clear()
Definition: ProcessInfo.h:114
lldb_private::HostThread
Definition: HostThread.h:29
StructuredData.h
Host.h
lldb_private::Environment::Envp
Definition: Environment.h:22
lldb_private::ProcessInfo::GetUserID
uint32_t GetUserID() const
Definition: ProcessInfo.h:48
lldb_private::ArchSpec::GetCore
Core GetCore() const
Definition: ArchSpec.h:442
lldb-defines.h
ProcessLaunchInfo.h
__pthread_fchdir
int __pthread_fchdir(int fildes)
PosixSpawnResponsible.h
lldb_private::eLazyBoolYes
@ eLazyBoolYes
Definition: lldb-private-enumerations.h:115
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:344
AddPosixSpawnFileAction
static bool AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Status &error)
Definition: Host.mm:1001
GetMacOSXProcessArgs
static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info)
Definition: Host.mm:511
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::DataExtractor::PeekData
const uint8_t * PeekData(lldb::offset_t offset, lldb::offset_t length) const
Peek at a bytes at offset.
Definition: DataExtractor.h:832
lldb_private::Args::Clear
void Clear()
Clear the arguments.
Definition: Args.cpp:379
lldb_private::ProcessLaunchInfo::GetFileActionForFD
const FileAction * GetFileActionForFD(int fd) const
Definition: ProcessLaunchInfo.cpp:115
lldb_private::ProcessInfo::SetUserID
void SetUserID(uint32_t uid)
Definition: ProcessInfo.h:56
lldb_private::ProcessInstanceInfoMatch
Definition: ProcessInfo.h:160
lldb_private::ProcessInfo::GetProcessID
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:66
lldb_private::FileSpec::GetFilename
const ConstString & GetFilename() const
Filename string const get accessor.
Definition: FileSpec.h:239
__pthread_chdir
int __pthread_chdir(const char *path)
lldb::offset_t
uint64_t offset_t
Definition: lldb-types.h:87
lldb_private::Flags::Test
bool Test(ValueType bit) const
Test a single flag bit.
Definition: Flags.h:96
lldb_private::FileSystem::Exists
bool Exists(const FileSpec &file_spec) const
Returns whether the given file exists.
Definition: common/FileSystem.cpp:150
lldb_private::ProcessLaunchInfo::GetFlags
Flags & GetFlags()
Definition: ProcessLaunchInfo.h:64
lldb_private::ProcessInfo::SetProcessID
void SetProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:68
lldb_private::ProcessInstanceInfo::SetEffectiveUserID
void SetEffectiveUserID(uint32_t uid)
Definition: ProcessInfo.h:129
lldb_private::Args
Definition: Args.h:33
lldb_private::FileSystem
Definition: FileSystem.h:28
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:463
lldb_private::LazyBool
LazyBool
Definition: lldb-private-enumerations.h:115
cpu_subtype_t
int cpu_subtype_t
Definition: LocateSymbolFile.cpp:33
LLDB_INVALID_CPUTYPE
#define LLDB_INVALID_CPUTYPE
Definition: lldb-defines.h:95
ThreadLauncher.h
setup_posix_spawn_responsible_flag
static int setup_posix_spawn_responsible_flag(posix_spawnattr_t *attr)
Definition: PosixSpawnResponsible.h:26
lldb_private::FileAction
Definition: FileAction.h:17
lldb_private::ProcessInstanceInfoMatch::Matches
bool Matches(const ProcessInstanceInfo &proc_info) const
Definition: ProcessInfo.cpp:290
CFCString
Definition: CFCString.h:16
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
CFCReleaser
lldb_private::eArchTypeMachO
@ eArchTypeMachO
Definition: lldb-private-enumerations.h:63
lldb::eErrorTypePOSIX
@ eErrorTypePOSIX
POSIX error codes.
Definition: lldb-enumerations.h:311
lldb_private::Environment::insert
std::pair< iterator, bool > insert(llvm::StringRef KeyEqValue)
Definition: Environment.h:71
ShouldLaunchUsingXPC
static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info)
Definition: Host.mm:1290
lldb_private::Host::MonitorChildProcessCallback
std::function< void(lldb::pid_t pid, int signal, int status)> MonitorChildProcessCallback
Definition: Host.h:69
lldb_private::FileSpec
Definition: FileSpec.h:55
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::Status::Success
bool Success() const
Test for success condition.
Definition: Status.cpp:287
lldb_private::ArchSpec::GetMachOCPUType
uint32_t GetMachOCPUType() const
Definition: ArchSpec.cpp:646
lldb_private::Environment::Envp::get
char *const * get() const
Definition: Environment.h:27
ProcessInfo.h
GetPosixspawnFlags
static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info)
Definition: Host.mm:827
lldb_private::ProcessLaunchInfo
Definition: ProcessLaunchInfo.h:31
lldb_private::DataExtractor
Definition: DataExtractor.h:48
Log.h
lldb_private::ProcessInstanceInfo::SetEffectiveGroupID
void SetEffectiveGroupID(uint32_t gid)
Definition: ProcessInfo.h:131
NameMatches.h
lldb_private::Status::Fail
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
lldb_private::ProcessInstanceInfoMatch::GetProcessInfo
ProcessInstanceInfo & GetProcessInfo()
Definition: ProcessInfo.h:171
lldb_private::StreamString::GetData
const char * GetData() const
Definition: StreamString.h:43
StreamString.h
lldb_private::ProcessInfo::GetName
const char * GetName() const
Definition: ProcessInfo.cpp:40
lldb_private::FileAction::GetFD
int GetFD() const
Definition: FileAction.h:36
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::ArchSpec::GetMachOCPUSubType
uint32_t GetMachOCPUSubType() const
Definition: ArchSpec.cpp:658
lldb::ConnectionStatus
ConnectionStatus
Connection Status Types.
Definition: lldb-enumerations.h:296
lldb_private::ProcessLaunchInfo::GetFileActionAtIndex
const FileAction * GetFileActionAtIndex(size_t idx) const
Definition: ProcessLaunchInfo.cpp:109
lldb_private::Environment::getEnvp
Envp getEnvp() const
Definition: Environment.h:78
lldb_private::FileAction::GetAction
Action GetAction() const
Definition: FileAction.h:38
ConnectionFileDescriptor.h
cpu_type_t
int cpu_type_t
Definition: LocateSymbolFile.cpp:32
lldb::eErrorTypeGeneric
@ eErrorTypeGeneric
Generic errors that can be any value.
Definition: lldb-enumerations.h:309
HostInfo.h
lldb_private::ProcessLaunchInfo::GetNumFileActions
size_t GetNumFileActions() const
Definition: ProcessLaunchInfo.h:58
LaunchProcessPosixSpawn
static Status LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid)
Definition: Host.mm:1078
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::ArchSpec::IsValid
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:361
lldb_private::FileAction::GetPath
llvm::StringRef GetPath() const
Definition: FileAction.cpp:28
CPU_TYPE_ARM64_32
#define CPU_TYPE_ARM64_32
Definition: HostInfoMacOSX.mm:57
lldb_private::ConnectionFileDescriptor::Connect
lldb::ConnectionStatus Connect(llvm::StringRef url, Status *error_ptr) override
Connect using the connect string url.
Definition: ConnectionFileDescriptorPosix.cpp:123
GetMacOSXProcessUserAndGroup
static bool GetMacOSXProcessUserAndGroup(ProcessInstanceInfo &process_info)
Definition: Host.mm:587
CFCBundle
Definition: CFCBundle.h:14
lldb_private::ProcessInstanceInfoMatch::GetNameMatchType
NameMatch GetNameMatchType() const
Definition: ProcessInfo.h:179
GetMacOSXProcessCPUType
static bool GetMacOSXProcessCPUType(ProcessInstanceInfo &process_info)
Definition: Host.mm:438
lldb_private::FileSpec::Clear
void Clear()
Clears the object state.
Definition: FileSpec.cpp:257
lldb_private::FileSpec::SetFilename
void SetFilename(ConstString filename)
Filename string set accessor.
Definition: FileSpec.cpp:342
lldb_private::ArchSpec::SetArchitecture
bool SetArchitecture(ArchitectureType arch_type, uint32_t cpu, uint32_t sub, uint32_t os=0)
Change the architecture object type, CPU type and OS type.
Definition: ArchSpec.cpp:854
lldb_private::Status
Definition: Status.h:44
lldb_private::Args::GetArgumentAtIndex
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:264
lldb_private::ArchSpec::GetArchitectureName
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:547
lldb_private::ProcessInstanceInfoMatch::UserIDsMatch
bool UserIDsMatch(const ProcessInstanceInfo &proc_info) const
Return true iff the (both effective and real) user and group IDs in this object match the ones in pro...
Definition: ProcessInfo.cpp:271
uint32_t
message
message(FATAL_ERROR "invalid libipt include path provided") endif() include_directories($
Definition: Plugins/Trace/intel-pt/CMakeLists.txt:6
lldb_private::eLazyBoolNo
@ eLazyBoolNo
Definition: lldb-private-enumerations.h:115
lldb::thread_result_t
void * thread_result_t
Definition: lldb-types.h:62
lldb_private::ProcessInfo::GetEnvironment
Environment & GetEnvironment()
Definition: ProcessInfo.h:86
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::endian::InlHostByteOrder
lldb::ByteOrder InlHostByteOrder()
Definition: Endian.h:25
g_os_log
static os_log_t g_os_log
Definition: Host.mm:102
ArchSpec.h
UINT32_MAX
#define UINT32_MAX
Definition: lldb-defines.h:19
lldb_private::ProcessLaunchInfo::GetShell
const FileSpec & GetShell() const
Definition: ProcessLaunchInfo.cpp:139
lldb_private::Environment
Definition: Environment.h:18
lldb_private::DataExtractor::GetU32
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
Definition: DataExtractor.cpp:425
lldb_private::ConstString::GetCString
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:215
LaunchProcessXPC
static Status LaunchProcessXPC(const char *exe_path, ProcessLaunchInfo &launch_info, lldb::pid_t &pid)
Definition: Host.mm:865
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:337
DataExtractor.h
_POSIX_SPAWN_DISABLE_ASLR
#define _POSIX_SPAWN_DISABLE_ASLR
Definition: Host.mm: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::eConnectionStatusSuccess
@ eConnectionStatusSuccess
Success.
Definition: lldb-enumerations.h:297
CPU_SUBTYPE_X86_64_H
#define CPU_SUBTYPE_X86_64_H
Definition: HostInfoMacOSX.mm:49
lldb_private::FileSpec::AppendPathComponent
void AppendPathComponent(llvm::StringRef component)
Definition: FileSpec.cpp:451
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
lldb_private::eLazyBoolCalculate
@ eLazyBoolCalculate
Definition: lldb-private-enumerations.h:115
lldb_private::DataExtractor::GetCStr
const char * GetCStr(lldb::offset_t *offset_ptr) const
Extract a C string from *offset_ptr.
Definition: DataExtractor.cpp:784
lldb_private::ProcessInfo::GetExecutableFile
FileSpec & GetExecutableFile()
Definition: ProcessInfo.h:41
FileSpec.h
lldb_private::ProcessLaunchInfo::MonitorProcess
bool MonitorProcess() const
Definition: ProcessLaunchInfo.cpp:184
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::GetLaunchInSeparateProcessGroup
bool GetLaunchInSeparateProcessGroup() const
Definition: ProcessLaunchInfo.h:84
lldb_private::FileSpec::SetFile
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:172
lldb_private::ArchSpec::Clear
void Clear()
Clears the object state.
Definition: ArchSpec.cpp:536
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
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::FileAction::GetActionArgument
int GetActionArgument() const
Definition: FileAction.h:40
lldb_private::Args::GetArgumentCount
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
lldb_private::DataBufferHeap
Definition: DataBufferHeap.h:30
lldb_private::ProcessInstanceInfoList
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition: Host.h:31
lldb_private::ConnectionFileDescriptor
Definition: ConnectionFileDescriptorPosix.h:29
lldb_private::ProcessInstanceInfoMatch::ProcessIDsMatch
bool ProcessIDsMatch(const ProcessInstanceInfo &proc_info) const
Return true iff the process ID and parent process IDs in this object match the ones in proc_info.
Definition: ProcessInfo.cpp:259
lldb
Definition: SBAddress.h:15
Endian.h
lldb_private::ProcessInstanceInfo::SetParentProcessID
void SetParentProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:135
LLDBLog.h
CPU_TYPE_ARM64
#define CPU_TYPE_ARM64
Definition: HostInfoMacOSX.mm:52
lldb_private::ProcessInfo::SetGroupID
void SetGroupID(uint32_t gid)
Definition: ProcessInfo.h:58
lldb_private::NameMatches
bool NameMatches(llvm::StringRef name, NameMatch match_type, llvm::StringRef match)
Definition: NameMatches.cpp:15
DataBufferHeap.h
lldb_private::ConnectionFileDescriptor::Read
size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr) override
The read function that attempts to read from the connection.
Definition: ConnectionFileDescriptorPosix.cpp:248