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