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