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