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