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