Host.cpp revision de9eadc2e60fe8b5df20e9cf93af5c9290c08099
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
48using namespace lldb;
49using namespace lldb_private;
50
51struct 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
59static void *
60MonitorChildProcessThreadFunction (void *arg);
61
62lldb::thread_t
63Host::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//------------------------------------------------------------------
99class ScopedPThreadCancelDisabler
100{
101public:
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    }
118private:
119    int m_old_state;    // Save the old cancelability state.
120};
121
122static void *
123MonitorChildProcessThreadFunction (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
229size_t
230Host::GetPageSize()
231{
232    return ::getpagesize();
233}
234
235const ArchSpec &
236Host::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
345const ConstString &
346Host::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
365const ConstString &
366Host::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
380const ConstString &
381Host::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
402lldb::pid_t
403Host::GetCurrentProcessID()
404{
405    return ::getpid();
406}
407
408lldb::tid_t
409Host::GetCurrentThreadID()
410{
411#if defined (__APPLE__)
412    return ::mach_thread_self();
413#else
414    return lldb::tid_t(pthread_self());
415#endif
416}
417
418const char *
419Host::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
468void
469Host::WillTerminate ()
470{
471}
472
473#if !defined (__APPLE__) // see macosx/Host.mm
474void
475Host::ThreadCreated (const char *thread_name)
476{
477}
478
479void
480Host::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
486size_t
487Host::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
495struct 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
509static thread_result_t
510ThreadCreateTrampoline (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
525lldb::thread_t
526Host::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
553bool
554Host::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
562bool
563Host::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
571bool
572Host::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//------------------------------------------------------------------
584static const char *
585ThreadNameAccessor (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
616const char *
617Host::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
650void
651Host::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
671FileSpec
672Host::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
716FileSpec
717Host::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
730bool
731Host::ResolveExecutableInBundle (FileSpec &file)
732{
733    return false;
734}
735#endif
736
737// Opaque info that tracks a dynamic library that was loaded
738struct 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
752void *
753Host::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
795Error
796Host::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
818void *
819Host::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
861bool
862Host::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
1047bool
1048Host::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
1064const char *
1065Host::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
1087const char *
1088Host::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
1126bool
1127Host::GetOSBuildString (std::string &s)
1128{
1129    s.clear();
1130    return false;
1131}
1132
1133bool
1134Host::GetOSKernelDescription (std::string &s)
1135{
1136    s.clear();
1137    return false;
1138}
1139
1140uint32_t
1141Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
1142{
1143    process_infos.Clear();
1144    return process_infos.GetSize();
1145}
1146
1147bool
1148Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
1149{
1150    process_info.Clear();
1151    return false;
1152}
1153
1154bool
1155Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no)
1156{
1157    return false;
1158}
1159
1160void
1161Host::SetCrashDescriptionWithFormat (const char *format, ...)
1162{
1163}
1164
1165void
1166Host::SetCrashDescription (const char *description)
1167{
1168}
1169
1170lldb::pid_t
1171LaunchApplication (const FileSpec &app_file_spec)
1172{
1173    return LLDB_INVALID_PROCESS_ID;
1174}
1175
1176#endif
1177