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