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