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/Log.h"
22 #include "lldb/Core/Module.h"
23 #include "lldb/Core/ModuleSpec.h"
24 #include "lldb/Core/Timer.h"
25 #include "lldb/Host/Host.h"
26 #include "lldb/Host/Symbols.h"
27 #include "lldb/Symbol/ObjectFile.h"
28 #include "lldb/Symbol/SymbolFile.h"
29 #include "lldb/Symbol/SymbolVendor.h"
30 #include "lldb/Target/Target.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 
36 //------------------------------------------------------------------
37 /// Default Constructor
38 //------------------------------------------------------------------
39 PlatformDarwin::PlatformDarwin (bool is_host) :
40     PlatformPOSIX(is_host),  // This is the local host platform
41     m_developer_directory (),
42     m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS)
43 {
44 }
45 
46 //------------------------------------------------------------------
47 /// Destructor.
48 ///
49 /// The destructor is virtual since this class is designed to be
50 /// inherited from by the plug-in instance.
51 //------------------------------------------------------------------
52 PlatformDarwin::~PlatformDarwin()
53 {
54 }
55 
56 FileSpecList
57 PlatformDarwin::LocateExecutableScriptingResources (Target *target,
58                                                     Module &module)
59 {
60     FileSpecList file_list;
61     if (target && target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython)
62     {
63         // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
64         // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
65         // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
66         // which should be stripped while leaving "this.binary.file" as-is.
67         FileSpec module_spec = module.GetFileSpec();
68 
69         if (module_spec)
70         {
71             SymbolVendor *symbols = module.GetSymbolVendor ();
72             if (symbols)
73             {
74                 SymbolFile *symfile = symbols->GetSymbolFile();
75                 if (symfile)
76                 {
77                     ObjectFile *objfile = symfile->GetObjectFile();
78                     if (objfile)
79                     {
80                         FileSpec symfile_spec (objfile->GetFileSpec());
81                         if (symfile_spec && symfile_spec.Exists())
82                         {
83                             while (module_spec.GetFilename())
84                             {
85                                 std::string module_basename (module_spec.GetFilename().GetCString());
86 
87                                 // FIXME: for Python, we cannot allow certain characters in module
88                                 // filenames we import. Theoretically, different scripting languages may
89                                 // have different sets of forbidden tokens in filenames, and that should
90                                 // be dealt with by each ScriptInterpreter. For now, we just replace dots
91                                 // with underscores, but if we ever support anything other than Python
92                                 // we will need to rework this
93                                 std::replace(module_basename.begin(), module_basename.end(), '.', '_');
94                                 std::replace(module_basename.begin(), module_basename.end(), ' ', '_');
95                                 std::replace(module_basename.begin(), module_basename.end(), '-', '_');
96 
97 
98                                 StreamString path_string;
99                                 // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
100                                 // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
101                                 path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), module_basename.c_str());
102                                 FileSpec script_fspec(path_string.GetData(), true);
103                                 if (script_fspec.Exists())
104                                 {
105                                     file_list.Append (script_fspec);
106                                     break;
107                                 }
108 
109                                 // If we didn't find the python file, then keep
110                                 // stripping the extensions and try again
111                                 ConstString filename_no_extension (module_spec.GetFileNameStrippingExtension());
112                                 if (module_spec.GetFilename() == filename_no_extension)
113                                     break;
114 
115                                 module_spec.GetFilename() = filename_no_extension;
116                             }
117                         }
118                     }
119                 }
120             }
121         }
122     }
123     return file_list;
124 }
125 
126 Error
127 PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
128                                    const ArchSpec &exe_arch,
129                                    lldb::ModuleSP &exe_module_sp,
130                                    const FileSpecList *module_search_paths_ptr)
131 {
132     Error error;
133     // Nothing special to do here, just use the actual file and architecture
134 
135     char exe_path[PATH_MAX];
136     FileSpec resolved_exe_file (exe_file);
137 
138     if (IsHost())
139     {
140         // If we have "ls" as the exe_file, resolve the executable loation based on
141         // the current path variables
142         if (!resolved_exe_file.Exists())
143         {
144             exe_file.GetPath (exe_path, sizeof(exe_path));
145             resolved_exe_file.SetFile(exe_path, true);
146         }
147 
148         if (!resolved_exe_file.Exists())
149             resolved_exe_file.ResolveExecutableLocation ();
150 
151         // Resolve any executable within a bundle on MacOSX
152         Host::ResolveExecutableInBundle (resolved_exe_file);
153 
154         if (resolved_exe_file.Exists())
155             error.Clear();
156         else
157         {
158             exe_file.GetPath (exe_path, sizeof(exe_path));
159             error.SetErrorStringWithFormat ("unable to find executable for '%s'", exe_path);
160         }
161     }
162     else
163     {
164         if (m_remote_platform_sp)
165         {
166             error = m_remote_platform_sp->ResolveExecutable (exe_file,
167                                                              exe_arch,
168                                                              exe_module_sp,
169                                                              module_search_paths_ptr);
170         }
171         else
172         {
173             // We may connect to a process and use the provided executable (Don't use local $PATH).
174 
175             // Resolve any executable within a bundle on MacOSX
176             Host::ResolveExecutableInBundle (resolved_exe_file);
177 
178             if (resolved_exe_file.Exists())
179                 error.Clear();
180             else
181                 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_exe_file.GetFilename().AsCString(""));
182         }
183     }
184 
185 
186     if (error.Success())
187     {
188         ModuleSpec module_spec (resolved_exe_file, exe_arch);
189         if (module_spec.GetArchitecture().IsValid())
190         {
191             error = ModuleList::GetSharedModule (module_spec,
192                                                  exe_module_sp,
193                                                  module_search_paths_ptr,
194                                                  NULL,
195                                                  NULL);
196 
197             if (error.Fail() || exe_module_sp.get() == NULL || exe_module_sp->GetObjectFile() == NULL)
198             {
199                 exe_module_sp.reset();
200                 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
201                                                 exe_file.GetPath().c_str(),
202                                                 exe_arch.GetArchitectureName());
203             }
204         }
205         else
206         {
207             // No valid architecture was specified, ask the platform for
208             // the architectures that we should be using (in the correct order)
209             // and see if we can find a match that way
210             StreamString arch_names;
211             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
212             {
213                 error = GetSharedModule (module_spec,
214                                          exe_module_sp,
215                                          module_search_paths_ptr,
216                                          NULL,
217                                          NULL);
218                 // Did we find an executable using one of the
219                 if (error.Success())
220                 {
221                     if (exe_module_sp && exe_module_sp->GetObjectFile())
222                         break;
223                     else
224                         error.SetErrorToGenericError();
225                 }
226 
227                 if (idx > 0)
228                     arch_names.PutCString (", ");
229                 arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName());
230             }
231 
232             if (error.Fail() || !exe_module_sp)
233             {
234                 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
235                                                 exe_file.GetPath().c_str(),
236                                                 GetPluginName().GetCString(),
237                                                 arch_names.GetString().c_str());
238             }
239         }
240     }
241 
242     return error;
243 }
244 
245 Error
246 PlatformDarwin::ResolveSymbolFile (Target &target,
247                                    const ModuleSpec &sym_spec,
248                                    FileSpec &sym_file)
249 {
250     Error error;
251     sym_file = sym_spec.GetSymbolFileSpec();
252     if (sym_file.Exists())
253     {
254         if (sym_file.GetFileType() == FileSpec::eFileTypeDirectory)
255         {
256             sym_file = Symbols::FindSymbolFileInBundle (sym_file,
257                                                         sym_spec.GetUUIDPtr(),
258                                                         sym_spec.GetArchitecturePtr());
259         }
260     }
261     else
262     {
263         if (sym_spec.GetUUID().IsValid())
264         {
265 
266         }
267     }
268     return error;
269 
270 }
271 
272 static lldb_private::Error
273 MakeCacheFolderForFile (const FileSpec& module_cache_spec)
274 {
275     FileSpec module_cache_folder = module_cache_spec.CopyByRemovingLastPathComponent();
276     StreamString mkdir_folder_cmd;
277     mkdir_folder_cmd.Printf("mkdir -p %s/%s", module_cache_folder.GetDirectory().AsCString(), module_cache_folder.GetFilename().AsCString());
278     return Host::RunShellCommand(mkdir_folder_cmd.GetData(),
279                           NULL,
280                           NULL,
281                           NULL,
282                           NULL,
283                           60);
284 }
285 
286 static lldb_private::Error
287 BringInRemoteFile (Platform* platform,
288                    const lldb_private::ModuleSpec &module_spec,
289                    const FileSpec& module_cache_spec)
290 {
291     MakeCacheFolderForFile(module_cache_spec);
292     Error err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec);
293     return err;
294 }
295 
296 lldb_private::Error
297 PlatformDarwin::GetSharedModuleWithLocalCache (const lldb_private::ModuleSpec &module_spec,
298                                                lldb::ModuleSP &module_sp,
299                                                const lldb_private::FileSpecList *module_search_paths_ptr,
300                                                lldb::ModuleSP *old_module_sp_ptr,
301                                                bool *did_create_ptr)
302 {
303 
304     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
305     if (log)
306         log->Printf("[%s] Trying to find module %s/%s - platform path %s/%s symbol path %s/%s\n",
307                      (IsHost() ? "host" : "remote"),
308                      module_spec.GetFileSpec().GetDirectory().AsCString(),
309                      module_spec.GetFileSpec().GetFilename().AsCString(),
310                      module_spec.GetPlatformFileSpec().GetDirectory().AsCString(),
311                      module_spec.GetPlatformFileSpec().GetFilename().AsCString(),
312                      module_spec.GetSymbolFileSpec().GetDirectory().AsCString(),
313                      module_spec.GetSymbolFileSpec().GetFilename().AsCString());
314 
315     std::string cache_path(GetLocalCacheDirectory());
316     std::string module_path (module_spec.GetFileSpec().GetPath());
317     cache_path.append(module_path);
318     FileSpec module_cache_spec(cache_path.c_str(),false);
319 
320     // if rsync is supported, always bring in the file - rsync will be very efficient
321     // when files are the same on the local and remote end of the connection
322     if (this->GetSupportsRSync())
323     {
324         Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
325         if (err.Fail())
326             return err;
327         if (module_cache_spec.Exists())
328         {
329             Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
330             if (log)
331                 log->Printf("[%s] module %s/%s was rsynced and is now there\n",
332                              (IsHost() ? "host" : "remote"),
333                              module_spec.GetFileSpec().GetDirectory().AsCString(),
334                              module_spec.GetFileSpec().GetFilename().AsCString());
335             ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
336             module_sp.reset(new Module(local_spec));
337             module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
338             return Error();
339         }
340     }
341 
342     if (module_spec.GetFileSpec().Exists() && !module_sp)
343     {
344         module_sp.reset(new Module(module_spec));
345         return Error();
346     }
347 
348     // try to find the module in the cache
349     if (module_cache_spec.Exists())
350     {
351         // get the local and remote MD5 and compare
352         if (m_remote_platform_sp)
353         {
354             // when going over the *slow* GDB remote transfer mechanism we first check
355             // the hashes of the files - and only do the actual transfer if they differ
356             uint64_t high_local,high_remote,low_local,low_remote;
357             Host::CalculateMD5 (module_cache_spec, low_local, high_local);
358             m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), low_remote, high_remote);
359             if (low_local != low_remote || high_local != high_remote)
360             {
361                 // bring in the remote file
362                 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
363                 if (log)
364                     log->Printf("[%s] module %s/%s needs to be replaced from remote copy\n",
365                                  (IsHost() ? "host" : "remote"),
366                                  module_spec.GetFileSpec().GetDirectory().AsCString(),
367                                  module_spec.GetFileSpec().GetFilename().AsCString());
368                 Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
369                 if (err.Fail())
370                     return err;
371             }
372         }
373 
374         ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
375         module_sp.reset(new Module(local_spec));
376         module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
377         Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
378             if (log)
379                 log->Printf("[%s] module %s/%s was found in the cache\n",
380                              (IsHost() ? "host" : "remote"),
381                              module_spec.GetFileSpec().GetDirectory().AsCString(),
382                              module_spec.GetFileSpec().GetFilename().AsCString());
383         return Error();
384     }
385 
386     // bring in the remote module file
387     if (log)
388         log->Printf("[%s] module %s/%s needs to come in remotely\n",
389                      (IsHost() ? "host" : "remote"),
390                      module_spec.GetFileSpec().GetDirectory().AsCString(),
391                      module_spec.GetFileSpec().GetFilename().AsCString());
392     Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
393     if (err.Fail())
394         return err;
395     if (module_cache_spec.Exists())
396     {
397         Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
398         if (log)
399             log->Printf("[%s] module %s/%s is now cached and fine\n",
400                          (IsHost() ? "host" : "remote"),
401                          module_spec.GetFileSpec().GetDirectory().AsCString(),
402                          module_spec.GetFileSpec().GetFilename().AsCString());
403         ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
404         module_sp.reset(new Module(local_spec));
405         module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
406         return Error();
407     }
408     else
409         return Error("unable to obtain valid module file");
410 }
411 
412 Error
413 PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec,
414                                  ModuleSP &module_sp,
415                                  const FileSpecList *module_search_paths_ptr,
416                                  ModuleSP *old_module_sp_ptr,
417                                  bool *did_create_ptr)
418 {
419     Error error;
420     module_sp.reset();
421 
422     if (IsRemote())
423     {
424         // If we have a remote platform always, let it try and locate
425         // the shared module first.
426         if (m_remote_platform_sp)
427         {
428             error = m_remote_platform_sp->GetSharedModule (module_spec,
429                                                            module_sp,
430                                                            module_search_paths_ptr,
431                                                            old_module_sp_ptr,
432                                                            did_create_ptr);
433         }
434     }
435 
436     if (!module_sp)
437     {
438         // Fall back to the local platform and find the file locally
439         error = Platform::GetSharedModule (module_spec,
440                                            module_sp,
441                                            module_search_paths_ptr,
442                                            old_module_sp_ptr,
443                                            did_create_ptr);
444 
445         const FileSpec &platform_file = module_spec.GetFileSpec();
446         if (!module_sp && module_search_paths_ptr && platform_file)
447         {
448             // We can try to pull off part of the file path up to the bundle
449             // directory level and try any module search paths...
450             FileSpec bundle_directory;
451             if (Host::GetBundleDirectory (platform_file, bundle_directory))
452             {
453                 if (platform_file == bundle_directory)
454                 {
455                     ModuleSpec new_module_spec (module_spec);
456                     new_module_spec.GetFileSpec() = bundle_directory;
457                     if (Host::ResolveExecutableInBundle (new_module_spec.GetFileSpec()))
458                     {
459                         Error new_error (Platform::GetSharedModule (new_module_spec,
460                                                                     module_sp,
461                                                                     NULL,
462                                                                     old_module_sp_ptr,
463                                                                     did_create_ptr));
464 
465                         if (module_sp)
466                             return new_error;
467                     }
468                 }
469                 else
470                 {
471                     char platform_path[PATH_MAX];
472                     char bundle_dir[PATH_MAX];
473                     platform_file.GetPath (platform_path, sizeof(platform_path));
474                     const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
475                     char new_path[PATH_MAX];
476                     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
477                     for (size_t i=0; i<num_module_search_paths; ++i)
478                     {
479                         const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
480                         if (search_path_len < sizeof(new_path))
481                         {
482                             snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
483                             FileSpec new_file_spec (new_path, false);
484                             if (new_file_spec.Exists())
485                             {
486                                 ModuleSpec new_module_spec (module_spec);
487                                 new_module_spec.GetFileSpec() = new_file_spec;
488                                 Error new_error (Platform::GetSharedModule (new_module_spec,
489                                                                             module_sp,
490                                                                             NULL,
491                                                                             old_module_sp_ptr,
492                                                                             did_create_ptr));
493 
494                                 if (module_sp)
495                                 {
496                                     module_sp->SetPlatformFileSpec(new_file_spec);
497                                     return new_error;
498                                 }
499                             }
500                         }
501                     }
502                 }
503             }
504         }
505     }
506     if (module_sp)
507         module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
508     return error;
509 }
510 
511 size_t
512 PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
513 {
514     const uint8_t *trap_opcode = NULL;
515     uint32_t trap_opcode_size = 0;
516     bool bp_is_thumb = false;
517 
518     llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
519     switch (machine)
520     {
521     case llvm::Triple::x86:
522     case llvm::Triple::x86_64:
523         {
524             static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
525             trap_opcode = g_i386_breakpoint_opcode;
526             trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
527         }
528         break;
529 
530     case llvm::Triple::thumb:
531         bp_is_thumb = true; // Fall through...
532     case llvm::Triple::arm:
533         {
534             static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
535             static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
536 
537             // Auto detect arm/thumb if it wasn't explicitly specified
538             if (!bp_is_thumb)
539             {
540                 lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
541                 if (bp_loc_sp)
542                     bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA;
543             }
544             if (bp_is_thumb)
545             {
546                 trap_opcode = g_thumb_breakpooint_opcode;
547                 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
548                 break;
549             }
550             trap_opcode = g_arm_breakpoint_opcode;
551             trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
552         }
553         break;
554 
555     case llvm::Triple::ppc:
556     case llvm::Triple::ppc64:
557         {
558             static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
559             trap_opcode = g_ppc_breakpoint_opcode;
560             trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
561         }
562         break;
563 
564     default:
565         assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()");
566         break;
567     }
568 
569     if (trap_opcode && trap_opcode_size)
570     {
571         if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
572             return trap_opcode_size;
573     }
574     return 0;
575 
576 }
577 
578 bool
579 PlatformDarwin::GetRemoteOSVersion ()
580 {
581     if (m_remote_platform_sp)
582         return m_remote_platform_sp->GetOSVersion (m_major_os_version,
583                                                    m_minor_os_version,
584                                                    m_update_os_version);
585     return false;
586 }
587 
588 bool
589 PlatformDarwin::GetRemoteOSBuildString (std::string &s)
590 {
591     if (m_remote_platform_sp)
592         return m_remote_platform_sp->GetRemoteOSBuildString (s);
593     s.clear();
594     return false;
595 }
596 
597 bool
598 PlatformDarwin::GetRemoteOSKernelDescription (std::string &s)
599 {
600     if (m_remote_platform_sp)
601         return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
602     s.clear();
603     return false;
604 }
605 
606 // Remote Platform subclasses need to override this function
607 ArchSpec
608 PlatformDarwin::GetRemoteSystemArchitecture ()
609 {
610     if (m_remote_platform_sp)
611         return m_remote_platform_sp->GetRemoteSystemArchitecture ();
612     return ArchSpec();
613 }
614 
615 
616 const char *
617 PlatformDarwin::GetHostname ()
618 {
619     if (IsHost())
620         return Platform::GetHostname();
621 
622     if (m_remote_platform_sp)
623         return m_remote_platform_sp->GetHostname ();
624     return NULL;
625 }
626 
627 bool
628 PlatformDarwin::IsConnected () const
629 {
630     if (IsHost())
631         return true;
632     else if (m_remote_platform_sp)
633         return m_remote_platform_sp->IsConnected();
634     return false;
635 }
636 
637 Error
638 PlatformDarwin::ConnectRemote (Args& args)
639 {
640     Error error;
641     if (IsHost())
642     {
643         error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
644     }
645     else
646     {
647         if (!m_remote_platform_sp)
648             m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
649 
650         if (m_remote_platform_sp && error.Success())
651             error = m_remote_platform_sp->ConnectRemote (args);
652         else
653             error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
654 
655         if (error.Fail())
656             m_remote_platform_sp.reset();
657     }
658 
659     if (error.Success() && m_remote_platform_sp)
660     {
661         if (m_options.get())
662         {
663             OptionGroupOptions* options = m_options.get();
664             OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
665             OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
666             OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
667 
668             if (m_rsync_options->m_rsync)
669             {
670                 SetSupportsRSync(true);
671                 SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str());
672                 SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str());
673                 SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname);
674             }
675             if (m_ssh_options->m_ssh)
676             {
677                 SetSupportsSSH(true);
678                 SetSSHOpts(m_ssh_options->m_ssh_opts.c_str());
679             }
680             SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str());
681         }
682     }
683 
684     return error;
685 }
686 
687 Error
688 PlatformDarwin::DisconnectRemote ()
689 {
690     Error error;
691 
692     if (IsHost())
693     {
694         error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
695     }
696     else
697     {
698         if (m_remote_platform_sp)
699             error = m_remote_platform_sp->DisconnectRemote ();
700         else
701             error.SetErrorString ("the platform is not currently connected");
702     }
703     return error;
704 }
705 
706 
707 bool
708 PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
709 {
710     bool sucess = false;
711     if (IsHost())
712     {
713         sucess = Platform::GetProcessInfo (pid, process_info);
714     }
715     else
716     {
717         if (m_remote_platform_sp)
718             sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
719     }
720     return sucess;
721 }
722 
723 
724 
725 uint32_t
726 PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
727                                ProcessInstanceInfoList &process_infos)
728 {
729     uint32_t match_count = 0;
730     if (IsHost())
731     {
732         // Let the base class figure out the host details
733         match_count = Platform::FindProcesses (match_info, process_infos);
734     }
735     else
736     {
737         // If we are remote, we can only return results if we are connected
738         if (m_remote_platform_sp)
739             match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
740     }
741     return match_count;
742 }
743 
744 Error
745 PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
746 {
747     Error error;
748 
749     if (IsHost())
750     {
751         error = Platform::LaunchProcess (launch_info);
752     }
753     else
754     {
755         if (m_remote_platform_sp)
756             error = m_remote_platform_sp->LaunchProcess (launch_info);
757         else
758             error.SetErrorString ("the platform is not currently connected");
759     }
760     return error;
761 }
762 
763 lldb::ProcessSP
764 PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
765                         Debugger &debugger,
766                         Target *target,
767                         Listener &listener,
768                         Error &error)
769 {
770     lldb::ProcessSP process_sp;
771 
772     if (IsHost())
773     {
774         if (target == NULL)
775         {
776             TargetSP new_target_sp;
777 
778             error = debugger.GetTargetList().CreateTarget (debugger,
779                                                            NULL,
780                                                            NULL,
781                                                            false,
782                                                            NULL,
783                                                            new_target_sp);
784             target = new_target_sp.get();
785         }
786         else
787             error.Clear();
788 
789         if (target && error.Success())
790         {
791             debugger.GetTargetList().SetSelectedTarget(target);
792 
793             process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL);
794 
795             if (process_sp)
796                 error = process_sp->Attach (attach_info);
797         }
798     }
799     else
800     {
801         if (m_remote_platform_sp)
802             process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
803         else
804             error.SetErrorString ("the platform is not currently connected");
805     }
806     return process_sp;
807 }
808 
809 const char *
810 PlatformDarwin::GetUserName (uint32_t uid)
811 {
812     // Check the cache in Platform in case we have already looked this uid up
813     const char *user_name = Platform::GetUserName(uid);
814     if (user_name)
815         return user_name;
816 
817     if (IsRemote() && m_remote_platform_sp)
818         return m_remote_platform_sp->GetUserName(uid);
819     return NULL;
820 }
821 
822 const char *
823 PlatformDarwin::GetGroupName (uint32_t gid)
824 {
825     const char *group_name = Platform::GetGroupName(gid);
826     if (group_name)
827         return group_name;
828 
829     if (IsRemote() && m_remote_platform_sp)
830         return m_remote_platform_sp->GetGroupName(gid);
831     return NULL;
832 }
833 
834 bool
835 PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
836 {
837     if (!module_sp)
838         return false;
839 
840     ObjectFile *obj_file = module_sp->GetObjectFile();
841     if (!obj_file)
842         return false;
843 
844     ObjectFile::Type obj_type = obj_file->GetType();
845     if (obj_type == ObjectFile::eTypeDynamicLinker)
846         return true;
847     else
848         return false;
849 }
850 
851 std::string
852 PlatformDarwin::GetQueueNameForThreadQAddress (Process *process, addr_t thread_dispatch_qaddr)
853 {
854     std::string dispatch_queue_name;
855     if (thread_dispatch_qaddr == LLDB_INVALID_ADDRESS || thread_dispatch_qaddr == 0 || process == NULL)
856         return "";
857 
858     Target &target = process->GetTarget();
859 
860     // Cache the dispatch_queue_offsets_addr value so we don't always have
861     // to look it up
862     if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
863     {
864         static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
865         const Symbol *dispatch_queue_offsets_symbol = NULL;
866 
867         // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 ("Snow Leopard")
868         ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false));
869         ModuleSP module_sp(target.GetImages().FindFirstModule (libSystem_module_spec));
870         if (module_sp)
871             dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
872 
873         // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") and later
874         if (dispatch_queue_offsets_symbol == NULL)
875         {
876             ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false));
877             module_sp = target.GetImages().FindFirstModule (libdispatch_module_spec);
878             if (module_sp)
879                 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
880         }
881         if (dispatch_queue_offsets_symbol)
882             m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&target);
883 
884         if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
885             return "";
886     }
887 
888     uint8_t memory_buffer[8];
889     DataExtractor data (memory_buffer,
890                         sizeof(memory_buffer),
891                         target.GetArchitecture().GetByteOrder(),
892                         target.GetArchitecture().GetAddressByteSize());
893 
894     // Excerpt from src/queue_private.h
895     // version 4 of this struct first appears in Mac OS X 10.9 ("Mavericks") and iOS 7.
896     // TODO When version 1-3 no longer needs to be supported, the dqo_label offset should be
897     // read from the inferior one time and saved in an ivar like m_dispatch_queue_offsets_addr.
898     struct dispatch_queue_offsets_s
899     {
900         uint16_t dqo_version;
901         uint16_t dqo_label;      // in version 1-3, offset to string; in version 4+, offset to a pointer to a string
902         uint16_t dqo_label_size; // in version 1-3, length of string; in version 4+, size of a (void*) in this process
903     } dispatch_queue_offsets;
904 
905     Error error;
906     if (process->ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
907     {
908         lldb::offset_t data_offset = 0;
909         if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
910         {
911             if (process->ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
912             {
913                 data_offset = 0;
914                 lldb::addr_t queue_addr = data.GetAddress(&data_offset);
915                 if (dispatch_queue_offsets.dqo_version >= 4)
916                 {
917                     // libdispatch versions 4+, pointer to dispatch name is in the
918                     // queue structure.
919                     lldb::addr_t pointer_to_label_address = queue_addr + dispatch_queue_offsets.dqo_label;
920                     if (process->ReadMemory (pointer_to_label_address, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
921                     {
922                         data_offset = 0;
923                         lldb::addr_t label_addr = data.GetAddress(&data_offset);
924                         process->ReadCStringFromMemory (label_addr, dispatch_queue_name, error);
925                     }
926                 }
927                 else
928                 {
929                     // libdispatch versions 1-3, dispatch name is a fixed width char array
930                     // in the queue structure.
931                     lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
932                     dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
933                     size_t bytes_read = process->ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
934                     if (bytes_read < dispatch_queue_offsets.dqo_label_size)
935                         dispatch_queue_name.erase (bytes_read);
936                 }
937             }
938         }
939     }
940     return dispatch_queue_name;
941 }
942 
943 lldb::queue_id_t
944 PlatformDarwin::GetQueueIDForThreadQAddress (Process *process, lldb::addr_t dispatch_qaddr)
945 {
946     if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0 || process == NULL)
947         return LLDB_INVALID_QUEUE_ID;
948 
949     Error error;
950     uint32_t ptr_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
951     uint64_t this_thread_queue_id = process->ReadUnsignedIntegerFromMemory (dispatch_qaddr, ptr_size, LLDB_INVALID_QUEUE_ID, error);
952     if (!error.Success())
953         return LLDB_INVALID_QUEUE_ID;
954 
955     return this_thread_queue_id;
956 }
957 
958 
959 bool
960 PlatformDarwin::x86GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
961 {
962     if (idx == 0)
963     {
964         arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
965         return arch.IsValid();
966     }
967     else if (idx == 1)
968     {
969         ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
970         ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
971         if (platform_arch.IsExactMatch(platform_arch64))
972         {
973             // This macosx platform supports both 32 and 64 bit. Since we already
974             // returned the 64 bit arch for idx == 0, return the 32 bit arch
975             // for idx == 1
976             arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
977             return arch.IsValid();
978         }
979     }
980     return false;
981 }
982 
983 // The architecture selection rules for arm processors
984 // These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f processor.
985 
986 bool
987 PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
988 {
989     ArchSpec system_arch (GetSystemArchitecture());
990     const ArchSpec::Core system_core = system_arch.GetCore();
991     switch (system_core)
992     {
993     default:
994         switch (idx)
995         {
996             case  0: arch.SetTriple ("armv7-apple-ios");    return true;
997             case  1: arch.SetTriple ("armv7f-apple-ios");   return true;
998             case  2: arch.SetTriple ("armv7k-apple-ios");   return true;
999             case  3: arch.SetTriple ("armv7s-apple-ios");   return true;
1000             case  4: arch.SetTriple ("armv7m-apple-ios");   return true;
1001             case  5: arch.SetTriple ("armv7em-apple-ios");  return true;
1002             case  6: arch.SetTriple ("armv6-apple-ios");    return true;
1003             case  7: arch.SetTriple ("armv6m-apple-ios");   return true;
1004             case  8: arch.SetTriple ("armv5-apple-ios");    return true;
1005             case  9: arch.SetTriple ("armv4-apple-ios");    return true;
1006             case 10: arch.SetTriple ("arm-apple-ios");      return true;
1007             case 11: arch.SetTriple ("thumbv7-apple-ios");  return true;
1008             case 12: arch.SetTriple ("thumbv7f-apple-ios"); return true;
1009             case 13: arch.SetTriple ("thumbv7k-apple-ios"); return true;
1010             case 14: arch.SetTriple ("thumbv7s-apple-ios"); return true;
1011             case 15: arch.SetTriple ("thumbv7m-apple-ios"); return true;
1012             case 16: arch.SetTriple ("thumbv7em-apple-ios"); return true;
1013             case 17: arch.SetTriple ("thumbv6-apple-ios");  return true;
1014             case 18: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1015             case 19: arch.SetTriple ("thumbv5-apple-ios");  return true;
1016             case 20: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1017             case 21: arch.SetTriple ("thumb-apple-ios");    return true;
1018         default: break;
1019         }
1020         break;
1021 
1022     case ArchSpec::eCore_arm_armv7f:
1023         switch (idx)
1024         {
1025             case  0: arch.SetTriple ("armv7f-apple-ios");   return true;
1026             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
1027             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
1028             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
1029             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
1030             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
1031             case  6: arch.SetTriple ("arm-apple-ios");      return true;
1032             case  7: arch.SetTriple ("thumbv7f-apple-ios"); return true;
1033             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
1034             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1035             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
1036             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
1037             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1038             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
1039             default: break;
1040         }
1041         break;
1042 
1043     case ArchSpec::eCore_arm_armv7k:
1044         switch (idx)
1045         {
1046             case  0: arch.SetTriple ("armv7k-apple-ios");   return true;
1047             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
1048             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
1049             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
1050             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
1051             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
1052             case  6: arch.SetTriple ("arm-apple-ios");      return true;
1053             case  7: arch.SetTriple ("thumbv7k-apple-ios"); return true;
1054             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
1055             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1056             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
1057             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
1058             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1059             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
1060             default: break;
1061         }
1062         break;
1063 
1064     case ArchSpec::eCore_arm_armv7s:
1065         switch (idx)
1066         {
1067             case  0: arch.SetTriple ("armv7s-apple-ios");   return true;
1068             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
1069             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
1070             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
1071             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
1072             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
1073             case  6: arch.SetTriple ("arm-apple-ios");      return true;
1074             case  7: arch.SetTriple ("thumbv7s-apple-ios"); return true;
1075             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
1076             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1077             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
1078             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
1079             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1080             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
1081             default: break;
1082         }
1083         break;
1084 
1085     case ArchSpec::eCore_arm_armv7m:
1086         switch (idx)
1087         {
1088             case  0: arch.SetTriple ("armv7m-apple-ios");   return true;
1089             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
1090             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
1091             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
1092             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
1093             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
1094             case  6: arch.SetTriple ("arm-apple-ios");      return true;
1095             case  7: arch.SetTriple ("thumbv7m-apple-ios"); return true;
1096             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
1097             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1098             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
1099             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
1100             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1101             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
1102             default: break;
1103         }
1104         break;
1105 
1106     case ArchSpec::eCore_arm_armv7em:
1107         switch (idx)
1108         {
1109             case  0: arch.SetTriple ("armv7em-apple-ios");  return true;
1110             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
1111             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
1112             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
1113             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
1114             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
1115             case  6: arch.SetTriple ("arm-apple-ios");      return true;
1116             case  7: arch.SetTriple ("thumbv7em-apple-ios"); return true;
1117             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
1118             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1119             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
1120             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
1121             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1122             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
1123             default: break;
1124         }
1125         break;
1126 
1127     case ArchSpec::eCore_arm_armv7:
1128         switch (idx)
1129         {
1130             case  0: arch.SetTriple ("armv7-apple-ios");    return true;
1131             case  1: arch.SetTriple ("armv6m-apple-ios");   return true;
1132             case  2: arch.SetTriple ("armv6-apple-ios");    return true;
1133             case  3: arch.SetTriple ("armv5-apple-ios");    return true;
1134             case  4: arch.SetTriple ("armv4-apple-ios");    return true;
1135             case  5: arch.SetTriple ("arm-apple-ios");      return true;
1136             case  6: arch.SetTriple ("thumbv7-apple-ios");  return true;
1137             case  7: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1138             case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
1139             case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
1140             case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1141             case 11: arch.SetTriple ("thumb-apple-ios");    return true;
1142             default: break;
1143         }
1144         break;
1145 
1146     case ArchSpec::eCore_arm_armv6m:
1147         switch (idx)
1148         {
1149             case 0: arch.SetTriple ("armv6m-apple-ios");   return true;
1150             case 1: arch.SetTriple ("armv6-apple-ios");    return true;
1151             case 2: arch.SetTriple ("armv5-apple-ios");    return true;
1152             case 3: arch.SetTriple ("armv4-apple-ios");    return true;
1153             case 4: arch.SetTriple ("arm-apple-ios");      return true;
1154             case 5: arch.SetTriple ("thumbv6m-apple-ios"); return true;
1155             case 6: arch.SetTriple ("thumbv6-apple-ios");  return true;
1156             case 7: arch.SetTriple ("thumbv5-apple-ios");  return true;
1157             case 8: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1158             case 9: arch.SetTriple ("thumb-apple-ios");    return true;
1159             default: break;
1160         }
1161         break;
1162 
1163     case ArchSpec::eCore_arm_armv6:
1164         switch (idx)
1165         {
1166             case 0: arch.SetTriple ("armv6-apple-ios");    return true;
1167             case 1: arch.SetTriple ("armv5-apple-ios");    return true;
1168             case 2: arch.SetTriple ("armv4-apple-ios");    return true;
1169             case 3: arch.SetTriple ("arm-apple-ios");      return true;
1170             case 4: arch.SetTriple ("thumbv6-apple-ios");  return true;
1171             case 5: arch.SetTriple ("thumbv5-apple-ios");  return true;
1172             case 6: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1173             case 7: arch.SetTriple ("thumb-apple-ios");    return true;
1174             default: break;
1175         }
1176         break;
1177 
1178     case ArchSpec::eCore_arm_armv5:
1179         switch (idx)
1180         {
1181             case 0: arch.SetTriple ("armv5-apple-ios");    return true;
1182             case 1: arch.SetTriple ("armv4-apple-ios");    return true;
1183             case 2: arch.SetTriple ("arm-apple-ios");      return true;
1184             case 3: arch.SetTriple ("thumbv5-apple-ios");  return true;
1185             case 4: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1186             case 5: arch.SetTriple ("thumb-apple-ios");    return true;
1187             default: break;
1188         }
1189         break;
1190 
1191     case ArchSpec::eCore_arm_armv4:
1192         switch (idx)
1193         {
1194             case 0: arch.SetTriple ("armv4-apple-ios");    return true;
1195             case 1: arch.SetTriple ("arm-apple-ios");      return true;
1196             case 2: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1197             case 3: arch.SetTriple ("thumb-apple-ios");    return true;
1198             default: break;
1199         }
1200         break;
1201     }
1202     arch.Clear();
1203     return false;
1204 }
1205 
1206 
1207 const char *
1208 PlatformDarwin::GetDeveloperDirectory()
1209 {
1210     if (m_developer_directory.empty())
1211     {
1212         bool developer_dir_path_valid = false;
1213         char developer_dir_path[PATH_MAX];
1214         FileSpec temp_file_spec;
1215         if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, temp_file_spec))
1216         {
1217             if (temp_file_spec.GetPath (developer_dir_path, sizeof(developer_dir_path)))
1218             {
1219                 char *shared_frameworks = strstr (developer_dir_path, "/SharedFrameworks/LLDB.framework");
1220                 if (shared_frameworks)
1221                 {
1222                     ::snprintf (shared_frameworks,
1223                                 sizeof(developer_dir_path) - (shared_frameworks - developer_dir_path),
1224                                 "/Developer");
1225                     developer_dir_path_valid = true;
1226                 }
1227                 else
1228                 {
1229                     char *lib_priv_frameworks = strstr (developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework");
1230                     if (lib_priv_frameworks)
1231                     {
1232                         *lib_priv_frameworks = '\0';
1233                         developer_dir_path_valid = true;
1234                     }
1235                 }
1236             }
1237         }
1238 
1239         if (!developer_dir_path_valid)
1240         {
1241             std::string xcode_dir_path;
1242             const char *xcode_select_prefix_dir = getenv ("XCODE_SELECT_PREFIX_DIR");
1243             if (xcode_select_prefix_dir)
1244                 xcode_dir_path.append (xcode_select_prefix_dir);
1245             xcode_dir_path.append ("/usr/share/xcode-select/xcode_dir_path");
1246             temp_file_spec.SetFile(xcode_dir_path.c_str(), false);
1247             size_t bytes_read = temp_file_spec.ReadFileContents(0, developer_dir_path, sizeof(developer_dir_path), NULL);
1248             if (bytes_read > 0)
1249             {
1250                 developer_dir_path[bytes_read] = '\0';
1251                 while (developer_dir_path[bytes_read-1] == '\r' ||
1252                        developer_dir_path[bytes_read-1] == '\n')
1253                     developer_dir_path[--bytes_read] = '\0';
1254                 developer_dir_path_valid = true;
1255             }
1256         }
1257 
1258         if (!developer_dir_path_valid)
1259         {
1260             FileSpec xcode_select_cmd ("/usr/bin/xcode-select", false);
1261             if (xcode_select_cmd.Exists())
1262             {
1263                 int exit_status = -1;
1264                 int signo = -1;
1265                 std::string command_output;
1266                 Error error = Host::RunShellCommand ("/usr/bin/xcode-select --print-path",
1267                                                      NULL,                                 // current working directory
1268                                                      &exit_status,
1269                                                      &signo,
1270                                                      &command_output,
1271                                                      2,                                     // short timeout
1272                                                      NULL);                                 // don't run in a shell
1273                 if (error.Success() && exit_status == 0 && !command_output.empty())
1274                 {
1275                     const char *cmd_output_ptr = command_output.c_str();
1276                     developer_dir_path[sizeof (developer_dir_path) - 1] = '\0';
1277                     size_t i;
1278                     for (i = 0; i < sizeof (developer_dir_path) - 1; i++)
1279                     {
1280                         if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' || cmd_output_ptr[i] == '\0')
1281                             break;
1282                         developer_dir_path[i] = cmd_output_ptr[i];
1283                     }
1284                     developer_dir_path[i] = '\0';
1285 
1286                     FileSpec devel_dir (developer_dir_path, false);
1287                     if (devel_dir.Exists() && devel_dir.IsDirectory())
1288                     {
1289                         developer_dir_path_valid = true;
1290                     }
1291                 }
1292             }
1293         }
1294 
1295         if (developer_dir_path_valid)
1296         {
1297             temp_file_spec.SetFile (developer_dir_path, false);
1298             if (temp_file_spec.Exists())
1299             {
1300                 m_developer_directory.assign (developer_dir_path);
1301                 return m_developer_directory.c_str();
1302             }
1303         }
1304         // Assign a single NULL character so we know we tried to find the device
1305         // support directory and we don't keep trying to find it over and over.
1306         m_developer_directory.assign (1, '\0');
1307     }
1308 
1309     // We should have put a single NULL character into m_developer_directory
1310     // or it should have a valid path if the code gets here
1311     assert (m_developer_directory.empty() == false);
1312     if (m_developer_directory[0])
1313         return m_developer_directory.c_str();
1314     return NULL;
1315 }
1316 
1317 
1318 BreakpointSP
1319 PlatformDarwin::SetThreadCreationBreakpoint (Target &target)
1320 {
1321     BreakpointSP bp_sp;
1322     static const char *g_bp_names[] =
1323     {
1324         "start_wqthread",
1325         "_pthread_wqthread",
1326         "_pthread_start",
1327     };
1328 
1329     static const char *g_bp_modules[] =
1330     {
1331         "libsystem_c.dylib",
1332         "libSystem.B.dylib"
1333     };
1334 
1335     FileSpecList bp_modules;
1336     for (size_t i = 0; i < sizeof(g_bp_modules)/sizeof(const char *); i++)
1337     {
1338         const char *bp_module = g_bp_modules[i];
1339         bp_modules.Append(FileSpec(bp_module, false));
1340     }
1341 
1342     bool internal = true;
1343     bool hardware = false;
1344     LazyBool skip_prologue = eLazyBoolNo;
1345     bp_sp = target.CreateBreakpoint (&bp_modules,
1346                                      NULL,
1347                                      g_bp_names,
1348                                      sizeof(g_bp_names)/sizeof(const char *),
1349                                      eFunctionNameTypeFull,
1350                                      skip_prologue,
1351                                      internal,
1352                                      hardware);
1353     bp_sp->SetBreakpointKind("thread-creation");
1354 
1355     return bp_sp;
1356 }
1357 
1358 size_t
1359 PlatformDarwin::GetEnvironment (StringList &env)
1360 {
1361     if (IsRemote())
1362     {
1363         if (m_remote_platform_sp)
1364             return m_remote_platform_sp->GetEnvironment(env);
1365         return 0;
1366     }
1367     return Host::GetEnvironment(env);
1368 }
1369 
1370 int32_t
1371 PlatformDarwin::GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info)
1372 {
1373     const char *shell = launch_info.GetShell();
1374     if (shell == NULL)
1375         return 1;
1376 
1377     const char *shell_name = strrchr (shell, '/');
1378     if (shell_name == NULL)
1379         shell_name = shell;
1380     else
1381         shell_name++;
1382 
1383     if (strcmp (shell_name, "sh") == 0)
1384     {
1385         // /bin/sh re-exec's itself as /bin/bash requiring another resume.
1386         // But it only does this if the COMMAND_MODE environment variable
1387         // is set to "legacy".
1388         char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
1389         if (envp != NULL)
1390         {
1391             for (int i = 0; envp[i] != NULL; i++)
1392             {
1393                 if (strcmp (envp[i], "COMMAND_MODE=legacy" ) == 0)
1394                     return 2;
1395             }
1396         }
1397         return 1;
1398     }
1399     else if (strcmp (shell_name, "csh") == 0
1400             || strcmp (shell_name, "tcsh") == 0
1401             || strcmp (shell_name, "zsh") == 0)
1402     {
1403         // csh and tcsh always seem to re-exec themselves.
1404         return 2;
1405     }
1406     else
1407         return 1;
1408 }
1409