File: | tools/lldb/source/Host/common/Host.cpp |
Location: | line 288, column 29 |
Description: | Use of memory after it is freed |
1 | //===-- Host.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 | #include "lldb/lldb-python.h" | |||
11 | ||||
12 | // C includes | |||
13 | #include <errno(*__errno_location ()).h> | |||
14 | #include <limits.h> | |||
15 | #include <stdlib.h> | |||
16 | #include <sys/types.h> | |||
17 | #ifdef _WIN32 | |||
18 | #include "lldb/Host/windows/windows.h" | |||
19 | #include <winsock2.h> | |||
20 | #include <ws2tcpip.h> | |||
21 | #else | |||
22 | #include <unistd.h> | |||
23 | #include <dlfcn.h> | |||
24 | #include <grp.h> | |||
25 | #include <netdb.h> | |||
26 | #include <pwd.h> | |||
27 | #include <sys/stat.h> | |||
28 | #endif | |||
29 | ||||
30 | #if !defined (__GNU__) && !defined (_WIN32) | |||
31 | // Does not exist under GNU/HURD or Windows | |||
32 | #include <sys/sysctl.h> | |||
33 | #endif | |||
34 | ||||
35 | #if defined (__APPLE__) | |||
36 | #include <mach/mach_port.h> | |||
37 | #include <mach/mach_init.h> | |||
38 | #include <mach-o/dyld.h> | |||
39 | #endif | |||
40 | ||||
41 | #if defined (__linux__1) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__) || defined(__NetBSD__) | |||
42 | #include <spawn.h> | |||
43 | #include <sys/wait.h> | |||
44 | #include <sys/syscall.h> | |||
45 | #endif | |||
46 | ||||
47 | #if defined (__FreeBSD__) | |||
48 | #include <pthread_np.h> | |||
49 | #endif | |||
50 | ||||
51 | // C++ includes | |||
52 | #include <limits> | |||
53 | ||||
54 | #include "lldb/Host/Host.h" | |||
55 | #include "lldb/Host/HostInfo.h" | |||
56 | #include "lldb/Core/ArchSpec.h" | |||
57 | #include "lldb/Core/ConstString.h" | |||
58 | #include "lldb/Core/Debugger.h" | |||
59 | #include "lldb/Core/Error.h" | |||
60 | #include "lldb/Core/Log.h" | |||
61 | #include "lldb/Core/Module.h" | |||
62 | #include "lldb/Core/StreamString.h" | |||
63 | #include "lldb/Core/ThreadSafeSTLMap.h" | |||
64 | #include "lldb/Host/Config.h" | |||
65 | #include "lldb/Host/Endian.h" | |||
66 | #include "lldb/Host/FileSpec.h" | |||
67 | #include "lldb/Host/FileSystem.h" | |||
68 | #include "lldb/Host/Mutex.h" | |||
69 | #include "lldb/lldb-private-forward.h" | |||
70 | #include "lldb/Target/FileAction.h" | |||
71 | #include "lldb/Target/Process.h" | |||
72 | #include "lldb/Target/ProcessLaunchInfo.h" | |||
73 | #include "lldb/Target/TargetList.h" | |||
74 | #include "lldb/Utility/CleanUp.h" | |||
75 | ||||
76 | #include "llvm/ADT/STLExtras.h" | |||
77 | #include "llvm/ADT/SmallString.h" | |||
78 | #include "llvm/Support/Host.h" | |||
79 | #include "llvm/Support/Path.h" | |||
80 | #include "llvm/Support/raw_ostream.h" | |||
81 | ||||
82 | #if defined (__APPLE__) | |||
83 | #ifndef _POSIX_SPAWN_DISABLE_ASLR | |||
84 | #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 | |||
85 | #endif | |||
86 | ||||
87 | extern "C" | |||
88 | { | |||
89 | int __pthread_chdir(const char *path); | |||
90 | int __pthread_fchdir (int fildes); | |||
91 | } | |||
92 | ||||
93 | #endif | |||
94 | ||||
95 | using namespace lldb; | |||
96 | using namespace lldb_private; | |||
97 | ||||
98 | // Define maximum thread name length | |||
99 | #if defined (__linux__1) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__NetBSD__) | |||
100 | uint32_t const Host::MAX_THREAD_NAME_LENGTH = 16; | |||
101 | #else | |||
102 | uint32_t const Host::MAX_THREAD_NAME_LENGTH = std::numeric_limits<uint32_t>::max (); | |||
103 | #endif | |||
104 | ||||
105 | #if !defined (__APPLE__) && !defined (_WIN32) | |||
106 | struct MonitorInfo | |||
107 | { | |||
108 | lldb::pid_t pid; // The process ID to monitor | |||
109 | Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals | |||
110 | void *callback_baton; // The callback baton for the callback function | |||
111 | bool monitor_signals; // If true, call the callback when "pid" gets signaled. | |||
112 | }; | |||
113 | ||||
114 | static thread_result_t | |||
115 | MonitorChildProcessThreadFunction (void *arg); | |||
116 | ||||
117 | lldb::thread_t | |||
118 | Host::StartMonitoringChildProcess | |||
119 | ( | |||
120 | Host::MonitorChildProcessCallback callback, | |||
121 | void *callback_baton, | |||
122 | lldb::pid_t pid, | |||
123 | bool monitor_signals | |||
124 | ) | |||
125 | { | |||
126 | lldb::thread_t thread = LLDB_INVALID_HOST_THREAD((lldb::thread_t)__null); | |||
127 | MonitorInfo * info_ptr = new MonitorInfo(); | |||
128 | ||||
129 | info_ptr->pid = pid; | |||
130 | info_ptr->callback = callback; | |||
131 | info_ptr->callback_baton = callback_baton; | |||
132 | info_ptr->monitor_signals = monitor_signals; | |||
133 | ||||
134 | char thread_name[256]; | |||
135 | ||||
136 | if (Host::MAX_THREAD_NAME_LENGTH <= 16) | |||
137 | { | |||
138 | // On some platforms, the thread name is limited to 16 characters. We need to | |||
139 | // abbreviate there or the pid info would get truncated. | |||
140 | ::snprintf (thread_name, sizeof(thread_name), "wait4(%" PRIu64"l" "u" ")", pid); | |||
141 | } | |||
142 | else | |||
143 | { | |||
144 | ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64"l" "u" ")>", pid); | |||
145 | } | |||
146 | ||||
147 | thread = ThreadCreate (thread_name, | |||
148 | MonitorChildProcessThreadFunction, | |||
149 | info_ptr, | |||
150 | NULL__null); | |||
151 | ||||
152 | return thread; | |||
153 | } | |||
154 | ||||
155 | //------------------------------------------------------------------ | |||
156 | // Scoped class that will disable thread canceling when it is | |||
157 | // constructed, and exception safely restore the previous value it | |||
158 | // when it goes out of scope. | |||
159 | //------------------------------------------------------------------ | |||
160 | class ScopedPThreadCancelDisabler | |||
161 | { | |||
162 | public: | |||
163 | ScopedPThreadCancelDisabler() | |||
164 | { | |||
165 | // Disable the ability for this thread to be cancelled | |||
166 | int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLEPTHREAD_CANCEL_DISABLE, &m_old_state); | |||
167 | if (err != 0) | |||
168 | m_old_state = -1; | |||
169 | ||||
170 | } | |||
171 | ||||
172 | ~ScopedPThreadCancelDisabler() | |||
173 | { | |||
174 | // Restore the ability for this thread to be cancelled to what it | |||
175 | // previously was. | |||
176 | if (m_old_state != -1) | |||
177 | ::pthread_setcancelstate (m_old_state, 0); | |||
178 | } | |||
179 | private: | |||
180 | int m_old_state; // Save the old cancelability state. | |||
181 | }; | |||
182 | ||||
183 | static thread_result_t | |||
184 | MonitorChildProcessThreadFunction (void *arg) | |||
185 | { | |||
186 | Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
187 | const char *function = __FUNCTION__; | |||
188 | if (log) | |||
| ||||
189 | log->Printf ("%s (arg = %p) thread starting...", function, arg); | |||
190 | ||||
191 | MonitorInfo *info = (MonitorInfo *)arg; | |||
192 | ||||
193 | const Host::MonitorChildProcessCallback callback = info->callback; | |||
194 | void * const callback_baton = info->callback_baton; | |||
195 | const bool monitor_signals = info->monitor_signals; | |||
196 | ||||
197 | assert (info->pid <= UINT32_MAX)((info->pid <= (4294967295U)) ? static_cast<void> (0) : __assert_fail ("info->pid <= (4294967295U)", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn216889/tools/lldb/source/Host/common/Host.cpp" , 197, __PRETTY_FUNCTION__)); | |||
198 | const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid; | |||
199 | ||||
200 | delete info; | |||
201 | ||||
202 | int status = -1; | |||
203 | #if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) | |||
204 | #define __WALL0x40000000 0 | |||
205 | #endif | |||
206 | const int options = __WALL0x40000000; | |||
207 | ||||
208 | while (1) | |||
209 | { | |||
210 | log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1)); | |||
211 | if (log) | |||
212 | log->Printf("%s ::wait_pid (pid = %" PRIi32"i" ", &status, options = %i)...", function, pid, options); | |||
213 | ||||
214 | // Wait for all child processes | |||
215 | ::pthread_testcancel (); | |||
216 | // Get signals from all children with same process group of pid | |||
217 | const ::pid_t wait_pid = ::waitpid (pid, &status, options); | |||
218 | ::pthread_testcancel (); | |||
219 | ||||
220 | if (wait_pid == -1) | |||
221 | { | |||
222 | if (errno(*__errno_location ()) == EINTR4) | |||
223 | continue; | |||
224 | else | |||
225 | { | |||
226 | if (log) | |||
227 | log->Printf ("%s (arg = %p) thread exiting because waitpid failed (%s)...", __FUNCTION__, arg, strerror(errno(*__errno_location ()))); | |||
228 | break; | |||
229 | } | |||
230 | } | |||
231 | else if (wait_pid > 0) | |||
232 | { | |||
233 | bool exited = false; | |||
234 | int signal = 0; | |||
235 | int exit_status = 0; | |||
236 | const char *status_cstr = NULL__null; | |||
237 | if (WIFSTOPPED(status)((((*(int *) &(status))) & 0xff) == 0x7f)) | |||
238 | { | |||
239 | signal = WSTOPSIG(status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
240 | status_cstr = "STOPPED"; | |||
241 | } | |||
242 | else if (WIFEXITED(status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
243 | { | |||
244 | exit_status = WEXITSTATUS(status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
245 | status_cstr = "EXITED"; | |||
246 | exited = true; | |||
247 | } | |||
248 | else if (WIFSIGNALED(status)(((signed char) ((((*(int *) &(status))) & 0x7f) + 1) >> 1) > 0)) | |||
249 | { | |||
250 | signal = WTERMSIG(status)(((*(int *) &(status))) & 0x7f); | |||
251 | status_cstr = "SIGNALED"; | |||
252 | if (wait_pid == abs(pid)) { | |||
253 | exited = true; | |||
254 | exit_status = -1; | |||
255 | } | |||
256 | } | |||
257 | else | |||
258 | { | |||
259 | status_cstr = "(\?\?\?)"; | |||
260 | } | |||
261 | ||||
262 | // Scope for pthread_cancel_disabler | |||
263 | { | |||
264 | ScopedPThreadCancelDisabler pthread_cancel_disabler; | |||
265 | ||||
266 | log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1)); | |||
267 | if (log) | |||
268 | log->Printf ("%s ::waitpid (pid = %" PRIi32"i" ", &status, options = %i) => pid = %" PRIi32"i" ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", | |||
269 | function, | |||
270 | wait_pid, | |||
271 | options, | |||
272 | pid, | |||
273 | status, | |||
274 | status_cstr, | |||
275 | signal, | |||
276 | exit_status); | |||
277 | ||||
278 | if (exited || (signal != 0 && monitor_signals)) | |||
279 | { | |||
280 | bool callback_return = false; | |||
281 | if (callback) | |||
282 | callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status); | |||
283 | ||||
284 | // If our process exited, then this thread should exit | |||
285 | if (exited && wait_pid == abs(pid)) | |||
286 | { | |||
287 | if (log) | |||
288 | log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg); | |||
| ||||
289 | break; | |||
290 | } | |||
291 | // If the callback returns true, it means this process should | |||
292 | // exit | |||
293 | if (callback_return) | |||
294 | { | |||
295 | if (log) | |||
296 | log->Printf ("%s (arg = %p) thread exiting because callback returned true...", __FUNCTION__, arg); | |||
297 | break; | |||
298 | } | |||
299 | } | |||
300 | } | |||
301 | } | |||
302 | } | |||
303 | ||||
304 | log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1)); | |||
305 | if (log) | |||
306 | log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg); | |||
307 | ||||
308 | return NULL__null; | |||
309 | } | |||
310 | ||||
311 | #endif // #if !defined (__APPLE__) && !defined (_WIN32) | |||
312 | ||||
313 | #if !defined (__APPLE__) | |||
314 | ||||
315 | void | |||
316 | Host::SystemLog (SystemLogType type, const char *format, va_list args) | |||
317 | { | |||
318 | vfprintf (stderrstderr, format, args); | |||
319 | } | |||
320 | ||||
321 | #endif | |||
322 | ||||
323 | void | |||
324 | Host::SystemLog (SystemLogType type, const char *format, ...) | |||
325 | { | |||
326 | va_list args; | |||
327 | va_start (args, format)__builtin_va_start(args, format); | |||
328 | SystemLog (type, format, args); | |||
329 | va_end (args)__builtin_va_end(args); | |||
330 | } | |||
331 | ||||
332 | lldb::pid_t | |||
333 | Host::GetCurrentProcessID() | |||
334 | { | |||
335 | return ::getpid(); | |||
336 | } | |||
337 | ||||
338 | #ifndef _WIN32 | |||
339 | ||||
340 | lldb::tid_t | |||
341 | Host::GetCurrentThreadID() | |||
342 | { | |||
343 | #if defined (__APPLE__) | |||
344 | // Calling "mach_thread_self()" bumps the reference count on the thread | |||
345 | // port, so we need to deallocate it. mach_task_self() doesn't bump the ref | |||
346 | // count. | |||
347 | thread_port_t thread_self = mach_thread_self(); | |||
348 | mach_port_deallocate(mach_task_self(), thread_self); | |||
349 | return thread_self; | |||
350 | #elif defined(__FreeBSD__) | |||
351 | return lldb::tid_t(pthread_getthreadid_np()); | |||
352 | #elif defined(__linux__1) | |||
353 | return lldb::tid_t(syscall(SYS_gettid186)); | |||
354 | #else | |||
355 | return lldb::tid_t(pthread_self()); | |||
356 | #endif | |||
357 | } | |||
358 | ||||
359 | lldb::thread_t | |||
360 | Host::GetCurrentThread () | |||
361 | { | |||
362 | return lldb::thread_t(pthread_self()); | |||
363 | } | |||
364 | ||||
365 | const char * | |||
366 | Host::GetSignalAsCString (int signo) | |||
367 | { | |||
368 | switch (signo) | |||
369 | { | |||
370 | case SIGHUP1: return "SIGHUP"; // 1 hangup | |||
371 | case SIGINT2: return "SIGINT"; // 2 interrupt | |||
372 | case SIGQUIT3: return "SIGQUIT"; // 3 quit | |||
373 | case SIGILL4: return "SIGILL"; // 4 illegal instruction (not reset when caught) | |||
374 | case SIGTRAP5: return "SIGTRAP"; // 5 trace trap (not reset when caught) | |||
375 | case SIGABRT6: return "SIGABRT"; // 6 abort() | |||
376 | #if defined(SIGPOLL29) | |||
377 | #if !defined(SIGIO29) || (SIGPOLL29 != SIGIO29) | |||
378 | // Under some GNU/Linux, SIGPOLL and SIGIO are the same. Causing the build to | |||
379 | // fail with 'multiple define cases with same value' | |||
380 | case SIGPOLL29: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) | |||
381 | #endif | |||
382 | #endif | |||
383 | #if defined(SIGEMT) | |||
384 | case SIGEMT: return "SIGEMT"; // 7 EMT instruction | |||
385 | #endif | |||
386 | case SIGFPE8: return "SIGFPE"; // 8 floating point exception | |||
387 | case SIGKILL9: return "SIGKILL"; // 9 kill (cannot be caught or ignored) | |||
388 | case SIGBUS7: return "SIGBUS"; // 10 bus error | |||
389 | case SIGSEGV11: return "SIGSEGV"; // 11 segmentation violation | |||
390 | case SIGSYS31: return "SIGSYS"; // 12 bad argument to system call | |||
391 | case SIGPIPE13: return "SIGPIPE"; // 13 write on a pipe with no one to read it | |||
392 | case SIGALRM14: return "SIGALRM"; // 14 alarm clock | |||
393 | case SIGTERM15: return "SIGTERM"; // 15 software termination signal from kill | |||
394 | case SIGURG23: return "SIGURG"; // 16 urgent condition on IO channel | |||
395 | case SIGSTOP19: return "SIGSTOP"; // 17 sendable stop signal not from tty | |||
396 | case SIGTSTP20: return "SIGTSTP"; // 18 stop signal from tty | |||
397 | case SIGCONT18: return "SIGCONT"; // 19 continue a stopped process | |||
398 | case SIGCHLD17: return "SIGCHLD"; // 20 to parent on child stop or exit | |||
399 | case SIGTTIN21: return "SIGTTIN"; // 21 to readers pgrp upon background tty read | |||
400 | case SIGTTOU22: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) | |||
401 | #if defined(SIGIO29) | |||
402 | case SIGIO29: return "SIGIO"; // 23 input/output possible signal | |||
403 | #endif | |||
404 | case SIGXCPU24: return "SIGXCPU"; // 24 exceeded CPU time limit | |||
405 | case SIGXFSZ25: return "SIGXFSZ"; // 25 exceeded file size limit | |||
406 | case SIGVTALRM26: return "SIGVTALRM"; // 26 virtual time alarm | |||
407 | case SIGPROF27: return "SIGPROF"; // 27 profiling time alarm | |||
408 | #if defined(SIGWINCH28) | |||
409 | case SIGWINCH28: return "SIGWINCH"; // 28 window size changes | |||
410 | #endif | |||
411 | #if defined(SIGINFO) | |||
412 | case SIGINFO: return "SIGINFO"; // 29 information request | |||
413 | #endif | |||
414 | case SIGUSR110: return "SIGUSR1"; // 30 user defined signal 1 | |||
415 | case SIGUSR212: return "SIGUSR2"; // 31 user defined signal 2 | |||
416 | default: | |||
417 | break; | |||
418 | } | |||
419 | return NULL__null; | |||
420 | } | |||
421 | ||||
422 | #endif | |||
423 | ||||
424 | void | |||
425 | Host::WillTerminate () | |||
426 | { | |||
427 | } | |||
428 | ||||
429 | #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__1) // see macosx/Host.mm | |||
430 | ||||
431 | void | |||
432 | Host::ThreadCreated (const char *thread_name) | |||
433 | { | |||
434 | } | |||
435 | ||||
436 | void | |||
437 | Host::Backtrace (Stream &strm, uint32_t max_frames) | |||
438 | { | |||
439 | // TODO: Is there a way to backtrace the current process on other systems? | |||
440 | } | |||
441 | ||||
442 | size_t | |||
443 | Host::GetEnvironment (StringList &env) | |||
444 | { | |||
445 | // TODO: Is there a way to the host environment for this process on other systems? | |||
446 | return 0; | |||
447 | } | |||
448 | ||||
449 | #endif // #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) | |||
450 | ||||
451 | struct HostThreadCreateInfo | |||
452 | { | |||
453 | std::string thread_name; | |||
454 | thread_func_t thread_fptr; | |||
455 | thread_arg_t thread_arg; | |||
456 | ||||
457 | HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) : | |||
458 | thread_name (name ? name : ""), | |||
459 | thread_fptr (fptr), | |||
460 | thread_arg (arg) | |||
461 | { | |||
462 | } | |||
463 | }; | |||
464 | ||||
465 | static thread_result_t | |||
466 | #ifdef _WIN32 | |||
467 | __stdcall | |||
468 | #endif | |||
469 | ThreadCreateTrampoline (thread_arg_t arg) | |||
470 | { | |||
471 | HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg; | |||
472 | Host::ThreadCreated (info->thread_name.c_str()); | |||
473 | thread_func_t thread_fptr = info->thread_fptr; | |||
474 | thread_arg_t thread_arg = info->thread_arg; | |||
475 | ||||
476 | Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2))); | |||
477 | if (log) | |||
478 | log->Printf("thread created"); | |||
479 | ||||
480 | delete info; | |||
481 | return thread_fptr (thread_arg); | |||
482 | } | |||
483 | ||||
484 | lldb::thread_t | |||
485 | Host::ThreadCreate | |||
486 | ( | |||
487 | const char *thread_name, | |||
488 | thread_func_t thread_fptr, | |||
489 | thread_arg_t thread_arg, | |||
490 | Error *error | |||
491 | ) | |||
492 | { | |||
493 | lldb::thread_t thread = LLDB_INVALID_HOST_THREAD((lldb::thread_t)__null); | |||
494 | ||||
495 | // Host::ThreadCreateTrampoline will delete this pointer for us. | |||
496 | HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg); | |||
497 | ||||
498 | #ifdef _WIN32 | |||
499 | thread = ::_beginthreadex(0, 0, ThreadCreateTrampoline, info_ptr, 0, NULL__null); | |||
500 | int err = thread <= 0 ? GetLastError() : 0; | |||
501 | #else | |||
502 | int err = ::pthread_create (&thread, NULL__null, ThreadCreateTrampoline, info_ptr); | |||
503 | #endif | |||
504 | if (err == 0) | |||
505 | { | |||
506 | if (error) | |||
507 | error->Clear(); | |||
508 | return thread; | |||
509 | } | |||
510 | ||||
511 | if (error) | |||
512 | error->SetError (err, eErrorTypePOSIX); | |||
513 | ||||
514 | return LLDB_INVALID_HOST_THREAD((lldb::thread_t)__null); | |||
515 | } | |||
516 | ||||
517 | #ifndef _WIN32 | |||
518 | ||||
519 | bool | |||
520 | Host::ThreadCancel (lldb::thread_t thread, Error *error) | |||
521 | { | |||
522 | int err = ::pthread_cancel (thread); | |||
523 | if (error) | |||
524 | error->SetError(err, eErrorTypePOSIX); | |||
525 | return err == 0; | |||
526 | } | |||
527 | ||||
528 | bool | |||
529 | Host::ThreadDetach (lldb::thread_t thread, Error *error) | |||
530 | { | |||
531 | int err = ::pthread_detach (thread); | |||
532 | if (error) | |||
533 | error->SetError(err, eErrorTypePOSIX); | |||
534 | return err == 0; | |||
535 | } | |||
536 | ||||
537 | bool | |||
538 | Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error) | |||
539 | { | |||
540 | int err = ::pthread_join (thread, thread_result_ptr); | |||
541 | if (error) | |||
542 | error->SetError(err, eErrorTypePOSIX); | |||
543 | return err == 0; | |||
544 | } | |||
545 | ||||
546 | lldb::thread_key_t | |||
547 | Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) | |||
548 | { | |||
549 | pthread_key_t key; | |||
550 | ::pthread_key_create (&key, callback); | |||
551 | return key; | |||
552 | } | |||
553 | ||||
554 | void* | |||
555 | Host::ThreadLocalStorageGet(lldb::thread_key_t key) | |||
556 | { | |||
557 | return ::pthread_getspecific (key); | |||
558 | } | |||
559 | ||||
560 | void | |||
561 | Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) | |||
562 | { | |||
563 | ::pthread_setspecific (key, value); | |||
564 | } | |||
565 | ||||
566 | bool | |||
567 | Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name) | |||
568 | { | |||
569 | #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 | |||
570 | lldb::pid_t curr_pid = Host::GetCurrentProcessID(); | |||
571 | lldb::tid_t curr_tid = Host::GetCurrentThreadID(); | |||
572 | if (pid == LLDB_INVALID_PROCESS_ID0) | |||
573 | pid = curr_pid; | |||
574 | ||||
575 | if (tid == LLDB_INVALID_THREAD_ID0) | |||
576 | tid = curr_tid; | |||
577 | ||||
578 | // Set the pthread name if possible | |||
579 | if (pid == curr_pid && tid == curr_tid) | |||
580 | { | |||
581 | if (::pthread_setname_np (name) == 0) | |||
582 | return true; | |||
583 | } | |||
584 | return false; | |||
585 | #elif defined (__FreeBSD__) | |||
586 | lldb::pid_t curr_pid = Host::GetCurrentProcessID(); | |||
587 | lldb::tid_t curr_tid = Host::GetCurrentThreadID(); | |||
588 | if (pid == LLDB_INVALID_PROCESS_ID0) | |||
589 | pid = curr_pid; | |||
590 | ||||
591 | if (tid == LLDB_INVALID_THREAD_ID0) | |||
592 | tid = curr_tid; | |||
593 | ||||
594 | // Set the pthread name if possible | |||
595 | if (pid == curr_pid && tid == curr_tid) | |||
596 | { | |||
597 | ::pthread_set_name_np (::pthread_self(), name); | |||
598 | return true; | |||
599 | } | |||
600 | return false; | |||
601 | #elif defined (__linux__1) || defined (__GLIBC__2) | |||
602 | void *fn = dlsym (RTLD_DEFAULT((void *) 0), "pthread_setname_np"); | |||
603 | if (fn) | |||
604 | { | |||
605 | lldb::pid_t curr_pid = Host::GetCurrentProcessID(); | |||
606 | lldb::tid_t curr_tid = Host::GetCurrentThreadID(); | |||
607 | if (pid == LLDB_INVALID_PROCESS_ID0) | |||
608 | pid = curr_pid; | |||
609 | ||||
610 | if (tid == LLDB_INVALID_THREAD_ID0) | |||
611 | tid = curr_tid; | |||
612 | ||||
613 | if (pid == curr_pid && tid == curr_tid) | |||
614 | { | |||
615 | int (*pthread_setname_np_func)(pthread_t thread, const char *name); | |||
616 | *reinterpret_cast<void **> (&pthread_setname_np_func) = fn; | |||
617 | ||||
618 | if (pthread_setname_np_func (::pthread_self(), name) == 0) | |||
619 | return true; | |||
620 | } | |||
621 | } | |||
622 | return false; | |||
623 | #else | |||
624 | return false; | |||
625 | #endif | |||
626 | } | |||
627 | ||||
628 | bool | |||
629 | Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, | |||
630 | const char *thread_name, size_t len) | |||
631 | { | |||
632 | std::unique_ptr<char[]> namebuf(new char[len+1]); | |||
633 | ||||
634 | // Thread names are coming in like '<lldb.comm.debugger.edit>' and | |||
635 | // '<lldb.comm.debugger.editline>'. So just chopping the end of the string | |||
636 | // off leads to a lot of similar named threads. Go through the thread name | |||
637 | // and search for the last dot and use that. | |||
638 | const char *lastdot = ::strrchr (thread_name, '.'); | |||
639 | ||||
640 | if (lastdot && lastdot != thread_name) | |||
641 | thread_name = lastdot + 1; | |||
642 | ::strncpy (namebuf.get(), thread_name, len); | |||
643 | namebuf[len] = 0; | |||
644 | ||||
645 | int namebuflen = strlen(namebuf.get()); | |||
646 | if (namebuflen > 0) | |||
647 | { | |||
648 | if (namebuf[namebuflen - 1] == '(' || namebuf[namebuflen - 1] == '>') | |||
649 | { | |||
650 | // Trim off trailing '(' and '>' characters for a bit more cleanup. | |||
651 | namebuflen--; | |||
652 | namebuf[namebuflen] = 0; | |||
653 | } | |||
654 | return Host::SetThreadName (pid, tid, namebuf.get()); | |||
655 | } | |||
656 | return false; | |||
657 | } | |||
658 | ||||
659 | #endif | |||
660 | ||||
661 | #if !defined (__APPLE__) // see Host.mm | |||
662 | ||||
663 | bool | |||
664 | Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) | |||
665 | { | |||
666 | bundle.Clear(); | |||
667 | return false; | |||
668 | } | |||
669 | ||||
670 | bool | |||
671 | Host::ResolveExecutableInBundle (FileSpec &file) | |||
672 | { | |||
673 | return false; | |||
674 | } | |||
675 | #endif | |||
676 | ||||
677 | #ifndef _WIN32 | |||
678 | ||||
679 | FileSpec | |||
680 | Host::GetModuleFileSpecForHostAddress (const void *host_addr) | |||
681 | { | |||
682 | FileSpec module_filespec; | |||
683 | Dl_info info; | |||
684 | if (::dladdr (host_addr, &info)) | |||
685 | { | |||
686 | if (info.dli_fname) | |||
687 | module_filespec.SetFile(info.dli_fname, true); | |||
688 | } | |||
689 | return module_filespec; | |||
690 | } | |||
691 | ||||
692 | #endif | |||
693 | ||||
694 | #if !defined(__linux__1) | |||
695 | bool | |||
696 | Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) | |||
697 | { | |||
698 | return false; | |||
699 | } | |||
700 | #endif | |||
701 | ||||
702 | lldb::TargetSP | |||
703 | Host::GetDummyTarget (lldb_private::Debugger &debugger) | |||
704 | { | |||
705 | static TargetSP g_dummy_target_sp; | |||
706 | ||||
707 | // FIXME: Maybe the dummy target should be per-Debugger | |||
708 | if (!g_dummy_target_sp || !g_dummy_target_sp->IsValid()) | |||
709 | { | |||
710 | ArchSpec arch(Target::GetDefaultArchitecture()); | |||
711 | if (!arch.IsValid()) | |||
712 | arch = HostInfo::GetArchitecture(); | |||
713 | Error err = debugger.GetTargetList().CreateTarget(debugger, | |||
714 | NULL__null, | |||
715 | arch.GetTriple().getTriple().c_str(), | |||
716 | false, | |||
717 | NULL__null, | |||
718 | g_dummy_target_sp); | |||
719 | } | |||
720 | ||||
721 | return g_dummy_target_sp; | |||
722 | } | |||
723 | ||||
724 | struct ShellInfo | |||
725 | { | |||
726 | ShellInfo () : | |||
727 | process_reaped (false), | |||
728 | can_delete (false), | |||
729 | pid (LLDB_INVALID_PROCESS_ID0), | |||
730 | signo(-1), | |||
731 | status(-1) | |||
732 | { | |||
733 | } | |||
734 | ||||
735 | lldb_private::Predicate<bool> process_reaped; | |||
736 | lldb_private::Predicate<bool> can_delete; | |||
737 | lldb::pid_t pid; | |||
738 | int signo; | |||
739 | int status; | |||
740 | }; | |||
741 | ||||
742 | static bool | |||
743 | MonitorShellCommand (void *callback_baton, | |||
744 | lldb::pid_t pid, | |||
745 | bool exited, // True if the process did exit | |||
746 | int signo, // Zero for no signal | |||
747 | int status) // Exit value of process if signal is zero | |||
748 | { | |||
749 | ShellInfo *shell_info = (ShellInfo *)callback_baton; | |||
750 | shell_info->pid = pid; | |||
751 | shell_info->signo = signo; | |||
752 | shell_info->status = status; | |||
753 | // Let the thread running Host::RunShellCommand() know that the process | |||
754 | // exited and that ShellInfo has been filled in by broadcasting to it | |||
755 | shell_info->process_reaped.SetValue(1, eBroadcastAlways); | |||
756 | // Now wait for a handshake back from that thread running Host::RunShellCommand | |||
757 | // so we know that we can delete shell_info_ptr | |||
758 | shell_info->can_delete.WaitForValueEqualTo(true); | |||
759 | // Sleep a bit to allow the shell_info->can_delete.SetValue() to complete... | |||
760 | usleep(1000); | |||
761 | // Now delete the shell info that was passed into this function | |||
762 | delete shell_info; | |||
763 | return true; | |||
764 | } | |||
765 | ||||
766 | Error | |||
767 | Host::RunShellCommand (const char *command, | |||
768 | const char *working_dir, | |||
769 | int *status_ptr, | |||
770 | int *signo_ptr, | |||
771 | std::string *command_output_ptr, | |||
772 | uint32_t timeout_sec, | |||
773 | const char *shell) | |||
774 | { | |||
775 | Error error; | |||
776 | ProcessLaunchInfo launch_info; | |||
777 | if (shell && shell[0]) | |||
778 | { | |||
779 | // Run the command in a shell | |||
780 | launch_info.SetShell(shell); | |||
781 | launch_info.GetArguments().AppendArgument(command); | |||
782 | const bool localhost = true; | |||
783 | const bool will_debug = false; | |||
784 | const bool first_arg_is_full_shell_command = true; | |||
785 | launch_info.ConvertArgumentsForLaunchingInShell (error, | |||
786 | localhost, | |||
787 | will_debug, | |||
788 | first_arg_is_full_shell_command, | |||
789 | 0); | |||
790 | } | |||
791 | else | |||
792 | { | |||
793 | // No shell, just run it | |||
794 | Args args (command); | |||
795 | const bool first_arg_is_executable = true; | |||
796 | launch_info.SetArguments(args, first_arg_is_executable); | |||
797 | } | |||
798 | ||||
799 | if (working_dir) | |||
800 | launch_info.SetWorkingDirectory(working_dir); | |||
801 | char output_file_path_buffer[PATH_MAX4096]; | |||
802 | const char *output_file_path = NULL__null; | |||
803 | ||||
804 | if (command_output_ptr) | |||
805 | { | |||
806 | // Create a temporary file to get the stdout/stderr and redirect the | |||
807 | // output of the command into this file. We will later read this file | |||
808 | // if all goes well and fill the data into "command_output_ptr" | |||
809 | FileSpec tmpdir_file_spec; | |||
810 | if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) | |||
811 | { | |||
812 | tmpdir_file_spec.AppendPathComponent("lldb-shell-output.XXXXXX"); | |||
813 | strncpy(output_file_path_buffer, tmpdir_file_spec.GetPath().c_str(), sizeof(output_file_path_buffer)); | |||
814 | } | |||
815 | else | |||
816 | { | |||
817 | strncpy(output_file_path_buffer, "/tmp/lldb-shell-output.XXXXXX", sizeof(output_file_path_buffer)); | |||
818 | } | |||
819 | ||||
820 | output_file_path = ::mktemp(output_file_path_buffer); | |||
821 | } | |||
822 | ||||
823 | launch_info.AppendSuppressFileAction (STDIN_FILENO0, true, false); | |||
824 | if (output_file_path) | |||
825 | { | |||
826 | launch_info.AppendOpenFileAction(STDOUT_FILENO1, output_file_path, false, true); | |||
827 | launch_info.AppendDuplicateFileAction(STDOUT_FILENO1, STDERR_FILENO2); | |||
828 | } | |||
829 | else | |||
830 | { | |||
831 | launch_info.AppendSuppressFileAction (STDOUT_FILENO1, false, true); | |||
832 | launch_info.AppendSuppressFileAction (STDERR_FILENO2, false, true); | |||
833 | } | |||
834 | ||||
835 | // The process monitor callback will delete the 'shell_info_ptr' below... | |||
836 | std::unique_ptr<ShellInfo> shell_info_ap (new ShellInfo()); | |||
837 | ||||
838 | const bool monitor_signals = false; | |||
839 | launch_info.SetMonitorProcessCallback(MonitorShellCommand, shell_info_ap.get(), monitor_signals); | |||
840 | ||||
841 | error = LaunchProcess (launch_info); | |||
842 | const lldb::pid_t pid = launch_info.GetProcessID(); | |||
843 | ||||
844 | if (error.Success() && pid == LLDB_INVALID_PROCESS_ID0) | |||
845 | error.SetErrorString("failed to get process ID"); | |||
846 | ||||
847 | if (error.Success()) | |||
848 | { | |||
849 | // The process successfully launched, so we can defer ownership of | |||
850 | // "shell_info" to the MonitorShellCommand callback function that will | |||
851 | // get called when the process dies. We release the unique pointer as it | |||
852 | // doesn't need to delete the ShellInfo anymore. | |||
853 | ShellInfo *shell_info = shell_info_ap.release(); | |||
854 | TimeValue *timeout_ptr = nullptr; | |||
855 | TimeValue timeout_time(TimeValue::Now()); | |||
856 | if (timeout_sec > 0) { | |||
857 | timeout_time.OffsetWithSeconds(timeout_sec); | |||
858 | timeout_ptr = &timeout_time; | |||
859 | } | |||
860 | bool timed_out = false; | |||
861 | shell_info->process_reaped.WaitForValueEqualTo(true, timeout_ptr, &timed_out); | |||
862 | if (timed_out) | |||
863 | { | |||
864 | error.SetErrorString("timed out waiting for shell command to complete"); | |||
865 | ||||
866 | // Kill the process since it didn't complete within the timeout specified | |||
867 | Kill (pid, SIGKILL9); | |||
868 | // Wait for the monitor callback to get the message | |||
869 | timeout_time = TimeValue::Now(); | |||
870 | timeout_time.OffsetWithSeconds(1); | |||
871 | timed_out = false; | |||
872 | shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out); | |||
873 | } | |||
874 | else | |||
875 | { | |||
876 | if (status_ptr) | |||
877 | *status_ptr = shell_info->status; | |||
878 | ||||
879 | if (signo_ptr) | |||
880 | *signo_ptr = shell_info->signo; | |||
881 | ||||
882 | if (command_output_ptr) | |||
883 | { | |||
884 | command_output_ptr->clear(); | |||
885 | FileSpec file_spec(output_file_path, File::eOpenOptionRead); | |||
886 | uint64_t file_size = file_spec.GetByteSize(); | |||
887 | if (file_size > 0) | |||
888 | { | |||
889 | if (file_size > command_output_ptr->max_size()) | |||
890 | { | |||
891 | error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string"); | |||
892 | } | |||
893 | else | |||
894 | { | |||
895 | command_output_ptr->resize(file_size); | |||
896 | file_spec.ReadFileContents(0, &((*command_output_ptr)[0]), command_output_ptr->size(), &error); | |||
897 | } | |||
898 | } | |||
899 | } | |||
900 | } | |||
901 | shell_info->can_delete.SetValue(true, eBroadcastAlways); | |||
902 | } | |||
903 | ||||
904 | if (output_file_path) | |||
905 | ::unlink (output_file_path); | |||
906 | // Handshake with the monitor thread, or just let it know in advance that | |||
907 | // it can delete "shell_info" in case we timed out and were not able to kill | |||
908 | // the process... | |||
909 | return error; | |||
910 | } | |||
911 | ||||
912 | ||||
913 | // LaunchProcessPosixSpawn for Apple, Linux, FreeBSD and other GLIBC | |||
914 | // systems | |||
915 | ||||
916 | #if defined (__APPLE__) || defined (__linux__1) || defined (__FreeBSD__) || defined (__GLIBC__2) || defined(__NetBSD__) | |||
917 | ||||
918 | // this method needs to be visible to macosx/Host.cpp and | |||
919 | // common/Host.cpp. | |||
920 | ||||
921 | short | |||
922 | Host::GetPosixspawnFlags (ProcessLaunchInfo &launch_info) | |||
923 | { | |||
924 | short flags = POSIX_SPAWN_SETSIGDEF0x04 | POSIX_SPAWN_SETSIGMASK0x08; | |||
925 | ||||
926 | #if defined (__APPLE__) | |||
927 | if (launch_info.GetFlags().Test (eLaunchFlagExec)) | |||
928 | flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag | |||
929 | ||||
930 | if (launch_info.GetFlags().Test (eLaunchFlagDebug)) | |||
931 | flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag | |||
932 | ||||
933 | if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) | |||
934 | flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag | |||
935 | ||||
936 | if (launch_info.GetLaunchInSeparateProcessGroup()) | |||
937 | flags |= POSIX_SPAWN_SETPGROUP0x02; | |||
938 | ||||
939 | #ifdef POSIX_SPAWN_CLOEXEC_DEFAULT | |||
940 | #if defined (__APPLE__) && (defined (__x86_64__1) || defined (__i386__)) | |||
941 | static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; | |||
942 | if (g_use_close_on_exec_flag == eLazyBoolCalculate) | |||
943 | { | |||
944 | g_use_close_on_exec_flag = eLazyBoolNo; | |||
945 | ||||
946 | uint32_t major, minor, update; | |||
947 | if (HostInfo::GetOSVersion(major, minor, update)) | |||
948 | { | |||
949 | // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or earlier | |||
950 | if (major > 10 || (major == 10 && minor > 7)) | |||
951 | { | |||
952 | // Only enable for 10.8 and later OS versions | |||
953 | g_use_close_on_exec_flag = eLazyBoolYes; | |||
954 | } | |||
955 | } | |||
956 | } | |||
957 | #else | |||
958 | static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; | |||
959 | #endif | |||
960 | // Close all files exception those with file actions if this is supported. | |||
961 | if (g_use_close_on_exec_flag == eLazyBoolYes) | |||
962 | flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; | |||
963 | #endif | |||
964 | #endif // #if defined (__APPLE__) | |||
965 | return flags; | |||
966 | } | |||
967 | ||||
968 | Error | |||
969 | Host::LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid) | |||
970 | { | |||
971 | Error error; | |||
972 | Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST(1u << 14) | LIBLLDB_LOG_PROCESS(1u << 1))); | |||
973 | ||||
974 | posix_spawnattr_t attr; | |||
975 | error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX); | |||
976 | ||||
977 | if (error.Fail() || log) | |||
978 | error.PutToLog(log, "::posix_spawnattr_init ( &attr )"); | |||
979 | if (error.Fail()) | |||
980 | return error; | |||
981 | ||||
982 | // Make a quick class that will cleanup the posix spawn attributes in case | |||
983 | // we return in the middle of this function. | |||
984 | lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy); | |||
985 | ||||
986 | sigset_t no_signals; | |||
987 | sigset_t all_signals; | |||
988 | sigemptyset (&no_signals); | |||
989 | sigfillset (&all_signals); | |||
990 | ::posix_spawnattr_setsigmask(&attr, &no_signals); | |||
991 | #if defined (__linux__1) || defined (__FreeBSD__) | |||
992 | ::posix_spawnattr_setsigdefault(&attr, &no_signals); | |||
993 | #else | |||
994 | ::posix_spawnattr_setsigdefault(&attr, &all_signals); | |||
995 | #endif | |||
996 | ||||
997 | short flags = GetPosixspawnFlags(launch_info); | |||
998 | ||||
999 | error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); | |||
1000 | if (error.Fail() || log) | |||
1001 | error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); | |||
1002 | if (error.Fail()) | |||
1003 | return error; | |||
1004 | ||||
1005 | // posix_spawnattr_setbinpref_np appears to be an Apple extension per: | |||
1006 | // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ | |||
1007 | #if defined (__APPLE__) && !defined (__arm__) | |||
1008 | ||||
1009 | // Don't set the binpref if a shell was provided. After all, that's only going to affect what version of the shell | |||
1010 | // is launched, not what fork of the binary is launched. We insert "arch --arch <ARCH> as part of the shell invocation | |||
1011 | // to do that job on OSX. | |||
1012 | ||||
1013 | if (launch_info.GetShell() == nullptr) | |||
1014 | { | |||
1015 | // We don't need to do this for ARM, and we really shouldn't now that we | |||
1016 | // have multiple CPU subtypes and no posix_spawnattr call that allows us | |||
1017 | // to set which CPU subtype to launch... | |||
1018 | const ArchSpec &arch_spec = launch_info.GetArchitecture(); | |||
1019 | cpu_type_t cpu = arch_spec.GetMachOCPUType(); | |||
1020 | cpu_type_t sub = arch_spec.GetMachOCPUSubType(); | |||
1021 | if (cpu != 0 && | |||
1022 | cpu != static_cast<cpu_type_t>(UINT32_MAX(4294967295U)) && | |||
1023 | cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE(0xFFFFFFFEu)) && | |||
1024 | !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail | |||
1025 | { | |||
1026 | size_t ocount = 0; | |||
1027 | error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX); | |||
1028 | if (error.Fail() || log) | |||
1029 | error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount); | |||
1030 | ||||
1031 | if (error.Fail() || ocount != 1) | |||
1032 | return error; | |||
1033 | } | |||
1034 | } | |||
1035 | ||||
1036 | #endif | |||
1037 | ||||
1038 | const char *tmp_argv[2]; | |||
1039 | char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector(); | |||
1040 | char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector(); | |||
1041 | if (argv == NULL__null) | |||
1042 | { | |||
1043 | // posix_spawn gets very unhappy if it doesn't have at least the program | |||
1044 | // name in argv[0]. One of the side affects I have noticed is the environment | |||
1045 | // variables don't make it into the child process if "argv == NULL"!!! | |||
1046 | tmp_argv[0] = exe_path; | |||
1047 | tmp_argv[1] = NULL__null; | |||
1048 | argv = (char * const*)tmp_argv; | |||
1049 | } | |||
1050 | ||||
1051 | #if !defined (__APPLE__) | |||
1052 | // manage the working directory | |||
1053 | char current_dir[PATH_MAX4096]; | |||
1054 | current_dir[0] = '\0'; | |||
1055 | #endif | |||
1056 | ||||
1057 | const char *working_dir = launch_info.GetWorkingDirectory(); | |||
1058 | if (working_dir) | |||
1059 | { | |||
1060 | #if defined (__APPLE__) | |||
1061 | // Set the working directory on this thread only | |||
1062 | if (__pthread_chdir (working_dir) < 0) { | |||
1063 | if (errno(*__errno_location ()) == ENOENT2) { | |||
1064 | error.SetErrorStringWithFormat("No such file or directory: %s", working_dir); | |||
1065 | } else if (errno(*__errno_location ()) == ENOTDIR20) { | |||
1066 | error.SetErrorStringWithFormat("Path doesn't name a directory: %s", working_dir); | |||
1067 | } else { | |||
1068 | error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution."); | |||
1069 | } | |||
1070 | return error; | |||
1071 | } | |||
1072 | #else | |||
1073 | if (::getcwd(current_dir, sizeof(current_dir)) == NULL__null) | |||
1074 | { | |||
1075 | error.SetError(errno(*__errno_location ()), eErrorTypePOSIX); | |||
1076 | error.LogIfError(log, "unable to save the current directory"); | |||
1077 | return error; | |||
1078 | } | |||
1079 | ||||
1080 | if (::chdir(working_dir) == -1) | |||
1081 | { | |||
1082 | error.SetError(errno(*__errno_location ()), eErrorTypePOSIX); | |||
1083 | error.LogIfError(log, "unable to change working directory to %s", working_dir); | |||
1084 | return error; | |||
1085 | } | |||
1086 | #endif | |||
1087 | } | |||
1088 | ||||
1089 | const size_t num_file_actions = launch_info.GetNumFileActions (); | |||
1090 | if (num_file_actions > 0) | |||
1091 | { | |||
1092 | posix_spawn_file_actions_t file_actions; | |||
1093 | error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX); | |||
1094 | if (error.Fail() || log) | |||
1095 | error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )"); | |||
1096 | if (error.Fail()) | |||
1097 | return error; | |||
1098 | ||||
1099 | // Make a quick class that will cleanup the posix spawn attributes in case | |||
1100 | // we return in the middle of this function. | |||
1101 | lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy); | |||
1102 | ||||
1103 | for (size_t i=0; i<num_file_actions; ++i) | |||
1104 | { | |||
1105 | const FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i); | |||
1106 | if (launch_file_action) | |||
1107 | { | |||
1108 | if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, error)) | |||
1109 | return error; | |||
1110 | } | |||
1111 | } | |||
1112 | ||||
1113 | error.SetError (::posix_spawnp (&pid, | |||
1114 | exe_path, | |||
1115 | &file_actions, | |||
1116 | &attr, | |||
1117 | argv, | |||
1118 | envp), | |||
1119 | eErrorTypePOSIX); | |||
1120 | ||||
1121 | if (error.Fail() || log) | |||
1122 | { | |||
1123 | error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", | |||
1124 | pid, exe_path, static_cast<void*>(&file_actions), | |||
1125 | static_cast<void*>(&attr), | |||
1126 | reinterpret_cast<const void*>(argv), | |||
1127 | reinterpret_cast<const void*>(envp)); | |||
1128 | if (log) | |||
1129 | { | |||
1130 | for (int ii=0; argv[ii]; ++ii) | |||
1131 | log->Printf("argv[%i] = '%s'", ii, argv[ii]); | |||
1132 | } | |||
1133 | } | |||
1134 | ||||
1135 | } | |||
1136 | else | |||
1137 | { | |||
1138 | error.SetError (::posix_spawnp (&pid, | |||
1139 | exe_path, | |||
1140 | NULL__null, | |||
1141 | &attr, | |||
1142 | argv, | |||
1143 | envp), | |||
1144 | eErrorTypePOSIX); | |||
1145 | ||||
1146 | if (error.Fail() || log) | |||
1147 | { | |||
1148 | error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )", | |||
1149 | pid, exe_path, static_cast<void*>(&attr), | |||
1150 | reinterpret_cast<const void*>(argv), | |||
1151 | reinterpret_cast<const void*>(envp)); | |||
1152 | if (log) | |||
1153 | { | |||
1154 | for (int ii=0; argv[ii]; ++ii) | |||
1155 | log->Printf("argv[%i] = '%s'", ii, argv[ii]); | |||
1156 | } | |||
1157 | } | |||
1158 | } | |||
1159 | ||||
1160 | if (working_dir) | |||
1161 | { | |||
1162 | #if defined (__APPLE__) | |||
1163 | // No more thread specific current working directory | |||
1164 | __pthread_fchdir (-1); | |||
1165 | #else | |||
1166 | if (::chdir(current_dir) == -1 && error.Success()) | |||
1167 | { | |||
1168 | error.SetError(errno(*__errno_location ()), eErrorTypePOSIX); | |||
1169 | error.LogIfError(log, "unable to change current directory back to %s", | |||
1170 | current_dir); | |||
1171 | } | |||
1172 | #endif | |||
1173 | } | |||
1174 | ||||
1175 | return error; | |||
1176 | } | |||
1177 | ||||
1178 | bool | |||
1179 | Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error) | |||
1180 | { | |||
1181 | if (info == NULL__null) | |||
1182 | return false; | |||
1183 | ||||
1184 | posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); | |||
1185 | ||||
1186 | switch (info->GetAction()) | |||
1187 | { | |||
1188 | case FileAction::eFileActionNone: | |||
1189 | error.Clear(); | |||
1190 | break; | |||
1191 | ||||
1192 | case FileAction::eFileActionClose: | |||
1193 | if (info->GetFD() == -1) | |||
1194 | error.SetErrorString("invalid fd for posix_spawn_file_actions_addclose(...)"); | |||
1195 | else | |||
1196 | { | |||
1197 | error.SetError(::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX); | |||
1198 | if (log && (error.Fail() || log)) | |||
1199 | error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)", | |||
1200 | static_cast<void *>(file_actions), info->GetFD()); | |||
1201 | } | |||
1202 | break; | |||
1203 | ||||
1204 | case FileAction::eFileActionDuplicate: | |||
1205 | if (info->GetFD() == -1) | |||
1206 | error.SetErrorString("invalid fd for posix_spawn_file_actions_adddup2(...)"); | |||
1207 | else if (info->GetActionArgument() == -1) | |||
1208 | error.SetErrorString("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); | |||
1209 | else | |||
1210 | { | |||
1211 | error.SetError( | |||
1212 | ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()), | |||
1213 | eErrorTypePOSIX); | |||
1214 | if (log && (error.Fail() || log)) | |||
1215 | error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", | |||
1216 | static_cast<void *>(file_actions), info->GetFD(), info->GetActionArgument()); | |||
1217 | } | |||
1218 | break; | |||
1219 | ||||
1220 | case FileAction::eFileActionOpen: | |||
1221 | if (info->GetFD() == -1) | |||
1222 | error.SetErrorString("invalid fd in posix_spawn_file_actions_addopen(...)"); | |||
1223 | else | |||
1224 | { | |||
1225 | int oflag = info->GetActionArgument(); | |||
1226 | ||||
1227 | mode_t mode = 0; | |||
1228 | ||||
1229 | if (oflag & O_CREAT0100) | |||
1230 | mode = 0640; | |||
1231 | ||||
1232 | error.SetError( | |||
1233 | ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), info->GetPath(), oflag, mode), | |||
1234 | eErrorTypePOSIX); | |||
1235 | if (error.Fail() || log) | |||
1236 | error.PutToLog(log, | |||
1237 | "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)", | |||
1238 | static_cast<void *>(file_actions), info->GetFD(), info->GetPath(), oflag, mode); | |||
1239 | } | |||
1240 | break; | |||
1241 | } | |||
1242 | return error.Success(); | |||
1243 | } | |||
1244 | ||||
1245 | #endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems | |||
1246 | ||||
1247 | ||||
1248 | #if defined(__linux__1) || defined(__FreeBSD__) || defined(__GLIBC__2) || defined(__NetBSD__) | |||
1249 | // The functions below implement process launching via posix_spawn() for Linux, | |||
1250 | // FreeBSD and NetBSD. | |||
1251 | ||||
1252 | Error | |||
1253 | Host::LaunchProcess (ProcessLaunchInfo &launch_info) | |||
1254 | { | |||
1255 | Error error; | |||
1256 | char exe_path[PATH_MAX4096]; | |||
1257 | ||||
1258 | PlatformSP host_platform_sp (Platform::GetDefaultPlatform ()); | |||
1259 | ||||
1260 | const ArchSpec &arch_spec = launch_info.GetArchitecture(); | |||
1261 | ||||
1262 | FileSpec exe_spec(launch_info.GetExecutableFile()); | |||
1263 | ||||
1264 | FileSpec::FileType file_type = exe_spec.GetFileType(); | |||
1265 | if (file_type != FileSpec::eFileTypeRegular) | |||
1266 | { | |||
1267 | lldb::ModuleSP exe_module_sp; | |||
1268 | error = host_platform_sp->ResolveExecutable (exe_spec, | |||
1269 | arch_spec, | |||
1270 | exe_module_sp, | |||
1271 | NULL__null); | |||
1272 | ||||
1273 | if (error.Fail()) | |||
1274 | return error; | |||
1275 | ||||
1276 | if (exe_module_sp) | |||
1277 | exe_spec = exe_module_sp->GetFileSpec(); | |||
1278 | } | |||
1279 | ||||
1280 | if (exe_spec.Exists()) | |||
1281 | { | |||
1282 | exe_spec.GetPath (exe_path, sizeof(exe_path)); | |||
1283 | } | |||
1284 | else | |||
1285 | { | |||
1286 | launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path)); | |||
1287 | error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path); | |||
1288 | return error; | |||
1289 | } | |||
1290 | ||||
1291 | assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))((!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)) ? static_cast <void> (0) : __assert_fail ("!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn216889/tools/lldb/source/Host/common/Host.cpp" , 1291, __PRETTY_FUNCTION__)); | |||
1292 | ||||
1293 | ::pid_t pid = LLDB_INVALID_PROCESS_ID0; | |||
1294 | ||||
1295 | error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); | |||
1296 | ||||
1297 | if (pid != LLDB_INVALID_PROCESS_ID0) | |||
1298 | { | |||
1299 | // If all went well, then set the process ID into the launch info | |||
1300 | launch_info.SetProcessID(pid); | |||
1301 | ||||
1302 | Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1303 | ||||
1304 | // Make sure we reap any processes we spawn or we will have zombies. | |||
1305 | if (!launch_info.MonitorProcess()) | |||
1306 | { | |||
1307 | const bool monitor_signals = false; | |||
1308 | StartMonitoringChildProcess (Process::SetProcessExitStatus, | |||
1309 | NULL__null, | |||
1310 | pid, | |||
1311 | monitor_signals); | |||
1312 | if (log) | |||
1313 | log->PutCString ("monitored child process with default Process::SetProcessExitStatus."); | |||
1314 | } | |||
1315 | else | |||
1316 | { | |||
1317 | if (log) | |||
1318 | log->PutCString ("monitored child process with user-specified process monitor."); | |||
1319 | } | |||
1320 | } | |||
1321 | else | |||
1322 | { | |||
1323 | // Invalid process ID, something didn't go well | |||
1324 | if (error.Success()) | |||
1325 | error.SetErrorString ("process launch failed for unknown reasons"); | |||
1326 | } | |||
1327 | return error; | |||
1328 | } | |||
1329 | ||||
1330 | #endif // defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) | |||
1331 | ||||
1332 | #ifndef _WIN32 | |||
1333 | ||||
1334 | void | |||
1335 | Host::Kill(lldb::pid_t pid, int signo) | |||
1336 | { | |||
1337 | ::kill(pid, signo); | |||
1338 | } | |||
1339 | ||||
1340 | #endif | |||
1341 | ||||
1342 | #if !defined (__APPLE__) | |||
1343 | bool | |||
1344 | Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) | |||
1345 | { | |||
1346 | return false; | |||
1347 | } | |||
1348 | ||||
1349 | void | |||
1350 | Host::SetCrashDescriptionWithFormat (const char *format, ...) | |||
1351 | { | |||
1352 | } | |||
1353 | ||||
1354 | void | |||
1355 | Host::SetCrashDescription (const char *description) | |||
1356 | { | |||
1357 | } | |||
1358 | ||||
1359 | lldb::pid_t | |||
1360 | Host::LaunchApplication (const FileSpec &app_file_spec) | |||
1361 | { | |||
1362 | return LLDB_INVALID_PROCESS_ID0; | |||
1363 | } | |||
1364 | ||||
1365 | #endif | |||
1366 | ||||
1367 | #if !defined (__linux__1) && !defined (__FreeBSD__) && !defined (__NetBSD__) | |||
1368 | ||||
1369 | const lldb_private::UnixSignalsSP& | |||
1370 | Host::GetUnixSignals () | |||
1371 | { | |||
1372 | static UnixSignalsSP s_unix_signals_sp (new UnixSignals ()); | |||
1373 | return s_unix_signals_sp; | |||
1374 | } | |||
1375 | ||||
1376 | #endif |