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/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/Log.h"
15 #include "lldb/Core/StreamString.h"
16 #include "lldb/Host/Config.h"
17 #include "lldb/Host/Endian.h"
18 #include "lldb/Host/FileSpec.h"
19 #include "lldb/Host/Mutex.h"
20 #include "lldb/Target/Process.h"
21 
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/MachO.h"
24 
25 #include <dlfcn.h>
26 #include <errno.h>
27 #include <grp.h>
28 #include <limits.h>
29 #include <netdb.h>
30 #include <pwd.h>
31 #include <sys/types.h>
32 
33 
34 #if defined (__APPLE__)
35 
36 #include <dispatch/dispatch.h>
37 #include <libproc.h>
38 #include <mach-o/dyld.h>
39 #include <sys/sysctl.h>
40 
41 
42 #elif defined (__linux__)
43 
44 #include <sys/wait.h>
45 
46 #endif
47 
48 using namespace lldb;
49 using namespace lldb_private;
50 
51 struct MonitorInfo
52 {
53     lldb::pid_t pid;                            // The process ID to monitor
54     Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals
55     void *callback_baton;                       // The callback baton for the callback function
56     bool monitor_signals;                       // If true, call the callback when "pid" gets signaled.
57 };
58 
59 static void *
60 MonitorChildProcessThreadFunction (void *arg);
61 
62 lldb::thread_t
63 Host::StartMonitoringChildProcess
64 (
65     Host::MonitorChildProcessCallback callback,
66     void *callback_baton,
67     lldb::pid_t pid,
68     bool monitor_signals
69 )
70 {
71     lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
72     if (callback)
73     {
74         std::auto_ptr<MonitorInfo> info_ap(new MonitorInfo);
75 
76         info_ap->pid = pid;
77         info_ap->callback = callback;
78         info_ap->callback_baton = callback_baton;
79         info_ap->monitor_signals = monitor_signals;
80 
81         char thread_name[256];
82         ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid);
83         thread = ThreadCreate (thread_name,
84                                MonitorChildProcessThreadFunction,
85                                info_ap.get(),
86                                NULL);
87 
88         if (IS_VALID_LLDB_HOST_THREAD(thread))
89             info_ap.release();
90     }
91     return thread;
92 }
93 
94 //------------------------------------------------------------------
95 // Scoped class that will disable thread canceling when it is
96 // constructed, and exception safely restore the previous value it
97 // when it goes out of scope.
98 //------------------------------------------------------------------
99 class ScopedPThreadCancelDisabler
100 {
101 public:
102     ScopedPThreadCancelDisabler()
103     {
104         // Disable the ability for this thread to be cancelled
105         int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
106         if (err != 0)
107             m_old_state = -1;
108 
109     }
110 
111     ~ScopedPThreadCancelDisabler()
112     {
113         // Restore the ability for this thread to be cancelled to what it
114         // previously was.
115         if (m_old_state != -1)
116             ::pthread_setcancelstate (m_old_state, 0);
117     }
118 private:
119     int m_old_state;    // Save the old cancelability state.
120 };
121 
122 static void *
123 MonitorChildProcessThreadFunction (void *arg)
124 {
125     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
126     const char *function = __FUNCTION__;
127     if (log)
128         log->Printf ("%s (arg = %p) thread starting...", function, arg);
129 
130     MonitorInfo *info = (MonitorInfo *)arg;
131 
132     const Host::MonitorChildProcessCallback callback = info->callback;
133     void * const callback_baton = info->callback_baton;
134     const lldb::pid_t pid = info->pid;
135     const bool monitor_signals = info->monitor_signals;
136 
137     delete info;
138 
139     int status = -1;
140     const int options = 0;
141     struct rusage *rusage = NULL;
142     while (1)
143     {
144         log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
145         if (log)
146             log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, pid, options, rusage);
147 
148         // Wait for all child processes
149         ::pthread_testcancel ();
150         const lldb::pid_t wait_pid = ::wait4 (pid, &status, options, rusage);
151         ::pthread_testcancel ();
152 
153         if (wait_pid == -1)
154         {
155             if (errno == EINTR)
156                 continue;
157             else
158                 break;
159         }
160         else if (wait_pid == pid)
161         {
162             bool exited = false;
163             int signal = 0;
164             int exit_status = 0;
165             const char *status_cstr = NULL;
166             if (WIFSTOPPED(status))
167             {
168                 signal = WSTOPSIG(status);
169                 status_cstr = "STOPPED";
170             }
171             else if (WIFEXITED(status))
172             {
173                 exit_status = WEXITSTATUS(status);
174                 status_cstr = "EXITED";
175                 exited = true;
176             }
177             else if (WIFSIGNALED(status))
178             {
179                 signal = WTERMSIG(status);
180                 status_cstr = "SIGNALED";
181                 exited = true;
182                 exit_status = -1;
183             }
184             else
185             {
186                 status_cstr = "(???)";
187             }
188 
189             // Scope for pthread_cancel_disabler
190             {
191                 ScopedPThreadCancelDisabler pthread_cancel_disabler;
192 
193                 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
194                 if (log)
195                     log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
196                                  function,
197                                  wait_pid,
198                                  options,
199                                  rusage,
200                                  pid,
201                                  status,
202                                  status_cstr,
203                                  signal,
204                                  exit_status);
205 
206                 if (exited || (signal != 0 && monitor_signals))
207                 {
208                     bool callback_return = callback (callback_baton, pid, signal, exit_status);
209 
210                     // If our process exited, then this thread should exit
211                     if (exited)
212                         break;
213                     // If the callback returns true, it means this process should
214                     // exit
215                     if (callback_return)
216                         break;
217                 }
218             }
219         }
220     }
221 
222     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
223     if (log)
224         log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg);
225 
226     return NULL;
227 }
228 
229 size_t
230 Host::GetPageSize()
231 {
232     return ::getpagesize();
233 }
234 
235 const ArchSpec &
236 Host::GetArchitecture (SystemDefaultArchitecture arch_kind)
237 {
238     static bool g_supports_32 = false;
239     static bool g_supports_64 = false;
240     static ArchSpec g_host_arch_32;
241     static ArchSpec g_host_arch_64;
242 
243 #if defined (__APPLE__)
244 
245     // Apple is different in that it can support both 32 and 64 bit executables
246     // in the same operating system running concurrently. Here we detect the
247     // correct host architectures for both 32 and 64 bit including if 64 bit
248     // executables are supported on the system.
249 
250     if (g_supports_32 == false && g_supports_64 == false)
251     {
252         // All apple systems support 32 bit execution.
253         g_supports_32 = true;
254         uint32_t cputype, cpusubtype;
255         uint32_t is_64_bit_capable = false;
256         size_t len = sizeof(cputype);
257         ArchSpec host_arch;
258         // These will tell us about the kernel architecture, which even on a 64
259         // bit machine can be 32 bit...
260         if  (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
261         {
262             len = sizeof (cpusubtype);
263             if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0)
264                 cpusubtype = CPU_TYPE_ANY;
265 
266             len = sizeof (is_64_bit_capable);
267             if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
268             {
269                 if (is_64_bit_capable)
270                     g_supports_64 = true;
271             }
272 
273             if (is_64_bit_capable)
274             {
275 #if defined (__i386__) || defined (__x86_64__)
276                 if (cpusubtype == CPU_SUBTYPE_486)
277                     cpusubtype = CPU_SUBTYPE_I386_ALL;
278 #endif
279                 if (cputype & CPU_ARCH_ABI64)
280                 {
281                     // We have a 64 bit kernel on a 64 bit system
282                     g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype);
283                     g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
284                 }
285                 else
286                 {
287                     // We have a 32 bit kernel on a 64 bit system
288                     g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
289                     cputype |= CPU_ARCH_ABI64;
290                     g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
291                 }
292             }
293             else
294             {
295                 g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype);
296                 g_host_arch_64.Clear();
297             }
298         }
299     }
300 
301 #else // #if defined (__APPLE__)
302 
303     if (g_supports_32 == false && g_supports_64 == false)
304     {
305         llvm::Triple triple(llvm::sys::getHostTriple());
306 
307         g_host_arch_32.Clear();
308         g_host_arch_64.Clear();
309 
310         switch (triple.getArch())
311         {
312         default:
313             g_host_arch_32.SetTriple(triple);
314             g_supports_32 = true;
315             break;
316 
317         case llvm::Triple::alpha:
318         case llvm::Triple::x86_64:
319         case llvm::Triple::sparcv9:
320         case llvm::Triple::ppc64:
321         case llvm::Triple::systemz:
322         case llvm::Triple::cellspu:
323             g_host_arch_64.SetTriple(triple);
324             g_supports_64 = true;
325             break;
326         }
327 
328         g_supports_32 = g_host_arch_32.IsValid();
329         g_supports_64 = g_host_arch_64.IsValid();
330     }
331 
332 #endif // #else for #if defined (__APPLE__)
333 
334     if (arch_kind == eSystemDefaultArchitecture32)
335         return g_host_arch_32;
336     else if (arch_kind == eSystemDefaultArchitecture64)
337         return g_host_arch_64;
338 
339     if (g_supports_64)
340         return g_host_arch_64;
341 
342     return g_host_arch_32;
343 }
344 
345 const ConstString &
346 Host::GetVendorString()
347 {
348     static ConstString g_vendor;
349     if (!g_vendor)
350     {
351 #if defined (__APPLE__)
352         char ostype[64];
353         size_t len = sizeof(ostype);
354         if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
355             g_vendor.SetCString (ostype);
356         else
357             g_vendor.SetCString("apple");
358 #elif defined (__linux__)
359         g_vendor.SetCString("gnu");
360 #endif
361     }
362     return g_vendor;
363 }
364 
365 const ConstString &
366 Host::GetOSString()
367 {
368     static ConstString g_os_string;
369     if (!g_os_string)
370     {
371 #if defined (__APPLE__)
372         g_os_string.SetCString("darwin");
373 #elif defined (__linux__)
374         g_os_string.SetCString("linux");
375 #endif
376     }
377     return g_os_string;
378 }
379 
380 const ConstString &
381 Host::GetTargetTriple()
382 {
383     static ConstString g_host_triple;
384     if (!(g_host_triple))
385     {
386         StreamString triple;
387         triple.Printf("%s-%s-%s",
388                       GetArchitecture().GetArchitectureName(),
389                       GetVendorString().AsCString(),
390                       GetOSString().AsCString());
391 
392         std::transform (triple.GetString().begin(),
393                         triple.GetString().end(),
394                         triple.GetString().begin(),
395                         ::tolower);
396 
397         g_host_triple.SetCString(triple.GetString().c_str());
398     }
399     return g_host_triple;
400 }
401 
402 lldb::pid_t
403 Host::GetCurrentProcessID()
404 {
405     return ::getpid();
406 }
407 
408 lldb::tid_t
409 Host::GetCurrentThreadID()
410 {
411 #if defined (__APPLE__)
412     return ::mach_thread_self();
413 #else
414     return lldb::tid_t(pthread_self());
415 #endif
416 }
417 
418 const char *
419 Host::GetSignalAsCString (int signo)
420 {
421     switch (signo)
422     {
423     case SIGHUP:    return "SIGHUP";    // 1    hangup
424     case SIGINT:    return "SIGINT";    // 2    interrupt
425     case SIGQUIT:   return "SIGQUIT";   // 3    quit
426     case SIGILL:    return "SIGILL";    // 4    illegal instruction (not reset when caught)
427     case SIGTRAP:   return "SIGTRAP";   // 5    trace trap (not reset when caught)
428     case SIGABRT:   return "SIGABRT";   // 6    abort()
429 #if  defined(_POSIX_C_SOURCE)
430     case SIGPOLL:   return "SIGPOLL";   // 7    pollable event ([XSR] generated, not supported)
431 #else    // !_POSIX_C_SOURCE
432     case SIGEMT:    return "SIGEMT";    // 7    EMT instruction
433 #endif    // !_POSIX_C_SOURCE
434     case SIGFPE:    return "SIGFPE";    // 8    floating point exception
435     case SIGKILL:   return "SIGKILL";   // 9    kill (cannot be caught or ignored)
436     case SIGBUS:    return "SIGBUS";    // 10    bus error
437     case SIGSEGV:   return "SIGSEGV";   // 11    segmentation violation
438     case SIGSYS:    return "SIGSYS";    // 12    bad argument to system call
439     case SIGPIPE:   return "SIGPIPE";   // 13    write on a pipe with no one to read it
440     case SIGALRM:   return "SIGALRM";   // 14    alarm clock
441     case SIGTERM:   return "SIGTERM";   // 15    software termination signal from kill
442     case SIGURG:    return "SIGURG";    // 16    urgent condition on IO channel
443     case SIGSTOP:   return "SIGSTOP";   // 17    sendable stop signal not from tty
444     case SIGTSTP:   return "SIGTSTP";   // 18    stop signal from tty
445     case SIGCONT:   return "SIGCONT";   // 19    continue a stopped process
446     case SIGCHLD:   return "SIGCHLD";   // 20    to parent on child stop or exit
447     case SIGTTIN:   return "SIGTTIN";   // 21    to readers pgrp upon background tty read
448     case SIGTTOU:   return "SIGTTOU";   // 22    like TTIN for output if (tp->t_local&LTOSTOP)
449 #if  !defined(_POSIX_C_SOURCE)
450     case SIGIO:     return "SIGIO";     // 23    input/output possible signal
451 #endif
452     case SIGXCPU:   return "SIGXCPU";   // 24    exceeded CPU time limit
453     case SIGXFSZ:   return "SIGXFSZ";   // 25    exceeded file size limit
454     case SIGVTALRM: return "SIGVTALRM"; // 26    virtual time alarm
455     case SIGPROF:   return "SIGPROF";   // 27    profiling time alarm
456 #if  !defined(_POSIX_C_SOURCE)
457     case SIGWINCH:  return "SIGWINCH";  // 28    window size changes
458     case SIGINFO:   return "SIGINFO";   // 29    information request
459 #endif
460     case SIGUSR1:   return "SIGUSR1";   // 30    user defined signal 1
461     case SIGUSR2:   return "SIGUSR2";   // 31    user defined signal 2
462     default:
463         break;
464     }
465     return NULL;
466 }
467 
468 void
469 Host::WillTerminate ()
470 {
471 }
472 
473 #if !defined (__APPLE__) // see macosx/Host.mm
474 void
475 Host::ThreadCreated (const char *thread_name)
476 {
477 }
478 
479 void
480 Host::Backtrace (Stream &strm, uint32_t max_frames)
481 {
482     // TODO: Is there a way to backtrace the current process on linux? Other systems?
483 }
484 
485 
486 size_t
487 Host::GetEnvironment (StringList &env)
488 {
489     // TODO: Is there a way to the host environment for this process on linux? Other systems?
490     return 0;
491 }
492 
493 #endif
494 
495 struct HostThreadCreateInfo
496 {
497     std::string thread_name;
498     thread_func_t thread_fptr;
499     thread_arg_t thread_arg;
500 
501     HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) :
502         thread_name (name ? name : ""),
503         thread_fptr (fptr),
504         thread_arg (arg)
505     {
506     }
507 };
508 
509 static thread_result_t
510 ThreadCreateTrampoline (thread_arg_t arg)
511 {
512     HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
513     Host::ThreadCreated (info->thread_name.c_str());
514     thread_func_t thread_fptr = info->thread_fptr;
515     thread_arg_t thread_arg = info->thread_arg;
516 
517     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
518     if (log)
519         log->Printf("thread created");
520 
521     delete info;
522     return thread_fptr (thread_arg);
523 }
524 
525 lldb::thread_t
526 Host::ThreadCreate
527 (
528     const char *thread_name,
529     thread_func_t thread_fptr,
530     thread_arg_t thread_arg,
531     Error *error
532 )
533 {
534     lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
535 
536     // Host::ThreadCreateTrampoline will delete this pointer for us.
537     HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
538 
539     int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
540     if (err == 0)
541     {
542         if (error)
543             error->Clear();
544         return thread;
545     }
546 
547     if (error)
548         error->SetError (err, eErrorTypePOSIX);
549 
550     return LLDB_INVALID_HOST_THREAD;
551 }
552 
553 bool
554 Host::ThreadCancel (lldb::thread_t thread, Error *error)
555 {
556     int err = ::pthread_cancel (thread);
557     if (error)
558         error->SetError(err, eErrorTypePOSIX);
559     return err == 0;
560 }
561 
562 bool
563 Host::ThreadDetach (lldb::thread_t thread, Error *error)
564 {
565     int err = ::pthread_detach (thread);
566     if (error)
567         error->SetError(err, eErrorTypePOSIX);
568     return err == 0;
569 }
570 
571 bool
572 Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error)
573 {
574     int err = ::pthread_join (thread, thread_result_ptr);
575     if (error)
576         error->SetError(err, eErrorTypePOSIX);
577     return err == 0;
578 }
579 
580 //------------------------------------------------------------------
581 // Control access to a static file thread name map using a single
582 // static function to avoid a static constructor.
583 //------------------------------------------------------------------
584 static const char *
585 ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
586 {
587     uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
588 
589     static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
590     Mutex::Locker locker(&g_mutex);
591 
592     typedef std::map<uint64_t, std::string> thread_name_map;
593     // rdar://problem/8153284
594     // Fixed a crasher where during shutdown, loggings attempted to access the
595     // thread name but the static map instance had already been destructed.
596     // Another approach is to introduce a static guard object which monitors its
597     // own destruction and raises a flag, but this incurs more overhead.
598     static thread_name_map *g_thread_names_ptr = new thread_name_map();
599     thread_name_map &g_thread_names = *g_thread_names_ptr;
600 
601     if (get)
602     {
603         // See if the thread name exists in our thread name pool
604         thread_name_map::iterator pos = g_thread_names.find(pid_tid);
605         if (pos != g_thread_names.end())
606             return pos->second.c_str();
607     }
608     else
609     {
610         // Set the thread name
611         g_thread_names[pid_tid] = name;
612     }
613     return NULL;
614 }
615 
616 const char *
617 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
618 {
619     const char *name = ThreadNameAccessor (true, pid, tid, NULL);
620     if (name == NULL)
621     {
622 #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
623         // We currently can only get the name of a thread in the current process.
624         if (pid == Host::GetCurrentProcessID())
625         {
626             char pthread_name[1024];
627             if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
628             {
629                 if (pthread_name[0])
630                 {
631                     // Set the thread in our string pool
632                     ThreadNameAccessor (false, pid, tid, pthread_name);
633                     // Get our copy of the thread name string
634                     name = ThreadNameAccessor (true, pid, tid, NULL);
635                 }
636             }
637 
638             if (name == NULL)
639             {
640                 dispatch_queue_t current_queue = ::dispatch_get_current_queue ();
641                 if (current_queue != NULL)
642                     name = dispatch_queue_get_label (current_queue);
643             }
644         }
645 #endif
646     }
647     return name;
648 }
649 
650 void
651 Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
652 {
653     lldb::pid_t curr_pid = Host::GetCurrentProcessID();
654     lldb::tid_t curr_tid = Host::GetCurrentThreadID();
655     if (pid == LLDB_INVALID_PROCESS_ID)
656         pid = curr_pid;
657 
658     if (tid == LLDB_INVALID_THREAD_ID)
659         tid = curr_tid;
660 
661 #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
662     // Set the pthread name if possible
663     if (pid == curr_pid && tid == curr_tid)
664     {
665         ::pthread_setname_np (name);
666     }
667 #endif
668     ThreadNameAccessor (false, pid, tid, name);
669 }
670 
671 FileSpec
672 Host::GetProgramFileSpec ()
673 {
674     static FileSpec g_program_filespec;
675     if (!g_program_filespec)
676     {
677 #if defined (__APPLE__)
678         char program_fullpath[PATH_MAX];
679         // If DST is NULL, then return the number of bytes needed.
680         uint32_t len = sizeof(program_fullpath);
681         int err = _NSGetExecutablePath (program_fullpath, &len);
682         if (err == 0)
683             g_program_filespec.SetFile (program_fullpath, false);
684         else if (err == -1)
685         {
686             char *large_program_fullpath = (char *)::malloc (len + 1);
687 
688             err = _NSGetExecutablePath (large_program_fullpath, &len);
689             if (err == 0)
690                 g_program_filespec.SetFile (large_program_fullpath, false);
691 
692             ::free (large_program_fullpath);
693         }
694 #elif defined (__linux__)
695         char exe_path[PATH_MAX];
696         ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
697         if (len > 0) {
698             exe_path[len] = 0;
699             g_program_filespec.SetFile(exe_path, false);
700         }
701 #elif defined (__FreeBSD__)
702         int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
703         size_t exe_path_size;
704         if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0)
705         {
706             char *exe_path = new char[exe_path_size];
707             if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
708                 g_program_filespec.SetFile(exe_path, false);
709             delete[] exe_path;
710         }
711 #endif
712     }
713     return g_program_filespec;
714 }
715 
716 FileSpec
717 Host::GetModuleFileSpecForHostAddress (const void *host_addr)
718 {
719     FileSpec module_filespec;
720     Dl_info info;
721     if (::dladdr (host_addr, &info))
722     {
723         if (info.dli_fname)
724             module_filespec.SetFile(info.dli_fname, true);
725     }
726     return module_filespec;
727 }
728 
729 #if !defined (__APPLE__) // see Host.mm
730 bool
731 Host::ResolveExecutableInBundle (FileSpec &file)
732 {
733     return false;
734 }
735 #endif
736 
737 // Opaque info that tracks a dynamic library that was loaded
738 struct DynamicLibraryInfo
739 {
740     DynamicLibraryInfo (const FileSpec &fs, int o, void *h) :
741         file_spec (fs),
742         open_options (o),
743         handle (h)
744     {
745     }
746 
747     const FileSpec file_spec;
748     uint32_t open_options;
749     void * handle;
750 };
751 
752 void *
753 Host::DynamicLibraryOpen (const FileSpec &file_spec, uint32_t options, Error &error)
754 {
755     char path[PATH_MAX];
756     if (file_spec.GetPath(path, sizeof(path)))
757     {
758         int mode = 0;
759 
760         if (options & eDynamicLibraryOpenOptionLazy)
761             mode |= RTLD_LAZY;
762         else
763             mode |= RTLD_NOW;
764 
765 
766         if (options & eDynamicLibraryOpenOptionLocal)
767             mode |= RTLD_LOCAL;
768         else
769             mode |= RTLD_GLOBAL;
770 
771 #ifdef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED
772         if (options & eDynamicLibraryOpenOptionLimitGetSymbol)
773             mode |= RTLD_FIRST;
774 #endif
775 
776         void * opaque = ::dlopen (path, mode);
777 
778         if (opaque)
779         {
780             error.Clear();
781             return new DynamicLibraryInfo (file_spec, options, opaque);
782         }
783         else
784         {
785             error.SetErrorString(::dlerror());
786         }
787     }
788     else
789     {
790         error.SetErrorString("failed to extract path");
791     }
792     return NULL;
793 }
794 
795 Error
796 Host::DynamicLibraryClose (void *opaque)
797 {
798     Error error;
799     if (opaque == NULL)
800     {
801         error.SetErrorString ("invalid dynamic library handle");
802     }
803     else
804     {
805         DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque;
806         if (::dlclose (dylib_info->handle) != 0)
807         {
808             error.SetErrorString(::dlerror());
809         }
810 
811         dylib_info->open_options = 0;
812         dylib_info->handle = 0;
813         delete dylib_info;
814     }
815     return error;
816 }
817 
818 void *
819 Host::DynamicLibraryGetSymbol (void *opaque, const char *symbol_name, Error &error)
820 {
821     if (opaque == NULL)
822     {
823         error.SetErrorString ("invalid dynamic library handle");
824     }
825     else
826     {
827         DynamicLibraryInfo *dylib_info = (DynamicLibraryInfo *) opaque;
828 
829         void *symbol_addr = ::dlsym (dylib_info->handle, symbol_name);
830         if (symbol_addr)
831         {
832 #ifndef LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED
833             // This host doesn't support limiting searches to this shared library
834             // so we need to verify that the match came from this shared library
835             // if it was requested in the Host::DynamicLibraryOpen() function.
836             if (dylib_info->open_options & eDynamicLibraryOpenOptionLimitGetSymbol)
837             {
838                 FileSpec match_dylib_spec (Host::GetModuleFileSpecForHostAddress (symbol_addr));
839                 if (match_dylib_spec != dylib_info->file_spec)
840                 {
841                     char dylib_path[PATH_MAX];
842                     if (dylib_info->file_spec.GetPath (dylib_path, sizeof(dylib_path)))
843                         error.SetErrorStringWithFormat ("symbol not found in \"%s\"", dylib_path);
844                     else
845                         error.SetErrorString ("symbol not found");
846                     return NULL;
847                 }
848             }
849 #endif
850             error.Clear();
851             return symbol_addr;
852         }
853         else
854         {
855             error.SetErrorString(::dlerror());
856         }
857     }
858     return NULL;
859 }
860 
861 bool
862 Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
863 {
864     // To get paths related to LLDB we get the path to the executable that
865     // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
866     // on linux this is assumed to be the "lldb" main executable. If LLDB on
867     // linux is actually in a shared library (lldb.so??) then this function will
868     // need to be modified to "do the right thing".
869 
870     switch (path_type)
871     {
872     case ePathTypeLLDBShlibDir:
873         {
874             static ConstString g_lldb_so_dir;
875             if (!g_lldb_so_dir)
876             {
877                 FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
878                 g_lldb_so_dir = lldb_file_spec.GetDirectory();
879             }
880             file_spec.GetDirectory() = g_lldb_so_dir;
881             return file_spec.GetDirectory();
882         }
883         break;
884 
885     case ePathTypeSupportExecutableDir:
886         {
887             static ConstString g_lldb_support_exe_dir;
888             if (!g_lldb_support_exe_dir)
889             {
890                 FileSpec lldb_file_spec;
891                 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
892                 {
893                     char raw_path[PATH_MAX];
894                     char resolved_path[PATH_MAX];
895                     lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
896 
897 #if defined (__APPLE__)
898                     char *framework_pos = ::strstr (raw_path, "LLDB.framework");
899                     if (framework_pos)
900                     {
901                         framework_pos += strlen("LLDB.framework");
902                         ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
903                     }
904 #endif
905                     FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
906                     g_lldb_support_exe_dir.SetCString(resolved_path);
907                 }
908             }
909             file_spec.GetDirectory() = g_lldb_support_exe_dir;
910             return file_spec.GetDirectory();
911         }
912         break;
913 
914     case ePathTypeHeaderDir:
915         {
916             static ConstString g_lldb_headers_dir;
917             if (!g_lldb_headers_dir)
918             {
919 #if defined (__APPLE__)
920                 FileSpec lldb_file_spec;
921                 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
922                 {
923                     char raw_path[PATH_MAX];
924                     char resolved_path[PATH_MAX];
925                     lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
926 
927                     char *framework_pos = ::strstr (raw_path, "LLDB.framework");
928                     if (framework_pos)
929                     {
930                         framework_pos += strlen("LLDB.framework");
931                         ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path));
932                     }
933                     FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
934                     g_lldb_headers_dir.SetCString(resolved_path);
935                 }
936 #else
937                 // TODO: Anyone know how we can determine this for linux? Other systems??
938                 g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
939 #endif
940             }
941             file_spec.GetDirectory() = g_lldb_headers_dir;
942             return file_spec.GetDirectory();
943         }
944         break;
945 
946     case ePathTypePythonDir:
947         {
948             // TODO: Anyone know how we can determine this for linux? Other systems?
949             // For linux we are currently assuming the location of the lldb
950             // binary that contains this function is the directory that will
951             // contain lldb.so, lldb.py and embedded_interpreter.py...
952 
953             static ConstString g_lldb_python_dir;
954             if (!g_lldb_python_dir)
955             {
956                 FileSpec lldb_file_spec;
957                 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
958                 {
959                     char raw_path[PATH_MAX];
960                     char resolved_path[PATH_MAX];
961                     lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
962 
963 #if defined (__APPLE__)
964                     char *framework_pos = ::strstr (raw_path, "LLDB.framework");
965                     if (framework_pos)
966                     {
967                         framework_pos += strlen("LLDB.framework");
968                         ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path));
969                     }
970 #endif
971                     FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
972                     g_lldb_python_dir.SetCString(resolved_path);
973                 }
974             }
975             file_spec.GetDirectory() = g_lldb_python_dir;
976             return file_spec.GetDirectory();
977         }
978         break;
979 
980     case ePathTypeLLDBSystemPlugins:    // System plug-ins directory
981         {
982 #if defined (__APPLE__)
983             static ConstString g_lldb_system_plugin_dir;
984             static bool g_lldb_system_plugin_dir_located = false;
985             if (!g_lldb_system_plugin_dir_located)
986             {
987                 g_lldb_system_plugin_dir_located = true;
988                 FileSpec lldb_file_spec;
989                 if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
990                 {
991                     char raw_path[PATH_MAX];
992                     char resolved_path[PATH_MAX];
993                     lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
994 
995                     char *framework_pos = ::strstr (raw_path, "LLDB.framework");
996                     if (framework_pos)
997                     {
998                         framework_pos += strlen("LLDB.framework");
999                         ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path));
1000                         FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
1001                         g_lldb_system_plugin_dir.SetCString(resolved_path);
1002                     }
1003                     return false;
1004                 }
1005             }
1006 
1007             if (g_lldb_system_plugin_dir)
1008             {
1009                 file_spec.GetDirectory() = g_lldb_system_plugin_dir;
1010                 return true;
1011             }
1012 #endif
1013             // TODO: where would system LLDB plug-ins be located on linux? Other systems?
1014             return false;
1015         }
1016         break;
1017 
1018     case ePathTypeLLDBUserPlugins:      // User plug-ins directory
1019         {
1020 #if defined (__APPLE__)
1021             static ConstString g_lldb_user_plugin_dir;
1022             if (!g_lldb_user_plugin_dir)
1023             {
1024                 char user_plugin_path[PATH_MAX];
1025                 if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns",
1026                                        user_plugin_path,
1027                                        sizeof(user_plugin_path)))
1028                 {
1029                     g_lldb_user_plugin_dir.SetCString(user_plugin_path);
1030                 }
1031             }
1032             file_spec.GetDirectory() = g_lldb_user_plugin_dir;
1033             return file_spec.GetDirectory();
1034 #endif
1035             // TODO: where would user LLDB plug-ins be located on linux? Other systems?
1036             return false;
1037         }
1038     default:
1039         assert (!"Unhandled PathType");
1040         break;
1041     }
1042 
1043     return false;
1044 }
1045 
1046 
1047 bool
1048 Host::GetHostname (std::string &s)
1049 {
1050     char hostname[PATH_MAX];
1051     hostname[sizeof(hostname) - 1] = '\0';
1052     if (::gethostname (hostname, sizeof(hostname) - 1) == 0)
1053     {
1054         struct hostent* h = ::gethostbyname (hostname);
1055         if (h)
1056             s.assign (h->h_name);
1057         else
1058             s.assign (hostname);
1059         return true;
1060     }
1061     return false;
1062 }
1063 
1064 const char *
1065 Host::GetUserName (uint32_t uid, std::string &user_name)
1066 {
1067     struct passwd user_info;
1068     struct passwd *user_info_ptr = &user_info;
1069     char user_buffer[PATH_MAX];
1070     size_t user_buffer_size = sizeof(user_buffer);
1071     if (::getpwuid_r (uid,
1072                       &user_info,
1073                       user_buffer,
1074                       user_buffer_size,
1075                       &user_info_ptr) == 0)
1076     {
1077         if (user_info_ptr)
1078         {
1079             user_name.assign (user_info_ptr->pw_name);
1080             return user_name.c_str();
1081         }
1082     }
1083     user_name.clear();
1084     return NULL;
1085 }
1086 
1087 const char *
1088 Host::GetGroupName (uint32_t gid, std::string &group_name)
1089 {
1090     char group_buffer[PATH_MAX];
1091     size_t group_buffer_size = sizeof(group_buffer);
1092     struct group group_info;
1093     struct group *group_info_ptr = &group_info;
1094     // Try the threadsafe version first
1095     if (::getgrgid_r (gid,
1096                       &group_info,
1097                       group_buffer,
1098                       group_buffer_size,
1099                       &group_info_ptr) == 0)
1100     {
1101         if (group_info_ptr)
1102         {
1103             group_name.assign (group_info_ptr->gr_name);
1104             return group_name.c_str();
1105         }
1106     }
1107     else
1108     {
1109         // The threadsafe version isn't currently working
1110         // for me on darwin, but the non-threadsafe version
1111         // is, so I am calling it below.
1112         group_info_ptr = ::getgrgid (gid);
1113         if (group_info_ptr)
1114         {
1115             group_name.assign (group_info_ptr->gr_name);
1116             return group_name.c_str();
1117         }
1118     }
1119     group_name.clear();
1120     return NULL;
1121 }
1122 
1123 
1124 #if !defined (__APPLE__) // see macosx/Host.mm
1125 
1126 bool
1127 Host::GetOSBuildString (std::string &s)
1128 {
1129     s.clear();
1130     return false;
1131 }
1132 
1133 bool
1134 Host::GetOSKernelDescription (std::string &s)
1135 {
1136     s.clear();
1137     return false;
1138 }
1139 
1140 uint32_t
1141 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
1142 {
1143     process_infos.Clear();
1144     return process_infos.GetSize();
1145 }
1146 
1147 bool
1148 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
1149 {
1150     process_info.Clear();
1151     return false;
1152 }
1153 
1154 bool
1155 Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no)
1156 {
1157     return false;
1158 }
1159 
1160 void
1161 Host::SetCrashDescriptionWithFormat (const char *format, ...)
1162 {
1163 }
1164 
1165 void
1166 Host::SetCrashDescription (const char *description)
1167 {
1168 }
1169 
1170 lldb::pid_t
1171 LaunchApplication (const FileSpec &app_file_spec)
1172 {
1173     return LLDB_INVALID_PROCESS_ID;
1174 }
1175 
1176 lldb::pid_t
1177 Host::LaunchInNewTerminal
1178 (
1179     const char *tty_name,
1180     const char **argv,
1181     const char **envp,
1182     const char *working_dir,
1183     const ArchSpec *arch_spec,
1184     bool stop_at_entry,
1185     bool disable_aslr
1186 )
1187 {
1188     return LLDB_INVALID_PROCESS_ID;
1189 }
1190 
1191 #endif
1192