1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | #include <errno(*__errno_location ()).h> |
12 | #include <limits.h> |
13 | #include <stdlib.h> |
14 | #include <sys/types.h> |
15 | #ifndef _WIN32 |
16 | #include <unistd.h> |
17 | #include <dlfcn.h> |
18 | #include <grp.h> |
19 | #include <netdb.h> |
20 | #include <pwd.h> |
21 | #include <sys/stat.h> |
22 | #endif |
23 | |
24 | #if defined (__APPLE__) |
25 | #include <mach/mach_port.h> |
26 | #include <mach/mach_init.h> |
27 | #include <mach-o/dyld.h> |
28 | #endif |
29 | |
30 | #if defined (__linux__1) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) || defined(__NetBSD__) |
31 | #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) |
32 | #include <spawn.h> |
33 | #endif |
34 | #include <sys/wait.h> |
35 | #include <sys/syscall.h> |
36 | #endif |
37 | |
38 | #if defined (__FreeBSD__) |
39 | #include <pthread_np.h> |
40 | #endif |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | #include "lldb/Host/FileSystem.h" |
48 | #include "lldb/Host/Host.h" |
49 | #include "lldb/Host/HostInfo.h" |
50 | #include "lldb/Core/ArchSpec.h" |
51 | #include "lldb/Core/Error.h" |
52 | #include "lldb/Core/Log.h" |
53 | #include "lldb/Host/FileSpec.h" |
54 | #include "lldb/Host/HostProcess.h" |
55 | #include "lldb/Host/MonitoringProcessLauncher.h" |
56 | #include "lldb/Host/Predicate.h" |
57 | #include "lldb/Host/ProcessLauncher.h" |
58 | #include "lldb/Host/ThreadLauncher.h" |
59 | #include "lldb/lldb-private-forward.h" |
60 | #include "llvm/Support/FileSystem.h" |
61 | #include "lldb/Target/FileAction.h" |
62 | #include "lldb/Target/ProcessLaunchInfo.h" |
63 | #include "lldb/Target/UnixSignals.h" |
64 | #include "lldb/Utility/CleanUp.h" |
65 | #include "llvm/ADT/SmallString.h" |
66 | |
67 | #if defined(_WIN32) |
68 | #include "lldb/Host/windows/ProcessLauncherWindows.h" |
69 | #elif defined(__ANDROID__) || defined(__ANDROID_NDK__) |
70 | #include "lldb/Host/android/ProcessLauncherAndroid.h" |
71 | #else |
72 | #include "lldb/Host/posix/ProcessLauncherPosix.h" |
73 | #endif |
74 | |
75 | #if defined (__APPLE__) |
76 | #ifndef _POSIX_SPAWN_DISABLE_ASLR |
77 | #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 |
78 | #endif |
79 | |
80 | extern "C" |
81 | { |
82 | int __pthread_chdir(const char *path); |
83 | int __pthread_fchdir (int fildes); |
84 | } |
85 | |
86 | #endif |
87 | |
88 | using namespace lldb; |
89 | using namespace lldb_private; |
90 | |
91 | #if !defined (__APPLE__) && !defined (_WIN32) |
92 | struct MonitorInfo |
93 | { |
94 | lldb::pid_t pid; |
95 | Host::MonitorChildProcessCallback callback; |
96 | void *callback_baton; |
97 | bool monitor_signals; |
98 | }; |
99 | |
100 | static thread_result_t |
101 | MonitorChildProcessThreadFunction (void *arg); |
102 | |
103 | HostThread |
104 | Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, bool monitor_signals) |
105 | { |
106 | MonitorInfo * info_ptr = new MonitorInfo(); |
107 | |
108 | info_ptr->pid = pid; |
109 | info_ptr->callback = callback; |
110 | info_ptr->callback_baton = callback_baton; |
111 | info_ptr->monitor_signals = monitor_signals; |
112 | |
113 | char thread_name[256]; |
114 | ::snprintf(thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64"l" "u" ")>", pid); |
115 | return ThreadLauncher::LaunchThread(thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL__null); |
116 | } |
117 | |
118 | #ifndef __linux__1 |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | class ScopedPThreadCancelDisabler |
125 | { |
126 | public: |
127 | ScopedPThreadCancelDisabler() |
128 | { |
129 | |
130 | int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLEPTHREAD_CANCEL_DISABLE, &m_old_state); |
131 | if (err != 0) |
132 | m_old_state = -1; |
133 | } |
134 | |
135 | ~ScopedPThreadCancelDisabler() |
136 | { |
137 | |
138 | |
139 | if (m_old_state != -1) |
140 | ::pthread_setcancelstate (m_old_state, 0); |
141 | } |
142 | private: |
143 | int m_old_state; |
144 | }; |
145 | #endif // __linux__ |
146 | |
147 | #ifdef __linux__1 |
148 | #if defined(__GNUC__4) && (__GNUC__4 < 4 || (__GNUC__4 == 4 && __GNUC_MINOR__2 < 8)) |
149 | static __thread volatile sig_atomic_t g_usr1_called; |
150 | #else |
151 | static thread_local volatile sig_atomic_t g_usr1_called; |
152 | #endif |
153 | |
154 | static void |
155 | SigUsr1Handler (int) |
156 | { |
157 | g_usr1_called = 1; |
158 | } |
159 | #endif // __linux__ |
160 | |
161 | static bool |
162 | CheckForMonitorCancellation() |
163 | { |
164 | #ifdef __linux__1 |
165 | if (g_usr1_called) |
166 | { |
167 | g_usr1_called = 0; |
168 | return true; |
169 | } |
170 | #else |
171 | ::pthread_testcancel (); |
172 | #endif |
173 | return false; |
174 | } |
175 | |
176 | static thread_result_t |
177 | MonitorChildProcessThreadFunction (void *arg) |
178 | { |
179 | Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); |
180 | const char *function = __FUNCTION__; |
181 | if (log) |
| |
| |
182 | log->Printf ("%s (arg = %p) thread starting...", function, arg); |
183 | |
184 | MonitorInfo *info = (MonitorInfo *)arg; |
185 | |
186 | const Host::MonitorChildProcessCallback callback = info->callback; |
187 | void * const callback_baton = info->callback_baton; |
188 | const bool monitor_signals = info->monitor_signals; |
189 | |
190 | assert (info->pid <= UINT32_MAX)((info->pid <= (4294967295U)) ? static_cast<void> (0) : __assert_fail ("info->pid <= (4294967295U)", "/tmp/buildd/llvm-toolchain-snapshot-3.9~svn267387/tools/lldb/source/Host/common/Host.cpp" , 190, __PRETTY_FUNCTION__)); |
191 | const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid; |
| 3 | | Assuming 'monitor_signals' is 0 | |
|
| |
192 | |
193 | delete info; |
| |
194 | |
195 | int status = -1; |
196 | #if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) |
197 | #define __WALL0x40000000 0 |
198 | #endif |
199 | const int options = __WALL0x40000000; |
200 | |
201 | #ifdef __linux__1 |
202 | |
203 | struct sigaction sigUsr1Action; |
204 | memset(&sigUsr1Action, 0, sizeof(sigUsr1Action)); |
205 | sigUsr1Action.sa_handler__sigaction_handler.sa_handler = SigUsr1Handler; |
206 | ::sigaction(SIGUSR110, &sigUsr1Action, nullptr); |
207 | #endif // __linux__ |
208 | |
209 | while (1) |
| 6 | | Loop condition is true. Entering loop body | |
|
210 | { |
211 | log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1)); |
212 | if (log) |
| 7 | | Assuming 'log' is non-null | |
|
| |
213 | log->Printf("%s ::waitpid (pid = %" PRIi32"i" ", &status, options = %i)...", function, pid, options); |
214 | |
215 | if (CheckForMonitorCancellation ()) |
| |
216 | break; |
217 | |
218 | |
219 | const ::pid_t wait_pid = ::waitpid (pid, &status, options); |
220 | |
221 | if (CheckForMonitorCancellation ()) |
| |
222 | break; |
223 | |
224 | if (wait_pid == -1) |
| |
225 | { |
226 | if (errno(*__errno_location ()) == EINTR4) |
| |
227 | continue; |
228 | else |
229 | { |
230 | if (log) |
| |
231 | log->Printf ("%s (arg = %p) thread exiting because waitpid failed (%s)...", __FUNCTION__, arg, strerror(errno(*__errno_location ()))); |
| 14 | | Use of memory after it is freed |
|
232 | break; |
233 | } |
234 | } |
235 | else if (wait_pid > 0) |
236 | { |
237 | bool exited = false; |
238 | int signal = 0; |
239 | int exit_status = 0; |
240 | const char *status_cstr = NULL__null; |
241 | if (WIFSTOPPED(status)((((*(int *) &(status))) & 0xff) == 0x7f)) |
242 | { |
243 | signal = WSTOPSIG(status)((((*(int *) &(status))) & 0xff00) >> 8); |
244 | status_cstr = "STOPPED"; |
245 | } |
246 | else if (WIFEXITED(status)((((*(int *) &(status))) & 0x7f) == 0)) |
247 | { |
248 | exit_status = WEXITSTATUS(status)((((*(int *) &(status))) & 0xff00) >> 8); |
249 | status_cstr = "EXITED"; |
250 | exited = true; |
251 | } |
252 | else if (WIFSIGNALED(status)(((signed char) ((((*(int *) &(status))) & 0x7f) + 1) >> 1) > 0)) |
253 | { |
254 | signal = WTERMSIG(status)(((*(int *) &(status))) & 0x7f); |
255 | status_cstr = "SIGNALED"; |
256 | if (wait_pid == abs(pid)) { |
257 | exited = true; |
258 | exit_status = -1; |
259 | } |
260 | } |
261 | else |
262 | { |
263 | status_cstr = "(\?\?\?)"; |
264 | } |
265 | |
266 | |
267 | { |
268 | #ifndef __linux__1 |
269 | ScopedPThreadCancelDisabler pthread_cancel_disabler; |
270 | #endif |
271 | |
272 | log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1)); |
273 | if (log) |
274 | log->Printf ("%s ::waitpid (pid = %" PRIi32"i" ", &status, options = %i) => pid = %" PRIi32"i" ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", |
275 | function, |
276 | pid, |
277 | options, |
278 | wait_pid, |
279 | status, |
280 | status_cstr, |
281 | signal, |
282 | exit_status); |
283 | |
284 | if (exited || (signal != 0 && monitor_signals)) |
285 | { |
286 | bool callback_return = false; |
287 | if (callback) |
288 | callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status); |
289 | |
290 | |
291 | if (exited && wait_pid == abs(pid)) |
292 | { |
293 | if (log) |
294 | log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg); |
295 | break; |
296 | } |
297 | |
298 | |
299 | if (callback_return) |
300 | { |
301 | if (log) |
302 | log->Printf ("%s (arg = %p) thread exiting because callback returned true...", __FUNCTION__, arg); |
303 | break; |
304 | } |
305 | } |
306 | } |
307 | } |
308 | } |
309 | |
310 | log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1)); |
311 | if (log) |
312 | log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg); |
313 | |
314 | return NULL__null; |
315 | } |
316 | |
317 | #endif // #if !defined (__APPLE__) && !defined (_WIN32) |
318 | |
319 | #if !defined (__APPLE__) |
320 | |
321 | void |
322 | Host::SystemLog (SystemLogType type, const char *format, va_list args) |
323 | { |
324 | vfprintf (stderrstderr, format, args); |
325 | } |
326 | |
327 | #endif |
328 | |
329 | void |
330 | Host::SystemLog (SystemLogType type, const char *format, ...) |
331 | { |
332 | va_list args; |
333 | va_start (args, format)__builtin_va_start(args, format); |
334 | SystemLog (type, format, args); |
335 | va_end (args)__builtin_va_end(args); |
336 | } |
337 | |
338 | lldb::pid_t |
339 | Host::GetCurrentProcessID() |
340 | { |
341 | return ::getpid(); |
342 | } |
343 | |
344 | #ifndef _WIN32 |
345 | |
346 | lldb::tid_t |
347 | Host::GetCurrentThreadID() |
348 | { |
349 | #if defined (__APPLE__) |
350 | |
351 | |
352 | |
353 | thread_port_t thread_self = mach_thread_self(); |
354 | mach_port_deallocate(mach_task_self(), thread_self); |
355 | return thread_self; |
356 | #elif defined(__FreeBSD__) |
357 | return lldb::tid_t(pthread_getthreadid_np()); |
358 | #elif defined(__ANDROID_NDK__) |
359 | return lldb::tid_t(gettid()); |
360 | #elif defined(__linux__1) |
361 | return lldb::tid_t(syscall(SYS_gettid186)); |
362 | #else |
363 | return lldb::tid_t(pthread_self()); |
364 | #endif |
365 | } |
366 | |
367 | lldb::thread_t |
368 | Host::GetCurrentThread () |
369 | { |
370 | return lldb::thread_t(pthread_self()); |
371 | } |
372 | |
373 | const char * |
374 | Host::GetSignalAsCString (int signo) |
375 | { |
376 | switch (signo) |
377 | { |
378 | case SIGHUP1: return "SIGHUP"; |
379 | case SIGINT2: return "SIGINT"; |
380 | case SIGQUIT3: return "SIGQUIT"; |
381 | case SIGILL4: return "SIGILL"; |
382 | case SIGTRAP5: return "SIGTRAP"; |
383 | case SIGABRT6: return "SIGABRT"; |
384 | #if defined(SIGPOLL29) |
385 | #if !defined(SIGIO29) || (SIGPOLL29 != SIGIO29) |
386 | |
387 | |
388 | case SIGPOLL29: return "SIGPOLL"; |
389 | #endif |
390 | #endif |
391 | #if defined(SIGEMT) |
392 | case SIGEMT: return "SIGEMT"; |
393 | #endif |
394 | case SIGFPE8: return "SIGFPE"; |
395 | case SIGKILL9: return "SIGKILL"; |
396 | case SIGBUS7: return "SIGBUS"; |
397 | case SIGSEGV11: return "SIGSEGV"; |
398 | case SIGSYS31: return "SIGSYS"; |
399 | case SIGPIPE13: return "SIGPIPE"; |
400 | case SIGALRM14: return "SIGALRM"; |
401 | case SIGTERM15: return "SIGTERM"; |
402 | case SIGURG23: return "SIGURG"; |
403 | case SIGSTOP19: return "SIGSTOP"; |
404 | case SIGTSTP20: return "SIGTSTP"; |
405 | case SIGCONT18: return "SIGCONT"; |
406 | case SIGCHLD17: return "SIGCHLD"; |
407 | case SIGTTIN21: return "SIGTTIN"; |
408 | case SIGTTOU22: return "SIGTTOU"; |
409 | #if defined(SIGIO29) |
410 | case SIGIO29: return "SIGIO"; |
411 | #endif |
412 | case SIGXCPU24: return "SIGXCPU"; |
413 | case SIGXFSZ25: return "SIGXFSZ"; |
414 | case SIGVTALRM26: return "SIGVTALRM"; |
415 | case SIGPROF27: return "SIGPROF"; |
416 | #if defined(SIGWINCH28) |
417 | case SIGWINCH28: return "SIGWINCH"; |
418 | #endif |
419 | #if defined(SIGINFO) |
420 | case SIGINFO: return "SIGINFO"; |
421 | #endif |
422 | case SIGUSR110: return "SIGUSR1"; |
423 | case SIGUSR212: return "SIGUSR2"; |
424 | default: |
425 | break; |
426 | } |
427 | return NULL__null; |
428 | } |
429 | |
430 | #endif |
431 | |
432 | #ifndef _WIN32 |
433 | |
434 | lldb::thread_key_t |
435 | Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) |
436 | { |
437 | pthread_key_t key; |
438 | ::pthread_key_create (&key, callback); |
439 | return key; |
440 | } |
441 | |
442 | void* |
443 | Host::ThreadLocalStorageGet(lldb::thread_key_t key) |
444 | { |
445 | return ::pthread_getspecific (key); |
446 | } |
447 | |
448 | void |
449 | Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) |
450 | { |
451 | ::pthread_setspecific (key, value); |
452 | } |
453 | |
454 | #endif |
455 | |
456 | #if !defined (__APPLE__) // see Host.mm |
457 | |
458 | bool |
459 | Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) |
460 | { |
461 | bundle.Clear(); |
462 | return false; |
463 | } |
464 | |
465 | bool |
466 | Host::ResolveExecutableInBundle (FileSpec &file) |
467 | { |
468 | return false; |
469 | } |
470 | #endif |
471 | |
472 | #ifndef _WIN32 |
473 | |
474 | FileSpec |
475 | Host::GetModuleFileSpecForHostAddress (const void *host_addr) |
476 | { |
477 | FileSpec module_filespec; |
478 | #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) |
479 | Dl_info info; |
480 | if (::dladdr (host_addr, &info)) |
481 | { |
482 | if (info.dli_fname) |
483 | module_filespec.SetFile(info.dli_fname, true); |
484 | } |
485 | #endif |
486 | return module_filespec; |
487 | } |
488 | |
489 | #endif |
490 | |
491 | #if !defined(__linux__1) |
492 | bool |
493 | Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) |
494 | { |
495 | return false; |
496 | } |
497 | #endif |
498 | |
499 | struct ShellInfo |
500 | { |
501 | ShellInfo () : |
502 | process_reaped (false), |
503 | can_delete (false), |
504 | pid (LLDB_INVALID_PROCESS_ID0), |
505 | signo(-1), |
506 | status(-1) |
507 | { |
508 | } |
509 | |
510 | lldb_private::Predicate<bool> process_reaped; |
511 | lldb_private::Predicate<bool> can_delete; |
512 | lldb::pid_t pid; |
513 | int signo; |
514 | int status; |
515 | }; |
516 | |
517 | static bool |
518 | MonitorShellCommand (void *callback_baton, |
519 | lldb::pid_t pid, |
520 | bool exited, |
521 | int signo, |
522 | int status) |
523 | { |
524 | ShellInfo *shell_info = (ShellInfo *)callback_baton; |
525 | shell_info->pid = pid; |
526 | shell_info->signo = signo; |
527 | shell_info->status = status; |
528 | |
529 | |
530 | shell_info->process_reaped.SetValue(1, eBroadcastAlways); |
531 | |
532 | |
533 | shell_info->can_delete.WaitForValueEqualTo(true); |
534 | |
535 | usleep(1000); |
536 | |
537 | delete shell_info; |
538 | return true; |
539 | } |
540 | |
541 | Error |
542 | Host::RunShellCommand(const char *command, |
543 | const FileSpec &working_dir, |
544 | int *status_ptr, |
545 | int *signo_ptr, |
546 | std::string *command_output_ptr, |
547 | uint32_t timeout_sec, |
548 | bool run_in_default_shell) |
549 | { |
550 | return RunShellCommand(Args(command), working_dir, status_ptr, signo_ptr, command_output_ptr, timeout_sec, run_in_default_shell); |
551 | } |
552 | |
553 | Error |
554 | Host::RunShellCommand(const Args &args, |
555 | const FileSpec &working_dir, |
556 | int *status_ptr, |
557 | int *signo_ptr, |
558 | std::string *command_output_ptr, |
559 | uint32_t timeout_sec, |
560 | bool run_in_default_shell) |
561 | { |
562 | Error error; |
563 | ProcessLaunchInfo launch_info; |
564 | launch_info.SetArchitecture(HostInfo::GetArchitecture()); |
565 | if (run_in_default_shell) |
566 | { |
567 | |
568 | launch_info.SetShell(HostInfo::GetDefaultShell()); |
569 | launch_info.GetArguments().AppendArguments(args); |
570 | const bool localhost = true; |
571 | const bool will_debug = false; |
572 | const bool first_arg_is_full_shell_command = false; |
573 | launch_info.ConvertArgumentsForLaunchingInShell (error, |
574 | localhost, |
575 | will_debug, |
576 | first_arg_is_full_shell_command, |
577 | 0); |
578 | } |
579 | else |
580 | { |
581 | |
582 | const bool first_arg_is_executable = true; |
583 | launch_info.SetArguments(args, first_arg_is_executable); |
584 | } |
585 | |
586 | if (working_dir) |
587 | launch_info.SetWorkingDirectory(working_dir); |
588 | llvm::SmallString<PATH_MAX4096> output_file_path; |
589 | |
590 | if (command_output_ptr) |
591 | { |
592 | |
593 | |
594 | |
595 | FileSpec tmpdir_file_spec; |
596 | if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) |
597 | { |
598 | tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); |
599 | llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), output_file_path); |
600 | } |
601 | else |
602 | { |
603 | llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", output_file_path); |
604 | } |
605 | } |
606 | |
607 | FileSpec output_file_spec{output_file_path.c_str(), false}; |
608 | |
609 | launch_info.AppendSuppressFileAction (STDIN_FILENO0, true, false); |
610 | if (output_file_spec) |
611 | { |
612 | launch_info.AppendOpenFileAction(STDOUT_FILENO1, output_file_spec, false, true); |
613 | launch_info.AppendDuplicateFileAction(STDOUT_FILENO1, STDERR_FILENO2); |
614 | } |
615 | else |
616 | { |
617 | launch_info.AppendSuppressFileAction (STDOUT_FILENO1, false, true); |
618 | launch_info.AppendSuppressFileAction (STDERR_FILENO2, false, true); |
619 | } |
620 | |
621 | |
622 | std::unique_ptr<ShellInfo> shell_info_ap (new ShellInfo()); |
623 | |
624 | const bool monitor_signals = false; |
625 | launch_info.SetMonitorProcessCallback(MonitorShellCommand, shell_info_ap.get(), monitor_signals); |
626 | |
627 | error = LaunchProcess (launch_info); |
628 | const lldb::pid_t pid = launch_info.GetProcessID(); |
629 | |
630 | if (error.Success() && pid == LLDB_INVALID_PROCESS_ID0) |
631 | error.SetErrorString("failed to get process ID"); |
632 | |
633 | if (error.Success()) |
634 | { |
635 | |
636 | |
637 | |
638 | |
639 | ShellInfo *shell_info = shell_info_ap.release(); |
640 | TimeValue *timeout_ptr = nullptr; |
641 | TimeValue timeout_time(TimeValue::Now()); |
642 | if (timeout_sec > 0) { |
643 | timeout_time.OffsetWithSeconds(timeout_sec); |
644 | timeout_ptr = &timeout_time; |
645 | } |
646 | bool timed_out = false; |
647 | shell_info->process_reaped.WaitForValueEqualTo(true, timeout_ptr, &timed_out); |
648 | if (timed_out) |
649 | { |
650 | error.SetErrorString("timed out waiting for shell command to complete"); |
651 | |
652 | |
653 | Kill (pid, SIGKILL9); |
654 | |
655 | timeout_time = TimeValue::Now(); |
656 | timeout_time.OffsetWithSeconds(1); |
657 | timed_out = false; |
658 | shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out); |
659 | } |
660 | else |
661 | { |
662 | if (status_ptr) |
663 | *status_ptr = shell_info->status; |
664 | |
665 | if (signo_ptr) |
666 | *signo_ptr = shell_info->signo; |
667 | |
668 | if (command_output_ptr) |
669 | { |
670 | command_output_ptr->clear(); |
671 | uint64_t file_size = output_file_spec.GetByteSize(); |
672 | if (file_size > 0) |
673 | { |
674 | if (file_size > command_output_ptr->max_size()) |
675 | { |
676 | error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string"); |
677 | } |
678 | else |
679 | { |
680 | std::vector<char> command_output(file_size); |
681 | output_file_spec.ReadFileContents(0, command_output.data(), file_size, &error); |
682 | if (error.Success()) |
683 | command_output_ptr->assign(command_output.data(), file_size); |
684 | } |
685 | } |
686 | } |
687 | } |
688 | shell_info->can_delete.SetValue(true, eBroadcastAlways); |
689 | } |
690 | |
691 | if (FileSystem::GetFileExists(output_file_spec)) |
692 | FileSystem::Unlink(output_file_spec); |
693 | |
694 | |
695 | |
696 | return error; |
697 | } |
698 | |
699 | |
700 | |
701 | |
702 | #if defined (__APPLE__) || defined (__linux__1) || defined (__FreeBSD__) || defined (__GLIBC__2) || defined(__NetBSD__) |
703 | #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) |
704 | |
705 | |
706 | |
707 | short |
708 | Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) |
709 | { |
710 | short flags = POSIX_SPAWN_SETSIGDEF0x04 | POSIX_SPAWN_SETSIGMASK0x08; |
711 | |
712 | #if defined (__APPLE__) |
713 | if (launch_info.GetFlags().Test (eLaunchFlagExec)) |
714 | flags |= POSIX_SPAWN_SETEXEC; |
715 | |
716 | if (launch_info.GetFlags().Test (eLaunchFlagDebug)) |
717 | flags |= POSIX_SPAWN_START_SUSPENDED; |
718 | |
719 | if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) |
720 | flags |= _POSIX_SPAWN_DISABLE_ASLR; |
721 | |
722 | if (launch_info.GetLaunchInSeparateProcessGroup()) |
723 | flags |= POSIX_SPAWN_SETPGROUP0x02; |
724 | |
725 | #ifdef POSIX_SPAWN_CLOEXEC_DEFAULT |
726 | #if defined (__APPLE__) && (defined (__x86_64__1) || defined (__i386__)) |
727 | static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; |
728 | if (g_use_close_on_exec_flag == eLazyBoolCalculate) |
729 | { |
730 | g_use_close_on_exec_flag = eLazyBoolNo; |
731 | |
732 | uint32_t major, minor, update; |
733 | if (HostInfo::GetOSVersion(major, minor, update)) |
734 | { |
735 | |
736 | if (major > 10 || (major == 10 && minor > 7)) |
737 | { |
738 | |
739 | g_use_close_on_exec_flag = eLazyBoolYes; |
740 | } |
741 | } |
742 | } |
743 | #else |
744 | static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; |
745 | #endif |
746 | |
747 | if (g_use_close_on_exec_flag == eLazyBoolYes) |
748 | flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; |
749 | #endif |
750 | #endif // #if defined (__APPLE__) |
751 | return flags; |
752 | } |
753 | |
754 | Error |
755 | Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid) |
756 | { |
757 | Error error; |
758 | Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST(1u << 14) | LIBLLDB_LOG_PROCESS(1u << 1))); |
759 | |
760 | posix_spawnattr_t attr; |
761 | error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX); |
762 | |
763 | if (error.Fail() || log) |
764 | error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); |
765 | if (error.Fail()) |
766 | return error; |
767 | |
768 | |
769 | |
770 | lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy); |
771 | |
772 | sigset_t no_signals; |
773 | sigset_t all_signals; |
774 | sigemptyset (&no_signals); |
775 | sigfillset (&all_signals); |
776 | ::posix_spawnattr_setsigmask(&attr, &no_signals); |
777 | #if defined (__linux__1) || defined (__FreeBSD__) |
778 | ::posix_spawnattr_setsigdefault(&attr, &no_signals); |
779 | #else |
780 | ::posix_spawnattr_setsigdefault(&attr, &all_signals); |
781 | #endif |
782 | |
783 | short flags = GetPosixspawnFlags(launch_info); |
784 | |
785 | error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); |
786 | if (error.Fail() || log) |
787 | error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); |
788 | if (error.Fail()) |
789 | return error; |
790 | |
791 | |
792 | |
793 | #if defined (__APPLE__) && !defined (__arm__) |
794 | |
795 | |
796 | |
797 | |
798 | |
799 | if (launch_info.GetShell() == nullptr) |
800 | { |
801 | |
802 | |
803 | |
804 | const ArchSpec &arch_spec = launch_info.GetArchitecture(); |
805 | cpu_type_t cpu = arch_spec.GetMachOCPUType(); |
806 | cpu_type_t sub = arch_spec.GetMachOCPUSubType(); |
807 | if (cpu != 0 && |
808 | cpu != static_cast<cpu_type_t>(UINT32_MAX(4294967295U)) && |
809 | cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE(0xFFFFFFFEu)) && |
810 | !(cpu == 0x01000007 && sub == 8)) |
811 | { |
812 | size_t ocount = 0; |
813 | error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX); |
814 | if (error.Fail() || log) |
815 | error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount); |
816 | |
817 | if (error.Fail() || ocount != 1) |
818 | return error; |
819 | } |
820 | } |
821 | |
822 | #endif |
823 | |
824 | const char *tmp_argv[2]; |
825 | char * const *argv = const_cast<char * const*>(launch_info.GetArguments().GetConstArgumentVector()); |
826 | char * const *envp = const_cast<char * const*>(launch_info.GetEnvironmentEntries().GetConstArgumentVector()); |
827 | if (argv == NULL__null) |
828 | { |
829 | |
830 | |
831 | |
832 | tmp_argv[0] = exe_path; |
833 | tmp_argv[1] = NULL__null; |
834 | argv = const_cast<char * const*>(tmp_argv); |
835 | } |
836 | |
837 | #if !defined (__APPLE__) |
838 | |
839 | char current_dir[PATH_MAX4096]; |
840 | current_dir[0] = '\0'; |
841 | #endif |
842 | |
843 | FileSpec working_dir{launch_info.GetWorkingDirectory()}; |
844 | if (working_dir) |
845 | { |
846 | #if defined (__APPLE__) |
847 | |
848 | if (__pthread_chdir(working_dir.GetCString()) < 0) { |
849 | if (errno(*__errno_location ()) == ENOENT2) { |
850 | error.SetErrorStringWithFormat("No such file or directory: %s", |
851 | working_dir.GetCString()); |
852 | } else if (errno(*__errno_location ()) == ENOTDIR20) { |
853 | error.SetErrorStringWithFormat("Path doesn't name a directory: %s", |
854 | working_dir.GetCString()); |
855 | } else { |
856 | error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution."); |
857 | } |
858 | return error; |
859 | } |
860 | #else |
861 | if (::getcwd(current_dir, sizeof(current_dir)) == NULL__null) |
862 | { |
863 | error.SetError(errno(*__errno_location ()), eErrorTypePOSIX); |
864 | error.LogIfError(log, "unable to save the current directory"); |
865 | return error; |
866 | } |
867 | |
868 | if (::chdir(working_dir.GetCString()) == -1) |
869 | { |
870 | error.SetError(errno(*__errno_location ()), eErrorTypePOSIX); |
871 | error.LogIfError(log, "unable to change working directory to %s", |
872 | working_dir.GetCString()); |
873 | return error; |
874 | } |
875 | #endif |
876 | } |
877 | |
878 | ::pid_t result_pid = LLDB_INVALID_PROCESS_ID0; |
879 | const size_t num_file_actions = launch_info.GetNumFileActions (); |
880 | if (num_file_actions > 0) |
881 | { |
882 | posix_spawn_file_actions_t file_actions; |
883 | error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX); |
884 | if (error.Fail() || log) |
885 | error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); |
886 | if (error.Fail()) |
887 | return error; |
888 | |
889 | |
890 | |
891 | lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy); |
892 | |
893 | for (size_t i=0; i<num_file_actions; ++i) |
894 | { |
895 | const FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i); |
896 | if (launch_file_action) |
897 | { |
898 | if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, error)) |
899 | return error; |
900 | } |
901 | } |
902 | |
903 | error.SetError(::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), eErrorTypePOSIX); |
904 | |
905 | if (error.Fail() || log) |
906 | { |
907 | error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", result_pid, |
908 | exe_path, static_cast<void *>(&file_actions), static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), |
909 | reinterpret_cast<const void *>(envp)); |
910 | if (log) |
911 | { |
912 | for (int ii=0; argv[ii]; ++ii) |
913 | log->Printf("argv[%i] = '%s'", ii, argv[ii]); |
914 | } |
915 | } |
916 | |
917 | } |
918 | else |
919 | { |
920 | error.SetError(::posix_spawnp(&result_pid, exe_path, NULL__null, &attr, argv, envp), eErrorTypePOSIX); |
921 | |
922 | if (error.Fail() || log) |
923 | { |
924 | error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )", |
925 | result_pid, exe_path, static_cast<void *>(&attr), reinterpret_cast<const void *>(argv), |
926 | reinterpret_cast<const void *>(envp)); |
927 | if (log) |
928 | { |
929 | for (int ii=0; argv[ii]; ++ii) |
930 | log->Printf("argv[%i] = '%s'", ii, argv[ii]); |
931 | } |
932 | } |
933 | } |
934 | pid = result_pid; |
935 | |
936 | if (working_dir) |
937 | { |
938 | #if defined (__APPLE__) |
939 | |
940 | __pthread_fchdir (-1); |
941 | #else |
942 | if (::chdir(current_dir) == -1 && error.Success()) |
943 | { |
944 | error.SetError(errno(*__errno_location ()), eErrorTypePOSIX); |
945 | error.LogIfError(log, "unable to change current directory back to %s", |
946 | current_dir); |
947 | } |
948 | #endif |
949 | } |
950 | |
951 | return error; |
952 | } |
953 | |
954 | bool |
955 | Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error) |
956 | { |
957 | if (info == NULL__null) |
958 | return false; |
959 | |
960 | posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); |
961 | |
962 | switch (info->GetAction()) |
963 | { |
964 | case FileAction::eFileActionNone: |
965 | error.Clear(); |
966 | break; |
967 | |
968 | case FileAction::eFileActionClose: |
969 | if (info->GetFD() == -1) |
970 | error.SetErrorString("invalid fd for posix_spawn_file_actions_addclose(...)"); |
971 | else |
972 | { |
973 | error.SetError(::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX); |
974 | if (log && (error.Fail() || log)) |
975 | error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)", |
976 | static_cast<void *>(file_actions), info->GetFD()); |
977 | } |
978 | break; |
979 | |
980 | case FileAction::eFileActionDuplicate: |
981 | if (info->GetFD() == -1) |
982 | error.SetErrorString("invalid fd for posix_spawn_file_actions_adddup2(...)"); |
983 | else if (info->GetActionArgument() == -1) |
984 | error.SetErrorString("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); |
985 | else |
986 | { |
987 | error.SetError( |
988 | ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()), |
989 | eErrorTypePOSIX); |
990 | if (log && (error.Fail() || log)) |
991 | error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", |
992 | static_cast<void *>(file_actions), info->GetFD(), info->GetActionArgument()); |
993 | } |
994 | break; |
995 | |
996 | case FileAction::eFileActionOpen: |
997 | if (info->GetFD() == -1) |
998 | error.SetErrorString("invalid fd in posix_spawn_file_actions_addopen(...)"); |
999 | else |
1000 | { |
1001 | int oflag = info->GetActionArgument(); |
1002 | |
1003 | mode_t mode = 0; |
1004 | |
1005 | if (oflag & O_CREAT0100) |
1006 | mode = 0640; |
1007 | |
1008 | error.SetError( |
1009 | ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), info->GetPath(), oflag, mode), |
1010 | eErrorTypePOSIX); |
1011 | if (error.Fail() || log) |
1012 | error.PutToLog(log, |
1013 | "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)", |
1014 | static_cast<void *>(file_actions), info->GetFD(), info->GetPath(), oflag, mode); |
1015 | } |
1016 | break; |
1017 | } |
1018 | return error.Success(); |
1019 | } |
1020 | #endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__) |
1021 | #endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__) |
1022 | |
1023 | #if defined(__linux__1) || defined(__FreeBSD__) || defined(__GLIBC__2) || defined(__NetBSD__) || defined(_WIN32) |
1024 | |
1025 | |
1026 | |
1027 | Error |
1028 | Host::LaunchProcess (ProcessLaunchInfo &launch_info) |
1029 | { |
1030 | std::unique_ptr<ProcessLauncher> delegate_launcher; |
1031 | #if defined(_WIN32) |
1032 | delegate_launcher.reset(new ProcessLauncherWindows()); |
1033 | #elif defined(__ANDROID__) || defined(__ANDROID_NDK__) |
1034 | delegate_launcher.reset(new ProcessLauncherAndroid()); |
1035 | #else |
1036 | delegate_launcher.reset(new ProcessLauncherPosix()); |
1037 | #endif |
1038 | MonitoringProcessLauncher launcher(std::move(delegate_launcher)); |
1039 | |
1040 | Error error; |
1041 | HostProcess process = launcher.LaunchProcess(launch_info, error); |
1042 | |
1043 | |
1044 | |
1045 | launch_info.SetProcessID(process.GetProcessId()); |
1046 | |
1047 | return error; |
1048 | } |
1049 | #endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) |
1050 | |
1051 | #ifndef _WIN32 |
1052 | void |
1053 | Host::Kill(lldb::pid_t pid, int signo) |
1054 | { |
1055 | ::kill(pid, signo); |
1056 | } |
1057 | |
1058 | #endif |
1059 | |
1060 | #if !defined (__APPLE__) |
1061 | bool |
1062 | Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) |
1063 | { |
1064 | return false; |
1065 | } |
1066 | |
1067 | void |
1068 | Host::SetCrashDescriptionWithFormat (const char *format, ...) |
1069 | { |
1070 | } |
1071 | |
1072 | void |
1073 | Host::SetCrashDescription (const char *description) |
1074 | { |
1075 | } |
1076 | |
1077 | #endif |
1078 | |
1079 | const UnixSignalsSP & |
1080 | Host::GetUnixSignals() |
1081 | { |
1082 | static const auto s_unix_signals_sp = UnixSignals::Create(HostInfo::GetArchitecture()); |
1083 | return s_unix_signals_sp; |
1084 | } |