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