PlatformDarwin.cpp revision 242b20558ac2cd662febaf604efd0f6a29e05b42
1//===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-python.h"
11
12#include "PlatformDarwin.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Breakpoint/BreakpointLocation.h"
19#include "lldb/Core/Debugger.h"
20#include "lldb/Core/Error.h"
21#include "lldb/Core/Module.h"
22#include "lldb/Core/ModuleSpec.h"
23#include "lldb/Core/Timer.h"
24#include "lldb/Host/Host.h"
25#include "lldb/Host/Symbols.h"
26#include "lldb/Symbol/ObjectFile.h"
27#include "lldb/Target/Target.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32
33//------------------------------------------------------------------
34/// Default Constructor
35//------------------------------------------------------------------
36PlatformDarwin::PlatformDarwin (bool is_host) :
37    Platform(is_host),  // This is the local host platform
38    m_remote_platform_sp (),
39    m_developer_directory ()
40{
41}
42
43//------------------------------------------------------------------
44/// Destructor.
45///
46/// The destructor is virtual since this class is designed to be
47/// inherited from by the plug-in instance.
48//------------------------------------------------------------------
49PlatformDarwin::~PlatformDarwin()
50{
51}
52
53FileSpec
54PlatformDarwin::LocateExecutableScriptingResource (const ModuleSpec &module_spec)
55{
56    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
57    const ArchSpec *arch = module_spec.GetArchitecturePtr();
58    const UUID *uuid = module_spec.GetUUIDPtr();
59
60    const char* module_directory = exec_fspec->GetDirectory().GetCString();
61
62    // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
63    // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
64    // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
65    // which should be stripped while leaving "this.binary.file" as-is.
66    const char* module_basename = exec_fspec->GetFileNameStrippingExtension().GetCString();
67
68    if (!module_directory || !module_basename)
69        return FileSpec();
70
71    Timer scoped_timer (__PRETTY_FUNCTION__,
72                        "LocateExecutableScriptingResource (file = %s, arch = %s, uuid = %p)",
73                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
74                        arch ? arch->GetArchitectureName() : "<NULL>",
75                        uuid);
76
77    // FIXME: for Python, we cannot allow dots in the middle of the filenames we import.
78    // Theoretically, different scripting languages may have different sets of
79    // forbidden tokens in filenames, and that should be dealt with by each ScriptInterpreter.
80    // For now, we just replace dots with underscores, but if we ever support anything
81    // other than Python we will need to rework this
82    std::auto_ptr<char> module_basename_fixed_ap(new char[strlen(module_basename)+1]);
83    char* module_basename_fixed = module_basename_fixed_ap.get();
84    strcpy(module_basename_fixed, module_basename);
85    while (*module_basename_fixed)
86    {
87        if (*module_basename_fixed == '.')
88            *module_basename_fixed = '_';
89        module_basename_fixed++;
90    }
91    module_basename_fixed = module_basename_fixed_ap.get();
92
93    FileSpec symbol_fspec (Symbols::LocateExecutableSymbolFile(module_spec));
94
95    FileSpec script_fspec;
96
97    StreamString path_string;
98
99    if (symbol_fspec && symbol_fspec.Exists())
100    {
101        // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
102        // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
103        path_string.Printf("%s/../Python/%s.py",symbol_fspec.GetDirectory().AsCString(""),module_basename_fixed);
104        script_fspec.SetFile(path_string.GetData(), true);
105        if (!script_fspec.Exists())
106            script_fspec.Clear();
107    }
108
109    // no symbols or symbols did not have a scripting resource
110    if (!symbol_fspec || !script_fspec)
111    {
112        path_string.Clear();
113        path_string.Printf("%s.framework",module_basename);
114        if (module_directory && strstr(module_directory, path_string.GetData()))
115        {
116            // we are going to be in foo.framework/Versions/X/foo
117            path_string.Clear();
118            // let's go to foo.framework/Versions/X/Resources/Python/foo.py
119            path_string.Printf("%s/Resources/Python/%s.py",module_directory,module_basename_fixed);
120            script_fspec.SetFile(path_string.GetData(), true);
121            if (!script_fspec.Exists())
122                script_fspec.Clear();
123        }
124    }
125
126    return script_fspec;
127}
128
129Error
130PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
131                                   const ArchSpec &exe_arch,
132                                   lldb::ModuleSP &exe_module_sp,
133                                   const FileSpecList *module_search_paths_ptr)
134{
135    Error error;
136    // Nothing special to do here, just use the actual file and architecture
137
138    char exe_path[PATH_MAX];
139    FileSpec resolved_exe_file (exe_file);
140
141    if (IsHost())
142    {
143        // If we have "ls" as the exe_file, resolve the executable loation based on
144        // the current path variables
145        if (!resolved_exe_file.Exists())
146        {
147            exe_file.GetPath (exe_path, sizeof(exe_path));
148            resolved_exe_file.SetFile(exe_path, true);
149        }
150
151        if (!resolved_exe_file.Exists())
152            resolved_exe_file.ResolveExecutableLocation ();
153
154        // Resolve any executable within a bundle on MacOSX
155        Host::ResolveExecutableInBundle (resolved_exe_file);
156
157        if (resolved_exe_file.Exists())
158            error.Clear();
159        else
160        {
161            exe_file.GetPath (exe_path, sizeof(exe_path));
162            error.SetErrorStringWithFormat ("unable to find executable for '%s'", exe_path);
163        }
164    }
165    else
166    {
167        if (m_remote_platform_sp)
168        {
169            error = m_remote_platform_sp->ResolveExecutable (exe_file,
170                                                             exe_arch,
171                                                             exe_module_sp,
172                                                             module_search_paths_ptr);
173        }
174        else
175        {
176            // We may connect to a process and use the provided executable (Don't use local $PATH).
177
178            // Resolve any executable within a bundle on MacOSX
179            Host::ResolveExecutableInBundle (resolved_exe_file);
180
181            if (resolved_exe_file.Exists())
182                error.Clear();
183            else
184                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_exe_file.GetFilename().AsCString(""));
185        }
186    }
187
188
189    if (error.Success())
190    {
191        ModuleSpec module_spec (resolved_exe_file, exe_arch);
192        if (module_spec.GetArchitecture().IsValid())
193        {
194            error = ModuleList::GetSharedModule (module_spec,
195                                                 exe_module_sp,
196                                                 module_search_paths_ptr,
197                                                 NULL,
198                                                 NULL);
199
200            if (error.Fail() || exe_module_sp.get() == NULL || exe_module_sp->GetObjectFile() == NULL)
201            {
202                exe_module_sp.reset();
203                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
204                                                exe_file.GetDirectory().AsCString(""),
205                                                exe_file.GetDirectory() ? "/" : "",
206                                                exe_file.GetFilename().AsCString(""),
207                                                exe_arch.GetArchitectureName());
208            }
209        }
210        else
211        {
212            // No valid architecture was specified, ask the platform for
213            // the architectures that we should be using (in the correct order)
214            // and see if we can find a match that way
215            StreamString arch_names;
216            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
217            {
218                error = ModuleList::GetSharedModule (module_spec,
219                                                     exe_module_sp,
220                                                     module_search_paths_ptr,
221                                                     NULL,
222                                                     NULL);
223                // Did we find an executable using one of the
224                if (error.Success())
225                {
226                    if (exe_module_sp && exe_module_sp->GetObjectFile())
227                        break;
228                    else
229                        error.SetErrorToGenericError();
230                }
231
232                if (idx > 0)
233                    arch_names.PutCString (", ");
234                arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName());
235            }
236
237            if (error.Fail() || !exe_module_sp)
238            {
239                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
240                                                exe_file.GetDirectory().AsCString(""),
241                                                exe_file.GetDirectory() ? "/" : "",
242                                                exe_file.GetFilename().AsCString(""),
243                                                GetShortPluginName(),
244                                                arch_names.GetString().c_str());
245            }
246        }
247    }
248
249    return error;
250}
251
252Error
253PlatformDarwin::ResolveSymbolFile (Target &target,
254                                   const ModuleSpec &sym_spec,
255                                   FileSpec &sym_file)
256{
257    Error error;
258    sym_file = sym_spec.GetSymbolFileSpec();
259    if (sym_file.Exists())
260    {
261        if (sym_file.GetFileType() == FileSpec::eFileTypeDirectory)
262        {
263            sym_file = Symbols::FindSymbolFileInBundle (sym_file,
264                                                        sym_spec.GetUUIDPtr(),
265                                                        sym_spec.GetArchitecturePtr());
266        }
267    }
268    else
269    {
270        if (sym_spec.GetUUID().IsValid())
271        {
272
273        }
274    }
275    return error;
276
277}
278
279
280
281Error
282PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec,
283                                 ModuleSP &module_sp,
284                                 const FileSpecList *module_search_paths_ptr,
285                                 ModuleSP *old_module_sp_ptr,
286                                 bool *did_create_ptr)
287{
288    Error error;
289    module_sp.reset();
290
291    if (IsRemote())
292    {
293        // If we have a remote platform always, let it try and locate
294        // the shared module first.
295        if (m_remote_platform_sp)
296        {
297            error = m_remote_platform_sp->GetSharedModule (module_spec,
298                                                           module_sp,
299                                                           module_search_paths_ptr,
300                                                           old_module_sp_ptr,
301                                                           did_create_ptr);
302        }
303    }
304
305    if (!module_sp)
306    {
307        // Fall back to the local platform and find the file locally
308        error = Platform::GetSharedModule (module_spec,
309                                           module_sp,
310                                           module_search_paths_ptr,
311                                           old_module_sp_ptr,
312                                           did_create_ptr);
313
314        const FileSpec &platform_file = module_spec.GetFileSpec();
315        if (!module_sp && module_search_paths_ptr && platform_file)
316        {
317            // We can try to pull off part of the file path up to the bundle
318            // directory level and try any module search paths...
319            FileSpec bundle_directory;
320            if (Host::GetBundleDirectory (platform_file, bundle_directory))
321            {
322                char platform_path[PATH_MAX];
323                char bundle_dir[PATH_MAX];
324                platform_file.GetPath (platform_path, sizeof(platform_path));
325                const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
326                char new_path[PATH_MAX];
327                size_t num_module_search_paths = module_search_paths_ptr->GetSize();
328                for (size_t i=0; i<num_module_search_paths; ++i)
329                {
330                    const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
331                    if (search_path_len < sizeof(new_path))
332                    {
333                        snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
334                        FileSpec new_file_spec (new_path, false);
335                        if (new_file_spec.Exists())
336                        {
337                            ModuleSpec new_module_spec (module_spec);
338                            new_module_spec.GetFileSpec() = new_file_spec;
339                            Error new_error (Platform::GetSharedModule (new_module_spec,
340                                                                        module_sp,
341                                                                        NULL,
342                                                                        old_module_sp_ptr,
343                                                                        did_create_ptr));
344
345                            if (module_sp)
346                            {
347                                module_sp->SetPlatformFileSpec(new_file_spec);
348                                return new_error;
349                            }
350                        }
351                    }
352                }
353            }
354        }
355    }
356    if (module_sp)
357        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
358    return error;
359}
360
361size_t
362PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
363{
364    const uint8_t *trap_opcode = NULL;
365    uint32_t trap_opcode_size = 0;
366    bool bp_is_thumb = false;
367
368    llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
369    switch (machine)
370    {
371    case llvm::Triple::x86:
372    case llvm::Triple::x86_64:
373        {
374            static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
375            trap_opcode = g_i386_breakpoint_opcode;
376            trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
377        }
378        break;
379
380    case llvm::Triple::thumb:
381        bp_is_thumb = true; // Fall through...
382    case llvm::Triple::arm:
383        {
384            static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
385            static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
386
387            // Auto detect arm/thumb if it wasn't explicitly specified
388            if (!bp_is_thumb)
389            {
390                lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
391                if (bp_loc_sp)
392                    bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA;
393            }
394            if (bp_is_thumb)
395            {
396                trap_opcode = g_thumb_breakpooint_opcode;
397                trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
398                break;
399            }
400            trap_opcode = g_arm_breakpoint_opcode;
401            trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
402        }
403        break;
404
405    case llvm::Triple::ppc:
406    case llvm::Triple::ppc64:
407        {
408            static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
409            trap_opcode = g_ppc_breakpoint_opcode;
410            trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
411        }
412        break;
413
414    default:
415        assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()");
416        break;
417    }
418
419    if (trap_opcode && trap_opcode_size)
420    {
421        if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
422            return trap_opcode_size;
423    }
424    return 0;
425
426}
427
428bool
429PlatformDarwin::GetRemoteOSVersion ()
430{
431    if (m_remote_platform_sp)
432        return m_remote_platform_sp->GetOSVersion (m_major_os_version,
433                                                   m_minor_os_version,
434                                                   m_update_os_version);
435    return false;
436}
437
438bool
439PlatformDarwin::GetRemoteOSBuildString (std::string &s)
440{
441    if (m_remote_platform_sp)
442        return m_remote_platform_sp->GetRemoteOSBuildString (s);
443    s.clear();
444    return false;
445}
446
447bool
448PlatformDarwin::GetRemoteOSKernelDescription (std::string &s)
449{
450    if (m_remote_platform_sp)
451        return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
452    s.clear();
453    return false;
454}
455
456// Remote Platform subclasses need to override this function
457ArchSpec
458PlatformDarwin::GetRemoteSystemArchitecture ()
459{
460    if (m_remote_platform_sp)
461        return m_remote_platform_sp->GetRemoteSystemArchitecture ();
462    return ArchSpec();
463}
464
465
466const char *
467PlatformDarwin::GetHostname ()
468{
469    if (IsHost())
470        return Platform::GetHostname();
471
472    if (m_remote_platform_sp)
473        return m_remote_platform_sp->GetHostname ();
474    return NULL;
475}
476
477bool
478PlatformDarwin::IsConnected () const
479{
480    if (IsHost())
481        return true;
482    else if (m_remote_platform_sp)
483        return m_remote_platform_sp->IsConnected();
484    return false;
485}
486
487Error
488PlatformDarwin::ConnectRemote (Args& args)
489{
490    Error error;
491    if (IsHost())
492    {
493        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName());
494    }
495    else
496    {
497        if (!m_remote_platform_sp)
498            m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
499
500        if (m_remote_platform_sp)
501        {
502            if (error.Success())
503            {
504                if (m_remote_platform_sp)
505                {
506                    error = m_remote_platform_sp->ConnectRemote (args);
507                }
508                else
509                {
510                    error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
511                }
512            }
513        }
514        else
515            error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
516
517        if (error.Fail())
518            m_remote_platform_sp.reset();
519    }
520
521    return error;
522}
523
524Error
525PlatformDarwin::DisconnectRemote ()
526{
527    Error error;
528
529    if (IsHost())
530    {
531        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName());
532    }
533    else
534    {
535        if (m_remote_platform_sp)
536            error = m_remote_platform_sp->DisconnectRemote ();
537        else
538            error.SetErrorString ("the platform is not currently connected");
539    }
540    return error;
541}
542
543
544bool
545PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
546{
547    bool sucess = false;
548    if (IsHost())
549    {
550        sucess = Platform::GetProcessInfo (pid, process_info);
551    }
552    else
553    {
554        if (m_remote_platform_sp)
555            sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
556    }
557    return sucess;
558}
559
560
561
562uint32_t
563PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
564                               ProcessInstanceInfoList &process_infos)
565{
566    uint32_t match_count = 0;
567    if (IsHost())
568    {
569        // Let the base class figure out the host details
570        match_count = Platform::FindProcesses (match_info, process_infos);
571    }
572    else
573    {
574        // If we are remote, we can only return results if we are connected
575        if (m_remote_platform_sp)
576            match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
577    }
578    return match_count;
579}
580
581Error
582PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
583{
584    Error error;
585
586    if (IsHost())
587    {
588        error = Platform::LaunchProcess (launch_info);
589    }
590    else
591    {
592        if (m_remote_platform_sp)
593            error = m_remote_platform_sp->LaunchProcess (launch_info);
594        else
595            error.SetErrorString ("the platform is not currently connected");
596    }
597    return error;
598}
599
600lldb::ProcessSP
601PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
602                        Debugger &debugger,
603                        Target *target,
604                        Listener &listener,
605                        Error &error)
606{
607    lldb::ProcessSP process_sp;
608
609    if (IsHost())
610    {
611        if (target == NULL)
612        {
613            TargetSP new_target_sp;
614
615            error = debugger.GetTargetList().CreateTarget (debugger,
616                                                           NULL,
617                                                           NULL,
618                                                           false,
619                                                           NULL,
620                                                           new_target_sp);
621            target = new_target_sp.get();
622        }
623        else
624            error.Clear();
625
626        if (target && error.Success())
627        {
628            debugger.GetTargetList().SetSelectedTarget(target);
629
630            process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL);
631
632            if (process_sp)
633                error = process_sp->Attach (attach_info);
634        }
635    }
636    else
637    {
638        if (m_remote_platform_sp)
639            process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
640        else
641            error.SetErrorString ("the platform is not currently connected");
642    }
643    return process_sp;
644}
645
646const char *
647PlatformDarwin::GetUserName (uint32_t uid)
648{
649    // Check the cache in Platform in case we have already looked this uid up
650    const char *user_name = Platform::GetUserName(uid);
651    if (user_name)
652        return user_name;
653
654    if (IsRemote() && m_remote_platform_sp)
655        return m_remote_platform_sp->GetUserName(uid);
656    return NULL;
657}
658
659const char *
660PlatformDarwin::GetGroupName (uint32_t gid)
661{
662    const char *group_name = Platform::GetGroupName(gid);
663    if (group_name)
664        return group_name;
665
666    if (IsRemote() && m_remote_platform_sp)
667        return m_remote_platform_sp->GetGroupName(gid);
668    return NULL;
669}
670
671bool
672PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
673{
674    if (!module_sp)
675        return false;
676
677    ObjectFile *obj_file = module_sp->GetObjectFile();
678    if (!obj_file)
679        return false;
680
681    ObjectFile::Type obj_type = obj_file->GetType();
682    if (obj_type == ObjectFile::eTypeDynamicLinker)
683        return true;
684    else
685        return false;
686}
687
688
689bool
690PlatformDarwin::x86GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
691{
692    if (idx == 0)
693    {
694        arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
695        return arch.IsValid();
696    }
697    else if (idx == 1)
698    {
699        ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
700        ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
701        if (platform_arch.IsExactMatch(platform_arch64))
702        {
703            // This macosx platform supports both 32 and 64 bit. Since we already
704            // returned the 64 bit arch for idx == 0, return the 32 bit arch
705            // for idx == 1
706            arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
707            return arch.IsValid();
708        }
709    }
710    return false;
711}
712
713// The architecture selection rules for arm processors
714// These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f processor.
715
716bool
717PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
718{
719    ArchSpec system_arch (GetSystemArchitecture());
720    const ArchSpec::Core system_core = system_arch.GetCore();
721    switch (system_core)
722    {
723    default:
724        switch (idx)
725        {
726            case  0: arch.SetTriple ("armv7-apple-ios");    return true;
727            case  1: arch.SetTriple ("armv7f-apple-ios");   return true;
728            case  2: arch.SetTriple ("armv7k-apple-ios");   return true;
729            case  3: arch.SetTriple ("armv7s-apple-ios");   return true;
730            case  4: arch.SetTriple ("armv6-apple-ios");    return true;
731            case  5: arch.SetTriple ("armv5-apple-ios");    return true;
732            case  6: arch.SetTriple ("armv4-apple-ios");    return true;
733            case  7: arch.SetTriple ("arm-apple-ios");      return true;
734            case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
735            case  9: arch.SetTriple ("thumbv7f-apple-ios"); return true;
736            case 10: arch.SetTriple ("thumbv7k-apple-ios"); return true;
737            case 11: arch.SetTriple ("thumbv7s-apple-ios"); return true;
738            case 12: arch.SetTriple ("thumbv6-apple-ios");  return true;
739            case 13: arch.SetTriple ("thumbv5-apple-ios");  return true;
740            case 14: arch.SetTriple ("thumbv4t-apple-ios"); return true;
741            case 15: arch.SetTriple ("thumb-apple-ios");    return true;
742        default: break;
743        }
744        break;
745
746    case ArchSpec::eCore_arm_armv7f:
747        switch (idx)
748        {
749            case  0: arch.SetTriple ("armv7f-apple-ios");   return true;
750            case  1: arch.SetTriple ("armv7-apple-ios");    return true;
751            case  2: arch.SetTriple ("armv6-apple-ios");    return true;
752            case  3: arch.SetTriple ("armv5-apple-ios");    return true;
753            case  4: arch.SetTriple ("armv4-apple-ios");    return true;
754            case  5: arch.SetTriple ("arm-apple-ios");      return true;
755            case  6: arch.SetTriple ("thumbv7f-apple-ios"); return true;
756            case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
757            case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
758            case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
759            case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
760            case 11: arch.SetTriple ("thumb-apple-ios");    return true;
761            default: break;
762        }
763        break;
764
765    case ArchSpec::eCore_arm_armv7k:
766        switch (idx)
767        {
768            case  0: arch.SetTriple ("armv7k-apple-ios");   return true;
769            case  1: arch.SetTriple ("armv7-apple-ios");    return true;
770            case  2: arch.SetTriple ("armv6-apple-ios");    return true;
771            case  3: arch.SetTriple ("armv5-apple-ios");    return true;
772            case  4: arch.SetTriple ("armv4-apple-ios");    return true;
773            case  5: arch.SetTriple ("arm-apple-ios");      return true;
774            case  6: arch.SetTriple ("thumbv7k-apple-ios"); return true;
775            case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
776            case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
777            case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
778            case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
779            case 11: arch.SetTriple ("thumb-apple-ios");    return true;
780            default: break;
781        }
782        break;
783
784    case ArchSpec::eCore_arm_armv7s:
785        switch (idx)
786        {
787            case  0: arch.SetTriple ("armv7s-apple-ios");   return true;
788            case  1: arch.SetTriple ("armv7-apple-ios");    return true;
789            case  2: arch.SetTriple ("armv6-apple-ios");    return true;
790            case  3: arch.SetTriple ("armv5-apple-ios");    return true;
791            case  4: arch.SetTriple ("armv4-apple-ios");    return true;
792            case  5: arch.SetTriple ("arm-apple-ios");      return true;
793            case  6: arch.SetTriple ("thumbv7s-apple-ios"); return true;
794            case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
795            case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
796            case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
797            case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
798            case 11: arch.SetTriple ("thumb-apple-ios");    return true;
799            default: break;
800        }
801        break;
802
803    case ArchSpec::eCore_arm_armv7:
804        switch (idx)
805        {
806            case 0: arch.SetTriple ("armv7-apple-ios");    return true;
807            case 1: arch.SetTriple ("armv6-apple-ios");    return true;
808            case 2: arch.SetTriple ("armv5-apple-ios");    return true;
809            case 3: arch.SetTriple ("armv4-apple-ios");    return true;
810            case 4: arch.SetTriple ("arm-apple-ios");      return true;
811            case 5: arch.SetTriple ("thumbv7-apple-ios");  return true;
812            case 6: arch.SetTriple ("thumbv6-apple-ios");  return true;
813            case 7: arch.SetTriple ("thumbv5-apple-ios");  return true;
814            case 8: arch.SetTriple ("thumbv4t-apple-ios"); return true;
815            case 9: arch.SetTriple ("thumb-apple-ios");    return true;
816            default: break;
817        }
818        break;
819
820    case ArchSpec::eCore_arm_armv6:
821        switch (idx)
822        {
823            case 0: arch.SetTriple ("armv6-apple-ios");    return true;
824            case 1: arch.SetTriple ("armv5-apple-ios");    return true;
825            case 2: arch.SetTriple ("armv4-apple-ios");    return true;
826            case 3: arch.SetTriple ("arm-apple-ios");      return true;
827            case 4: arch.SetTriple ("thumbv6-apple-ios");  return true;
828            case 5: arch.SetTriple ("thumbv5-apple-ios");  return true;
829            case 6: arch.SetTriple ("thumbv4t-apple-ios"); return true;
830            case 7: arch.SetTriple ("thumb-apple-ios");    return true;
831            default: break;
832        }
833        break;
834
835    case ArchSpec::eCore_arm_armv5:
836        switch (idx)
837        {
838            case 0: arch.SetTriple ("armv5-apple-ios");    return true;
839            case 1: arch.SetTriple ("armv4-apple-ios");    return true;
840            case 2: arch.SetTriple ("arm-apple-ios");      return true;
841            case 3: arch.SetTriple ("thumbv5-apple-ios");  return true;
842            case 4: arch.SetTriple ("thumbv4t-apple-ios"); return true;
843            case 5: arch.SetTriple ("thumb-apple-ios");    return true;
844            default: break;
845        }
846        break;
847
848    case ArchSpec::eCore_arm_armv4:
849        switch (idx)
850        {
851            case 0: arch.SetTriple ("armv4-apple-ios");    return true;
852            case 1: arch.SetTriple ("arm-apple-ios");      return true;
853            case 2: arch.SetTriple ("thumbv4t-apple-ios"); return true;
854            case 3: arch.SetTriple ("thumb-apple-ios");    return true;
855            default: break;
856        }
857        break;
858    }
859    arch.Clear();
860    return false;
861}
862
863
864const char *
865PlatformDarwin::GetDeveloperDirectory()
866{
867    if (m_developer_directory.empty())
868    {
869        bool developer_dir_path_valid = false;
870        char developer_dir_path[PATH_MAX];
871        FileSpec temp_file_spec;
872        if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, temp_file_spec))
873        {
874            if (temp_file_spec.GetPath (developer_dir_path, sizeof(developer_dir_path)))
875            {
876                char *shared_frameworks = strstr (developer_dir_path, "/SharedFrameworks/LLDB.framework");
877                if (shared_frameworks)
878                {
879                    ::snprintf (shared_frameworks,
880                                sizeof(developer_dir_path) - (shared_frameworks - developer_dir_path),
881                                "/Developer");
882                    developer_dir_path_valid = true;
883                }
884                else
885                {
886                    char *lib_priv_frameworks = strstr (developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework");
887                    if (lib_priv_frameworks)
888                    {
889                        *lib_priv_frameworks = '\0';
890                        developer_dir_path_valid = true;
891                    }
892                }
893            }
894        }
895
896        if (!developer_dir_path_valid)
897        {
898            std::string xcode_dir_path;
899            const char *xcode_select_prefix_dir = getenv ("XCODE_SELECT_PREFIX_DIR");
900            if (xcode_select_prefix_dir)
901                xcode_dir_path.append (xcode_select_prefix_dir);
902            xcode_dir_path.append ("/usr/share/xcode-select/xcode_dir_path");
903            temp_file_spec.SetFile(xcode_dir_path.c_str(), false);
904            size_t bytes_read = temp_file_spec.ReadFileContents(0, developer_dir_path, sizeof(developer_dir_path), NULL);
905            if (bytes_read > 0)
906            {
907                developer_dir_path[bytes_read] = '\0';
908                while (developer_dir_path[bytes_read-1] == '\r' ||
909                       developer_dir_path[bytes_read-1] == '\n')
910                    developer_dir_path[--bytes_read] = '\0';
911                developer_dir_path_valid = true;
912            }
913        }
914
915        if (developer_dir_path_valid)
916        {
917            temp_file_spec.SetFile (developer_dir_path, false);
918            if (temp_file_spec.Exists())
919            {
920                m_developer_directory.assign (developer_dir_path);
921                return m_developer_directory.c_str();
922            }
923        }
924        // Assign a single NULL character so we know we tried to find the device
925        // support directory and we don't keep trying to find it over and over.
926        m_developer_directory.assign (1, '\0');
927    }
928
929    // We should have put a single NULL character into m_developer_directory
930    // or it should have a valid path if the code gets here
931    assert (m_developer_directory.empty() == false);
932    if (m_developer_directory[0])
933        return m_developer_directory.c_str();
934    return NULL;
935}
936
937
938BreakpointSP
939PlatformDarwin::SetThreadCreationBreakpoint (Target &target)
940{
941    BreakpointSP bp_sp;
942    static const char *g_bp_names[] =
943    {
944        "start_wqthread",
945        "_pthread_wqthread",
946        "_pthread_start",
947    };
948
949    static const char *g_bp_modules[] =
950    {
951        "libsystem_c.dylib",
952        "libSystem.B.dylib"
953    };
954
955    FileSpecList bp_modules;
956    for (int i = 0; i < sizeof(g_bp_modules)/sizeof(const char *); i++)
957    {
958        const char *bp_module = g_bp_modules[i];
959        bp_modules.Append(FileSpec(bp_module, false));
960    }
961
962    bool internal = true;
963    LazyBool skip_prologue = eLazyBoolNo;
964    bp_sp = target.CreateBreakpoint (&bp_modules,
965                                     NULL,
966                                     g_bp_names,
967                                     sizeof(g_bp_names)/sizeof(const char *),
968                                     eFunctionNameTypeFull,
969                                     skip_prologue,
970                                     internal);
971
972    return bp_sp;
973}
974
975size_t
976PlatformDarwin::GetEnvironment (StringList &env)
977{
978    if (IsRemote())
979    {
980        if (m_remote_platform_sp)
981            return m_remote_platform_sp->GetEnvironment(env);
982        return 0;
983    }
984    return Host::GetEnvironment(env);
985}
986