blob: 2f4247d41016f93563c26a84b499382f03714b0e [file] [log] [blame]
Greg Clayton8f3b21d2010-09-07 20:11:56 +00001//===-- 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/Host/Host.h"
11#include "lldb/Core/ArchSpec.h"
12#include "lldb/Core/ConstString.h"
13#include "lldb/Core/Error.h"
14#include "lldb/Core/FileSpec.h"
15#include "lldb/Core/Log.h"
16#include "lldb/Core/StreamString.h"
Greg Claytoncd548032011-02-01 01:31:41 +000017#include "lldb/Host/Endian.h"
Greg Clayton8f3b21d2010-09-07 20:11:56 +000018#include "lldb/Host/Mutex.h"
19
20#include <dlfcn.h>
21#include <errno.h>
22#include <sys/sysctl.h>
23#include <sys/wait.h>
24
25#if defined (__APPLE__)
Greg Clayton49ce6822010-10-31 03:01:06 +000026#include <dispatch/dispatch.h>
Greg Clayton8f3b21d2010-09-07 20:11:56 +000027#include <libproc.h>
28#include <mach-o/dyld.h>
29#endif
30
31using namespace lldb;
32using namespace lldb_private;
33
34struct MonitorInfo
35{
36 lldb::pid_t pid; // The process ID to monitor
37 Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals
38 void *callback_baton; // The callback baton for the callback function
39 bool monitor_signals; // If true, call the callback when "pid" gets signaled.
40};
41
42static void *
43MonitorChildProcessThreadFunction (void *arg);
44
45lldb::thread_t
46Host::StartMonitoringChildProcess
47(
48 Host::MonitorChildProcessCallback callback,
49 void *callback_baton,
50 lldb::pid_t pid,
51 bool monitor_signals
52)
53{
54 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
55 if (callback)
56 {
57 std::auto_ptr<MonitorInfo> info_ap(new MonitorInfo);
58
59 info_ap->pid = pid;
60 info_ap->callback = callback;
61 info_ap->callback_baton = callback_baton;
62 info_ap->monitor_signals = monitor_signals;
63
64 char thread_name[256];
65 ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid);
66 thread = ThreadCreate (thread_name,
67 MonitorChildProcessThreadFunction,
68 info_ap.get(),
69 NULL);
70
71 if (thread != LLDB_INVALID_HOST_THREAD)
72 info_ap.release();
73 }
74 return thread;
75}
76
77//------------------------------------------------------------------
78// Scoped class that will disable thread canceling when it is
79// constructed, and exception safely restore the previous value it
80// when it goes out of scope.
81//------------------------------------------------------------------
82class ScopedPThreadCancelDisabler
83{
84public:
85 ScopedPThreadCancelDisabler()
86 {
87 // Disable the ability for this thread to be cancelled
88 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
89 if (err != 0)
90 m_old_state = -1;
91
92 }
93
94 ~ScopedPThreadCancelDisabler()
95 {
96 // Restore the ability for this thread to be cancelled to what it
97 // previously was.
98 if (m_old_state != -1)
99 ::pthread_setcancelstate (m_old_state, 0);
100 }
101private:
102 int m_old_state; // Save the old cancelability state.
103};
104
105static void *
106MonitorChildProcessThreadFunction (void *arg)
107{
Greg Claytone005f2c2010-11-06 01:53:30 +0000108 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000109 const char *function = __FUNCTION__;
110 if (log)
111 log->Printf ("%s (arg = %p) thread starting...", function, arg);
112
113 MonitorInfo *info = (MonitorInfo *)arg;
114
115 const Host::MonitorChildProcessCallback callback = info->callback;
116 void * const callback_baton = info->callback_baton;
117 const lldb::pid_t pid = info->pid;
118 const bool monitor_signals = info->monitor_signals;
119
120 delete info;
121
122 int status = -1;
123 const int options = 0;
124 struct rusage *rusage = NULL;
125 while (1)
126 {
Caroline Tice926060e2010-10-29 21:48:37 +0000127 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000128 if (log)
129 log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, pid, options, rusage);
130
131 // Wait for all child processes
132 ::pthread_testcancel ();
133 const lldb::pid_t wait_pid = ::wait4 (pid, &status, options, rusage);
134 ::pthread_testcancel ();
135
136 if (wait_pid == -1)
137 {
138 if (errno == EINTR)
139 continue;
140 else
141 break;
142 }
143 else if (wait_pid == pid)
144 {
145 bool exited = false;
146 int signal = 0;
147 int exit_status = 0;
148 const char *status_cstr = NULL;
149 if (WIFSTOPPED(status))
150 {
151 signal = WSTOPSIG(status);
152 status_cstr = "STOPPED";
153 }
154 else if (WIFEXITED(status))
155 {
156 exit_status = WEXITSTATUS(status);
157 status_cstr = "EXITED";
158 exited = true;
159 }
160 else if (WIFSIGNALED(status))
161 {
162 signal = WTERMSIG(status);
163 status_cstr = "SIGNALED";
164 exited = true;
165 exit_status = -1;
166 }
167 else
168 {
169 status_cstr = "(???)";
170 }
171
172 // Scope for pthread_cancel_disabler
173 {
174 ScopedPThreadCancelDisabler pthread_cancel_disabler;
175
Caroline Tice926060e2010-10-29 21:48:37 +0000176 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000177 if (log)
178 log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
179 function,
180 wait_pid,
181 options,
182 rusage,
183 pid,
184 status,
185 status_cstr,
186 signal,
187 exit_status);
188
189 if (exited || (signal != 0 && monitor_signals))
190 {
191 bool callback_return = callback (callback_baton, pid, signal, exit_status);
192
193 // If our process exited, then this thread should exit
194 if (exited)
195 break;
196 // If the callback returns true, it means this process should
197 // exit
198 if (callback_return)
199 break;
200 }
201 }
202 }
203 }
204
Caroline Tice926060e2010-10-29 21:48:37 +0000205 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000206 if (log)
207 log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg);
208
209 return NULL;
210}
211
212size_t
213Host::GetPageSize()
214{
215 return ::getpagesize();
216}
217
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000218const ArchSpec &
219Host::GetArchitecture ()
220{
221 static ArchSpec g_host_arch;
222 if (!g_host_arch.IsValid())
223 {
224#if defined (__APPLE__)
225 uint32_t cputype, cpusubtype;
226 uint32_t is_64_bit_capable;
227 size_t len = sizeof(cputype);
228 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
229 {
230 len = sizeof(cpusubtype);
231 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
232 g_host_arch.SetArch(cputype, cpusubtype);
233
234 len = sizeof (is_64_bit_capable);
235 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
236 {
237 if (is_64_bit_capable)
238 {
239 if (cputype == CPU_TYPE_I386 && cpusubtype == CPU_SUBTYPE_486)
240 cpusubtype = CPU_SUBTYPE_I386_ALL;
241
242 cputype |= CPU_ARCH_ABI64;
243 }
244 }
245 }
246#elif defined (__linux__)
247 g_host_arch.SetArch(7u, 144u);
248#endif
249 }
250 return g_host_arch;
251}
252
253const ConstString &
254Host::GetVendorString()
255{
256 static ConstString g_vendor;
257 if (!g_vendor)
258 {
259#if defined (__APPLE__)
260 char ostype[64];
261 size_t len = sizeof(ostype);
262 if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
263 g_vendor.SetCString (ostype);
264 else
265 g_vendor.SetCString("apple");
266#elif defined (__linux__)
267 g_vendor.SetCString("gnu");
268#endif
269 }
270 return g_vendor;
271}
272
273const ConstString &
274Host::GetOSString()
275{
276 static ConstString g_os_string;
277 if (!g_os_string)
278 {
279#if defined (__APPLE__)
280 g_os_string.SetCString("darwin");
281#elif defined (__linux__)
282 g_os_string.SetCString("linux");
283#endif
284 }
285 return g_os_string;
286}
287
288const ConstString &
289Host::GetTargetTriple()
290{
291 static ConstString g_host_triple;
292 if (!(g_host_triple))
293 {
294 StreamString triple;
295 triple.Printf("%s-%s-%s",
296 GetArchitecture().AsCString(),
297 GetVendorString().AsCString(),
298 GetOSString().AsCString());
299
300 std::transform (triple.GetString().begin(),
301 triple.GetString().end(),
302 triple.GetString().begin(),
303 ::tolower);
304
305 g_host_triple.SetCString(triple.GetString().c_str());
306 }
307 return g_host_triple;
308}
309
310lldb::pid_t
311Host::GetCurrentProcessID()
312{
313 return ::getpid();
314}
315
316lldb::tid_t
317Host::GetCurrentThreadID()
318{
319#if defined (__APPLE__)
320 return ::mach_thread_self();
321#else
322 return lldb::tid_t(pthread_self());
323#endif
324}
325
326const char *
327Host::GetSignalAsCString (int signo)
328{
329 switch (signo)
330 {
331 case SIGHUP: return "SIGHUP"; // 1 hangup
332 case SIGINT: return "SIGINT"; // 2 interrupt
333 case SIGQUIT: return "SIGQUIT"; // 3 quit
334 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught)
335 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught)
336 case SIGABRT: return "SIGABRT"; // 6 abort()
337#if defined(_POSIX_C_SOURCE)
338 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
339#else // !_POSIX_C_SOURCE
340 case SIGEMT: return "SIGEMT"; // 7 EMT instruction
341#endif // !_POSIX_C_SOURCE
342 case SIGFPE: return "SIGFPE"; // 8 floating point exception
343 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored)
344 case SIGBUS: return "SIGBUS"; // 10 bus error
345 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation
346 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call
347 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it
348 case SIGALRM: return "SIGALRM"; // 14 alarm clock
349 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill
350 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel
351 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty
352 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty
353 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process
354 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit
355 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read
356 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local&LTOSTOP)
357#if !defined(_POSIX_C_SOURCE)
358 case SIGIO: return "SIGIO"; // 23 input/output possible signal
359#endif
360 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit
361 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit
362 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm
363 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm
364#if !defined(_POSIX_C_SOURCE)
365 case SIGWINCH: return "SIGWINCH"; // 28 window size changes
366 case SIGINFO: return "SIGINFO"; // 29 information request
367#endif
368 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1
369 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2
370 default:
371 break;
372 }
373 return NULL;
374}
375
376void
377Host::WillTerminate ()
378{
379}
380
381#if !defined (__APPLE__) // see macosx/Host.mm
382void
383Host::ThreadCreated (const char *thread_name)
384{
385}
Greg Claytonb749a262010-12-03 06:02:24 +0000386
387void
388Host::Backtrace (Stream &strm, uint32_t max_frames)
389{
Greg Clayton52fd9842011-02-02 02:24:04 +0000390 // TODO: Is there a way to backtrace the current process on linux? Other systems?
Greg Claytonb749a262010-12-03 06:02:24 +0000391}
392
Greg Clayton638351a2010-12-04 00:10:17 +0000393
394size_t
395Host::GetEnvironment (StringList &env)
396{
Greg Clayton52fd9842011-02-02 02:24:04 +0000397 // TODO: Is there a way to the host environment for this process on linux? Other systems?
Greg Clayton638351a2010-12-04 00:10:17 +0000398 return 0;
399}
400
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000401#endif
402
403struct HostThreadCreateInfo
404{
405 std::string thread_name;
406 thread_func_t thread_fptr;
407 thread_arg_t thread_arg;
408
409 HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) :
410 thread_name (name ? name : ""),
411 thread_fptr (fptr),
412 thread_arg (arg)
413 {
414 }
415};
416
417static thread_result_t
418ThreadCreateTrampoline (thread_arg_t arg)
419{
420 HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
421 Host::ThreadCreated (info->thread_name.c_str());
422 thread_func_t thread_fptr = info->thread_fptr;
423 thread_arg_t thread_arg = info->thread_arg;
424
Greg Claytone005f2c2010-11-06 01:53:30 +0000425 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000426 if (log)
427 log->Printf("thread created");
428
429 delete info;
430 return thread_fptr (thread_arg);
431}
432
433lldb::thread_t
434Host::ThreadCreate
435(
436 const char *thread_name,
437 thread_func_t thread_fptr,
438 thread_arg_t thread_arg,
439 Error *error
440)
441{
442 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
443
444 // Host::ThreadCreateTrampoline will delete this pointer for us.
445 HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
446
447 int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
448 if (err == 0)
449 {
450 if (error)
451 error->Clear();
452 return thread;
453 }
454
455 if (error)
456 error->SetError (err, eErrorTypePOSIX);
457
458 return LLDB_INVALID_HOST_THREAD;
459}
460
461bool
462Host::ThreadCancel (lldb::thread_t thread, Error *error)
463{
464 int err = ::pthread_cancel (thread);
465 if (error)
466 error->SetError(err, eErrorTypePOSIX);
467 return err == 0;
468}
469
470bool
471Host::ThreadDetach (lldb::thread_t thread, Error *error)
472{
473 int err = ::pthread_detach (thread);
474 if (error)
475 error->SetError(err, eErrorTypePOSIX);
476 return err == 0;
477}
478
479bool
480Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error)
481{
482 int err = ::pthread_join (thread, thread_result_ptr);
483 if (error)
484 error->SetError(err, eErrorTypePOSIX);
485 return err == 0;
486}
487
488//------------------------------------------------------------------
489// Control access to a static file thread name map using a single
490// static function to avoid a static constructor.
491//------------------------------------------------------------------
492static const char *
493ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
494{
495 uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
496
497 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
498 Mutex::Locker locker(&g_mutex);
499
500 typedef std::map<uint64_t, std::string> thread_name_map;
501 // rdar://problem/8153284
502 // Fixed a crasher where during shutdown, loggings attempted to access the
503 // thread name but the static map instance had already been destructed.
504 // Another approach is to introduce a static guard object which monitors its
505 // own destruction and raises a flag, but this incurs more overhead.
506 static thread_name_map *g_thread_names_ptr = new thread_name_map();
507 thread_name_map &g_thread_names = *g_thread_names_ptr;
508
509 if (get)
510 {
511 // See if the thread name exists in our thread name pool
512 thread_name_map::iterator pos = g_thread_names.find(pid_tid);
513 if (pos != g_thread_names.end())
514 return pos->second.c_str();
515 }
516 else
517 {
518 // Set the thread name
519 g_thread_names[pid_tid] = name;
520 }
521 return NULL;
522}
523
524const char *
525Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
526{
527 const char *name = ThreadNameAccessor (true, pid, tid, NULL);
528 if (name == NULL)
529 {
530#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
531 // We currently can only get the name of a thread in the current process.
532 if (pid == Host::GetCurrentProcessID())
533 {
534 char pthread_name[1024];
535 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
536 {
537 if (pthread_name[0])
538 {
539 // Set the thread in our string pool
540 ThreadNameAccessor (false, pid, tid, pthread_name);
541 // Get our copy of the thread name string
542 name = ThreadNameAccessor (true, pid, tid, NULL);
543 }
544 }
Greg Clayton49ce6822010-10-31 03:01:06 +0000545
546 if (name == NULL)
547 {
548 dispatch_queue_t current_queue = ::dispatch_get_current_queue ();
549 if (current_queue != NULL)
550 name = dispatch_queue_get_label (current_queue);
551 }
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000552 }
553#endif
554 }
555 return name;
556}
557
558void
559Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
560{
561 lldb::pid_t curr_pid = Host::GetCurrentProcessID();
562 lldb::tid_t curr_tid = Host::GetCurrentThreadID();
563 if (pid == LLDB_INVALID_PROCESS_ID)
564 pid = curr_pid;
565
566 if (tid == LLDB_INVALID_THREAD_ID)
567 tid = curr_tid;
568
569#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
570 // Set the pthread name if possible
571 if (pid == curr_pid && tid == curr_tid)
572 {
573 ::pthread_setname_np (name);
574 }
575#endif
576 ThreadNameAccessor (false, pid, tid, name);
577}
578
579FileSpec
580Host::GetProgramFileSpec ()
581{
582 static FileSpec g_program_filespec;
583 if (!g_program_filespec)
584 {
585#if defined (__APPLE__)
586 char program_fullpath[PATH_MAX];
587 // If DST is NULL, then return the number of bytes needed.
588 uint32_t len = sizeof(program_fullpath);
589 int err = _NSGetExecutablePath (program_fullpath, &len);
590 if (err == 0)
Greg Clayton20fbf8d2011-01-13 01:23:43 +0000591 g_program_filespec.SetFile (program_fullpath, false);
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000592 else if (err == -1)
593 {
594 char *large_program_fullpath = (char *)::malloc (len + 1);
595
596 err = _NSGetExecutablePath (large_program_fullpath, &len);
597 if (err == 0)
Greg Clayton20fbf8d2011-01-13 01:23:43 +0000598 g_program_filespec.SetFile (large_program_fullpath, false);
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000599
600 ::free (large_program_fullpath);
601 }
602#elif defined (__linux__)
603 char exe_path[PATH_MAX];
Stephen Wilsonf302a9e2011-01-12 04:21:21 +0000604 ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
605 if (len > 0) {
606 exe_path[len] = 0;
Greg Clayton20fbf8d2011-01-13 01:23:43 +0000607 g_program_filespec.SetFile(exe_path, false);
Stephen Wilsonf302a9e2011-01-12 04:21:21 +0000608 }
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000609#elif defined (__FreeBSD__)
610 int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
611 size_t exe_path_size;
612 if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0)
613 {
Greg Clayton366795e2011-01-13 01:27:55 +0000614 char *exe_path = new char[exe_path_size];
615 if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
616 g_program_filespec.SetFile(exe_path, false);
617 delete[] exe_path;
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000618 }
619#endif
620 }
621 return g_program_filespec;
622}
623
624FileSpec
625Host::GetModuleFileSpecForHostAddress (const void *host_addr)
626{
627 FileSpec module_filespec;
628 Dl_info info;
629 if (::dladdr (host_addr, &info))
630 {
631 if (info.dli_fname)
Greg Clayton537a7a82010-10-20 20:54:39 +0000632 module_filespec.SetFile(info.dli_fname, true);
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000633 }
634 return module_filespec;
635}
636
637#if !defined (__APPLE__) // see Host.mm
638bool
Greg Clayton24b48ff2010-10-17 22:03:32 +0000639Host::ResolveExecutableInBundle (FileSpec &file)
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000640{
Greg Clayton24b48ff2010-10-17 22:03:32 +0000641 return false;
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000642}
643#endif
644
Greg Clayton52fd9842011-02-02 02:24:04 +0000645void *
646Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error)
647{
648 void *dynamic_library_handle = NULL;
649 char path[PATH_MAX];
650 if (file_spec.GetPath(path, sizeof(path)))
651 {
652 dynamic_library_handle = ::dlopen (path, RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST);
653 if (dynamic_library_handle)
654 {
655 error.Clear();
656 }
657 else
658 {
659 error.SetErrorString(::dlerror());
660 }
661 }
662 else
663 {
664 error.SetErrorString("failed to extract path");
665 }
666
667 return dynamic_library_handle;
668}
669
670Error
671Host::DynamicLibraryClose (void *dynamic_library_handle)
672{
673 Error error;
674 if (dynamic_library_handle == NULL)
675 {
676 error.SetErrorString ("invalid dynamic library handle");
677 }
678 else if (::dlclose(dynamic_library_handle) != 0)
679 {
680 error.SetErrorString(::dlerror());
681 }
682 return error;
683}
684
685void *
686Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error)
687{
688 if (dynamic_library_handle == NULL)
689 {
690 error.SetErrorString ("invalid dynamic library handle");
691 return NULL;
692 }
693
694 void *symbol_addr = ::dlsym (dynamic_library_handle, symbol_name);
695 if (symbol_addr == NULL)
696 error.SetErrorString(::dlerror());
697 else
698 error.Clear();
699 return symbol_addr;
700}
Greg Clayton24b48ff2010-10-17 22:03:32 +0000701
702bool
703Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
704{
Greg Clayton5d187e52011-01-08 20:28:42 +0000705 // To get paths related to LLDB we get the path to the executable that
Greg Clayton24b48ff2010-10-17 22:03:32 +0000706 // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
707 // on linux this is assumed to be the "lldb" main executable. If LLDB on
708 // linux is actually in a shared library (lldb.so??) then this function will
709 // need to be modified to "do the right thing".
710
711 switch (path_type)
712 {
713 case ePathTypeLLDBShlibDir:
714 {
715 static ConstString g_lldb_so_dir;
716 if (!g_lldb_so_dir)
717 {
718 FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
719 g_lldb_so_dir = lldb_file_spec.GetDirectory();
720 }
721 file_spec.GetDirectory() = g_lldb_so_dir;
722 return file_spec.GetDirectory();
723 }
724 break;
725
726 case ePathTypeSupportExecutableDir:
727 {
728 static ConstString g_lldb_support_exe_dir;
729 if (!g_lldb_support_exe_dir)
730 {
731 FileSpec lldb_file_spec;
732 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
733 {
734 char raw_path[PATH_MAX];
735 char resolved_path[PATH_MAX];
736 lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
737
738#if defined (__APPLE__)
739 char *framework_pos = ::strstr (raw_path, "LLDB.framework");
740 if (framework_pos)
741 {
742 framework_pos += strlen("LLDB.framework");
743 ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
744 }
745#endif
746 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
747 g_lldb_support_exe_dir.SetCString(resolved_path);
748 }
749 }
750 file_spec.GetDirectory() = g_lldb_support_exe_dir;
751 return file_spec.GetDirectory();
752 }
753 break;
754
755 case ePathTypeHeaderDir:
756 {
757 static ConstString g_lldb_headers_dir;
758 if (!g_lldb_headers_dir)
759 {
760#if defined (__APPLE__)
761 FileSpec lldb_file_spec;
762 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
763 {
764 char raw_path[PATH_MAX];
765 char resolved_path[PATH_MAX];
766 lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
767
768 char *framework_pos = ::strstr (raw_path, "LLDB.framework");
769 if (framework_pos)
770 {
771 framework_pos += strlen("LLDB.framework");
772 ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path));
773 }
774 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
775 g_lldb_headers_dir.SetCString(resolved_path);
776 }
777#else
Greg Clayton52fd9842011-02-02 02:24:04 +0000778 // TODO: Anyone know how we can determine this for linux? Other systems??
Greg Clayton24b48ff2010-10-17 22:03:32 +0000779 g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
780#endif
781 }
782 file_spec.GetDirectory() = g_lldb_headers_dir;
783 return file_spec.GetDirectory();
784 }
785 break;
786
787 case ePathTypePythonDir:
788 {
Greg Clayton52fd9842011-02-02 02:24:04 +0000789 // TODO: Anyone know how we can determine this for linux? Other systems?
Greg Clayton24b48ff2010-10-17 22:03:32 +0000790 // For linux we are currently assuming the location of the lldb
791 // binary that contains this function is the directory that will
792 // contain lldb.so, lldb.py and embedded_interpreter.py...
793
794 static ConstString g_lldb_python_dir;
795 if (!g_lldb_python_dir)
796 {
797 FileSpec lldb_file_spec;
798 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
799 {
800 char raw_path[PATH_MAX];
801 char resolved_path[PATH_MAX];
802 lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
803
804#if defined (__APPLE__)
805 char *framework_pos = ::strstr (raw_path, "LLDB.framework");
806 if (framework_pos)
807 {
808 framework_pos += strlen("LLDB.framework");
809 ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path));
810 }
811#endif
812 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
813 g_lldb_python_dir.SetCString(resolved_path);
814 }
815 }
816 file_spec.GetDirectory() = g_lldb_python_dir;
817 return file_spec.GetDirectory();
818 }
819 break;
820
Greg Clayton52fd9842011-02-02 02:24:04 +0000821 case ePathTypeLLDBSystemPlugins: // System plug-ins directory
822 {
823#if defined (__APPLE__)
824 static ConstString g_lldb_system_plugin_dir;
825 if (!g_lldb_system_plugin_dir)
826 {
827 FileSpec lldb_file_spec;
828 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
829 {
830 char raw_path[PATH_MAX];
831 char resolved_path[PATH_MAX];
832 lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
833
834 char *framework_pos = ::strstr (raw_path, "LLDB.framework");
835 if (framework_pos)
836 {
837 framework_pos += strlen("LLDB.framework");
838 ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path));
839 }
840 FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
841 g_lldb_system_plugin_dir.SetCString(resolved_path);
842 }
843 }
844 file_spec.GetDirectory() = g_lldb_system_plugin_dir;
845 return file_spec.GetDirectory();
846#endif
847 // TODO: where would system LLDB plug-ins be located on linux? Other systems?
848 return false;
849 }
850 break;
851
852 case ePathTypeLLDBUserPlugins: // User plug-ins directory
853 {
854#if defined (__APPLE__)
855 static ConstString g_lldb_user_plugin_dir;
856 if (!g_lldb_user_plugin_dir)
857 {
858 char user_plugin_path[PATH_MAX];
859 if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns",
860 user_plugin_path,
861 sizeof(user_plugin_path)))
862 {
863 g_lldb_user_plugin_dir.SetCString(user_plugin_path);
864 }
865 }
866 file_spec.GetDirectory() = g_lldb_user_plugin_dir;
867 return file_spec.GetDirectory();
868#endif
869 // TODO: where would user LLDB plug-ins be located on linux? Other systems?
870 return false;
871 }
Greg Clayton24b48ff2010-10-17 22:03:32 +0000872 default:
873 assert (!"Unhandled PathType");
874 break;
875 }
876
877 return false;
878}
879
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000880uint32_t
881Host::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
882{
883 uint32_t num_matches = 0;
884
885#if defined (__APPLE__)
886 int num_pids;
887 int size_of_pids;
Greg Claytonfb8876d2010-10-10 22:07:18 +0000888 std::vector<int> pid_list;
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000889
890 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
891 if (size_of_pids == -1)
892 return 0;
893
894 num_pids = size_of_pids/sizeof(int);
Greg Claytonfb8876d2010-10-10 22:07:18 +0000895
896 pid_list.resize (size_of_pids);
897 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, &pid_list[0], size_of_pids);
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000898 if (size_of_pids == -1)
899 return 0;
900
901 lldb::pid_t our_pid = getpid();
902
903 for (int i = 0; i < num_pids; i++)
904 {
905 struct proc_bsdinfo bsd_info;
906 int error = proc_pidinfo (pid_list[i], PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
907 if (error == 0)
908 continue;
909
910 // Don't offer to attach to zombie processes, already traced or exiting
911 // processes, and of course, ourselves... It looks like passing the second arg of
912 // 0 to proc_listpids will exclude zombies anyway, but that's not documented so...
913 if (((bsd_info.pbi_flags & (PROC_FLAG_TRACED | PROC_FLAG_INEXIT)) != 0)
914 || (bsd_info.pbi_status == SZOMB)
915 || (bsd_info.pbi_pid == our_pid))
916 continue;
917 char pid_name[MAXCOMLEN * 2 + 1];
918 int name_len;
919 name_len = proc_name(bsd_info.pbi_pid, pid_name, MAXCOMLEN * 2);
920 if (name_len == 0)
921 continue;
922
923 if (strstr(pid_name, name) != pid_name)
924 continue;
925 matches.AppendString (pid_name);
926 pids.push_back (bsd_info.pbi_pid);
927 num_matches++;
928 }
929#endif
930
931 return num_matches;
932}
933
934ArchSpec
935Host::GetArchSpecForExistingProcess (lldb::pid_t pid)
936{
937 ArchSpec return_spec;
938
939#if defined (__APPLE__)
940 struct proc_bsdinfo bsd_info;
941 int error = proc_pidinfo (pid, PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
942 if (error == 0)
943 return return_spec;
944 if (bsd_info.pbi_flags & PROC_FLAG_LP64)
945 return_spec.SetArch(LLDB_ARCH_DEFAULT_64BIT);
946 else
947 return_spec.SetArch(LLDB_ARCH_DEFAULT_32BIT);
948#endif
949
950 return return_spec;
951}
952
953ArchSpec
954Host::GetArchSpecForExistingProcess (const char *process_name)
955{
956 ArchSpec returnSpec;
957 StringList matches;
958 std::vector<lldb::pid_t> pids;
959 if (ListProcessesMatchingName(process_name, matches, pids))
960 {
961 if (matches.GetSize() == 1)
962 {
963 return GetArchSpecForExistingProcess(pids[0]);
964 }
965 }
966 return returnSpec;
967}
968
969#if !defined (__APPLE__) // see macosx/Host.mm
970bool
Greg Claytonb73620c2010-12-18 01:54:34 +0000971Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no)
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000972{
973 return false;
974}
Greg Clayton24b48ff2010-10-17 22:03:32 +0000975
Greg Claytone98ac252010-11-10 04:57:04 +0000976void
977Host::SetCrashDescriptionWithFormat (const char *format, ...)
978{
979}
980
981void
982Host::SetCrashDescription (const char *description)
983{
984}
Greg Clayton24b48ff2010-10-17 22:03:32 +0000985
986lldb::pid_t
987LaunchApplication (const FileSpec &app_file_spec)
988{
989 return LLDB_INVALID_PROCESS_ID;
990}
991
992lldb::pid_t
993Host::LaunchInNewTerminal
994(
Greg Claytonb73620c2010-12-18 01:54:34 +0000995 const char *tty_name,
Greg Clayton24b48ff2010-10-17 22:03:32 +0000996 const char **argv,
997 const char **envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000998 const char *working_dir,
Greg Clayton24b48ff2010-10-17 22:03:32 +0000999 const ArchSpec *arch_spec,
1000 bool stop_at_entry,
1001 bool disable_aslr
1002)
1003{
1004 return LLDB_INVALID_PROCESS_ID;
1005}
1006
Greg Clayton8f3b21d2010-09-07 20:11:56 +00001007#endif