1 //===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/lldb-python.h"
11 
12 #include "PlatformDarwin.h"
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Breakpoint/BreakpointLocation.h"
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Error.h"
21 #include "lldb/Core/Module.h"
22 #include "lldb/Core/ModuleSpec.h"
23 #include "lldb/Core/Timer.h"
24 #include "lldb/Host/Host.h"
25 #include "lldb/Host/Symbols.h"
26 #include "lldb/Symbol/ObjectFile.h"
27 #include "lldb/Symbol/SymbolFile.h"
28 #include "lldb/Symbol/SymbolVendor.h"
29 #include "lldb/Target/Target.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 
35 //------------------------------------------------------------------
36 /// Default Constructor
37 //------------------------------------------------------------------
PlatformDarwin(bool is_host)38 PlatformDarwin::PlatformDarwin (bool is_host) :
39     Platform(is_host),  // This is the local host platform
40     m_remote_platform_sp (),
41     m_developer_directory ()
42 {
43 }
44 
45 //------------------------------------------------------------------
46 /// Destructor.
47 ///
48 /// The destructor is virtual since this class is designed to be
49 /// inherited from by the plug-in instance.
50 //------------------------------------------------------------------
~PlatformDarwin()51 PlatformDarwin::~PlatformDarwin()
52 {
53 }
54 
55 FileSpecList
LocateExecutableScriptingResources(Target * target,Module & module)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
ResolveExecutable(const FileSpec & exe_file,const ArchSpec & exe_arch,lldb::ModuleSP & exe_module_sp,const FileSpecList * module_search_paths_ptr)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 = ModuleList::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
ResolveSymbolFile(Target & target,const ModuleSpec & sym_spec,FileSpec & sym_file)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 
272 
273 Error
GetSharedModule(const ModuleSpec & module_spec,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,ModuleSP * old_module_sp_ptr,bool * did_create_ptr)274 PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec,
275                                  ModuleSP &module_sp,
276                                  const FileSpecList *module_search_paths_ptr,
277                                  ModuleSP *old_module_sp_ptr,
278                                  bool *did_create_ptr)
279 {
280     Error error;
281     module_sp.reset();
282 
283     if (IsRemote())
284     {
285         // If we have a remote platform always, let it try and locate
286         // the shared module first.
287         if (m_remote_platform_sp)
288         {
289             error = m_remote_platform_sp->GetSharedModule (module_spec,
290                                                            module_sp,
291                                                            module_search_paths_ptr,
292                                                            old_module_sp_ptr,
293                                                            did_create_ptr);
294         }
295     }
296 
297     if (!module_sp)
298     {
299         // Fall back to the local platform and find the file locally
300         error = Platform::GetSharedModule (module_spec,
301                                            module_sp,
302                                            module_search_paths_ptr,
303                                            old_module_sp_ptr,
304                                            did_create_ptr);
305 
306         const FileSpec &platform_file = module_spec.GetFileSpec();
307         if (!module_sp && module_search_paths_ptr && platform_file)
308         {
309             // We can try to pull off part of the file path up to the bundle
310             // directory level and try any module search paths...
311             FileSpec bundle_directory;
312             if (Host::GetBundleDirectory (platform_file, bundle_directory))
313             {
314                 if (platform_file == bundle_directory)
315                 {
316                     ModuleSpec new_module_spec (module_spec);
317                     new_module_spec.GetFileSpec() = bundle_directory;
318                     if (Host::ResolveExecutableInBundle (new_module_spec.GetFileSpec()))
319                     {
320                         Error new_error (Platform::GetSharedModule (new_module_spec,
321                                                                     module_sp,
322                                                                     NULL,
323                                                                     old_module_sp_ptr,
324                                                                     did_create_ptr));
325 
326                         if (module_sp)
327                             return new_error;
328                     }
329                 }
330                 else
331                 {
332                     char platform_path[PATH_MAX];
333                     char bundle_dir[PATH_MAX];
334                     platform_file.GetPath (platform_path, sizeof(platform_path));
335                     const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
336                     char new_path[PATH_MAX];
337                     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
338                     for (size_t i=0; i<num_module_search_paths; ++i)
339                     {
340                         const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
341                         if (search_path_len < sizeof(new_path))
342                         {
343                             snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
344                             FileSpec new_file_spec (new_path, false);
345                             if (new_file_spec.Exists())
346                             {
347                                 ModuleSpec new_module_spec (module_spec);
348                                 new_module_spec.GetFileSpec() = new_file_spec;
349                                 Error new_error (Platform::GetSharedModule (new_module_spec,
350                                                                             module_sp,
351                                                                             NULL,
352                                                                             old_module_sp_ptr,
353                                                                             did_create_ptr));
354 
355                                 if (module_sp)
356                                 {
357                                     module_sp->SetPlatformFileSpec(new_file_spec);
358                                     return new_error;
359                                 }
360                             }
361                         }
362                     }
363                 }
364             }
365         }
366     }
367     if (module_sp)
368         module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
369     return error;
370 }
371 
372 size_t
GetSoftwareBreakpointTrapOpcode(Target & target,BreakpointSite * bp_site)373 PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
374 {
375     const uint8_t *trap_opcode = NULL;
376     uint32_t trap_opcode_size = 0;
377     bool bp_is_thumb = false;
378 
379     llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
380     switch (machine)
381     {
382     case llvm::Triple::x86:
383     case llvm::Triple::x86_64:
384         {
385             static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
386             trap_opcode = g_i386_breakpoint_opcode;
387             trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
388         }
389         break;
390 
391     case llvm::Triple::thumb:
392         bp_is_thumb = true; // Fall through...
393     case llvm::Triple::arm:
394         {
395             static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
396             static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
397 
398             // Auto detect arm/thumb if it wasn't explicitly specified
399             if (!bp_is_thumb)
400             {
401                 lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
402                 if (bp_loc_sp)
403                     bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA;
404             }
405             if (bp_is_thumb)
406             {
407                 trap_opcode = g_thumb_breakpooint_opcode;
408                 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
409                 break;
410             }
411             trap_opcode = g_arm_breakpoint_opcode;
412             trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
413         }
414         break;
415 
416     case llvm::Triple::ppc:
417     case llvm::Triple::ppc64:
418         {
419             static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
420             trap_opcode = g_ppc_breakpoint_opcode;
421             trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
422         }
423         break;
424 
425     default:
426         assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()");
427         break;
428     }
429 
430     if (trap_opcode && trap_opcode_size)
431     {
432         if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
433             return trap_opcode_size;
434     }
435     return 0;
436 
437 }
438 
439 bool
GetRemoteOSVersion()440 PlatformDarwin::GetRemoteOSVersion ()
441 {
442     if (m_remote_platform_sp)
443         return m_remote_platform_sp->GetOSVersion (m_major_os_version,
444                                                    m_minor_os_version,
445                                                    m_update_os_version);
446     return false;
447 }
448 
449 bool
GetRemoteOSBuildString(std::string & s)450 PlatformDarwin::GetRemoteOSBuildString (std::string &s)
451 {
452     if (m_remote_platform_sp)
453         return m_remote_platform_sp->GetRemoteOSBuildString (s);
454     s.clear();
455     return false;
456 }
457 
458 bool
GetRemoteOSKernelDescription(std::string & s)459 PlatformDarwin::GetRemoteOSKernelDescription (std::string &s)
460 {
461     if (m_remote_platform_sp)
462         return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
463     s.clear();
464     return false;
465 }
466 
467 // Remote Platform subclasses need to override this function
468 ArchSpec
GetRemoteSystemArchitecture()469 PlatformDarwin::GetRemoteSystemArchitecture ()
470 {
471     if (m_remote_platform_sp)
472         return m_remote_platform_sp->GetRemoteSystemArchitecture ();
473     return ArchSpec();
474 }
475 
476 
477 const char *
GetHostname()478 PlatformDarwin::GetHostname ()
479 {
480     if (IsHost())
481         return Platform::GetHostname();
482 
483     if (m_remote_platform_sp)
484         return m_remote_platform_sp->GetHostname ();
485     return NULL;
486 }
487 
488 bool
IsConnected() const489 PlatformDarwin::IsConnected () const
490 {
491     if (IsHost())
492         return true;
493     else if (m_remote_platform_sp)
494         return m_remote_platform_sp->IsConnected();
495     return false;
496 }
497 
498 Error
ConnectRemote(Args & args)499 PlatformDarwin::ConnectRemote (Args& args)
500 {
501     Error error;
502     if (IsHost())
503     {
504         error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
505     }
506     else
507     {
508         if (!m_remote_platform_sp)
509             m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
510 
511         if (m_remote_platform_sp)
512         {
513             if (error.Success())
514             {
515                 if (m_remote_platform_sp)
516                 {
517                     error = m_remote_platform_sp->ConnectRemote (args);
518                 }
519                 else
520                 {
521                     error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
522                 }
523             }
524         }
525         else
526             error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
527 
528         if (error.Fail())
529             m_remote_platform_sp.reset();
530     }
531 
532     return error;
533 }
534 
535 Error
DisconnectRemote()536 PlatformDarwin::DisconnectRemote ()
537 {
538     Error error;
539 
540     if (IsHost())
541     {
542         error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
543     }
544     else
545     {
546         if (m_remote_platform_sp)
547             error = m_remote_platform_sp->DisconnectRemote ();
548         else
549             error.SetErrorString ("the platform is not currently connected");
550     }
551     return error;
552 }
553 
554 
555 bool
GetProcessInfo(lldb::pid_t pid,ProcessInstanceInfo & process_info)556 PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
557 {
558     bool sucess = false;
559     if (IsHost())
560     {
561         sucess = Platform::GetProcessInfo (pid, process_info);
562     }
563     else
564     {
565         if (m_remote_platform_sp)
566             sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
567     }
568     return sucess;
569 }
570 
571 
572 
573 uint32_t
FindProcesses(const ProcessInstanceInfoMatch & match_info,ProcessInstanceInfoList & process_infos)574 PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
575                                ProcessInstanceInfoList &process_infos)
576 {
577     uint32_t match_count = 0;
578     if (IsHost())
579     {
580         // Let the base class figure out the host details
581         match_count = Platform::FindProcesses (match_info, process_infos);
582     }
583     else
584     {
585         // If we are remote, we can only return results if we are connected
586         if (m_remote_platform_sp)
587             match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
588     }
589     return match_count;
590 }
591 
592 Error
LaunchProcess(ProcessLaunchInfo & launch_info)593 PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
594 {
595     Error error;
596 
597     if (IsHost())
598     {
599         error = Platform::LaunchProcess (launch_info);
600     }
601     else
602     {
603         if (m_remote_platform_sp)
604             error = m_remote_platform_sp->LaunchProcess (launch_info);
605         else
606             error.SetErrorString ("the platform is not currently connected");
607     }
608     return error;
609 }
610 
611 lldb::ProcessSP
Attach(ProcessAttachInfo & attach_info,Debugger & debugger,Target * target,Listener & listener,Error & error)612 PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
613                         Debugger &debugger,
614                         Target *target,
615                         Listener &listener,
616                         Error &error)
617 {
618     lldb::ProcessSP process_sp;
619 
620     if (IsHost())
621     {
622         if (target == NULL)
623         {
624             TargetSP new_target_sp;
625 
626             error = debugger.GetTargetList().CreateTarget (debugger,
627                                                            NULL,
628                                                            NULL,
629                                                            false,
630                                                            NULL,
631                                                            new_target_sp);
632             target = new_target_sp.get();
633         }
634         else
635             error.Clear();
636 
637         if (target && error.Success())
638         {
639             debugger.GetTargetList().SetSelectedTarget(target);
640 
641             process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL);
642 
643             if (process_sp)
644                 error = process_sp->Attach (attach_info);
645         }
646     }
647     else
648     {
649         if (m_remote_platform_sp)
650             process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
651         else
652             error.SetErrorString ("the platform is not currently connected");
653     }
654     return process_sp;
655 }
656 
657 const char *
GetUserName(uint32_t uid)658 PlatformDarwin::GetUserName (uint32_t uid)
659 {
660     // Check the cache in Platform in case we have already looked this uid up
661     const char *user_name = Platform::GetUserName(uid);
662     if (user_name)
663         return user_name;
664 
665     if (IsRemote() && m_remote_platform_sp)
666         return m_remote_platform_sp->GetUserName(uid);
667     return NULL;
668 }
669 
670 const char *
GetGroupName(uint32_t gid)671 PlatformDarwin::GetGroupName (uint32_t gid)
672 {
673     const char *group_name = Platform::GetGroupName(gid);
674     if (group_name)
675         return group_name;
676 
677     if (IsRemote() && m_remote_platform_sp)
678         return m_remote_platform_sp->GetGroupName(gid);
679     return NULL;
680 }
681 
682 bool
ModuleIsExcludedForNonModuleSpecificSearches(lldb_private::Target & target,const lldb::ModuleSP & module_sp)683 PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
684 {
685     if (!module_sp)
686         return false;
687 
688     ObjectFile *obj_file = module_sp->GetObjectFile();
689     if (!obj_file)
690         return false;
691 
692     ObjectFile::Type obj_type = obj_file->GetType();
693     if (obj_type == ObjectFile::eTypeDynamicLinker)
694         return true;
695     else
696         return false;
697 }
698 
699 
700 bool
x86GetSupportedArchitectureAtIndex(uint32_t idx,ArchSpec & arch)701 PlatformDarwin::x86GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
702 {
703     if (idx == 0)
704     {
705         arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
706         return arch.IsValid();
707     }
708     else if (idx == 1)
709     {
710         ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
711         ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
712         if (platform_arch.IsExactMatch(platform_arch64))
713         {
714             // This macosx platform supports both 32 and 64 bit. Since we already
715             // returned the 64 bit arch for idx == 0, return the 32 bit arch
716             // for idx == 1
717             arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
718             return arch.IsValid();
719         }
720     }
721     return false;
722 }
723 
724 // The architecture selection rules for arm processors
725 // These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f processor.
726 
727 bool
ARMGetSupportedArchitectureAtIndex(uint32_t idx,ArchSpec & arch)728 PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
729 {
730     ArchSpec system_arch (GetSystemArchitecture());
731     const ArchSpec::Core system_core = system_arch.GetCore();
732     switch (system_core)
733     {
734     default:
735         switch (idx)
736         {
737             case  0: arch.SetTriple ("armv7-apple-ios");    return true;
738             case  1: arch.SetTriple ("armv7f-apple-ios");   return true;
739             case  2: arch.SetTriple ("armv7k-apple-ios");   return true;
740             case  3: arch.SetTriple ("armv7s-apple-ios");   return true;
741             case  4: arch.SetTriple ("armv7m-apple-ios");   return true;
742             case  5: arch.SetTriple ("armv7em-apple-ios");  return true;
743             case  6: arch.SetTriple ("armv6-apple-ios");    return true;
744             case  7: arch.SetTriple ("armv5-apple-ios");    return true;
745             case  8: arch.SetTriple ("armv4-apple-ios");    return true;
746             case  9: arch.SetTriple ("arm-apple-ios");      return true;
747             case 10: arch.SetTriple ("thumbv7-apple-ios");  return true;
748             case 11: arch.SetTriple ("thumbv7f-apple-ios"); return true;
749             case 12: arch.SetTriple ("thumbv7k-apple-ios"); return true;
750             case 13: arch.SetTriple ("thumbv7s-apple-ios"); return true;
751             case 14: arch.SetTriple ("thumbv7m-apple-ios"); return true;
752             case 15: arch.SetTriple ("thumbv7em-apple-ios"); return true;
753             case 16: arch.SetTriple ("thumbv6-apple-ios");  return true;
754             case 17: arch.SetTriple ("thumbv5-apple-ios");  return true;
755             case 18: arch.SetTriple ("thumbv4t-apple-ios"); return true;
756             case 19: arch.SetTriple ("thumb-apple-ios");    return true;
757         default: break;
758         }
759         break;
760 
761     case ArchSpec::eCore_arm_armv7f:
762         switch (idx)
763         {
764             case  0: arch.SetTriple ("armv7f-apple-ios");   return true;
765             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
766             case  2: arch.SetTriple ("armv6-apple-ios");    return true;
767             case  3: arch.SetTriple ("armv5-apple-ios");    return true;
768             case  4: arch.SetTriple ("armv4-apple-ios");    return true;
769             case  5: arch.SetTriple ("arm-apple-ios");      return true;
770             case  6: arch.SetTriple ("thumbv7f-apple-ios"); return true;
771             case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
772             case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
773             case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
774             case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
775             case 11: arch.SetTriple ("thumb-apple-ios");    return true;
776             default: break;
777         }
778         break;
779 
780     case ArchSpec::eCore_arm_armv7k:
781         switch (idx)
782         {
783             case  0: arch.SetTriple ("armv7k-apple-ios");   return true;
784             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
785             case  2: arch.SetTriple ("armv6-apple-ios");    return true;
786             case  3: arch.SetTriple ("armv5-apple-ios");    return true;
787             case  4: arch.SetTriple ("armv4-apple-ios");    return true;
788             case  5: arch.SetTriple ("arm-apple-ios");      return true;
789             case  6: arch.SetTriple ("thumbv7k-apple-ios"); return true;
790             case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
791             case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
792             case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
793             case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
794             case 11: arch.SetTriple ("thumb-apple-ios");    return true;
795             default: break;
796         }
797         break;
798 
799     case ArchSpec::eCore_arm_armv7s:
800         switch (idx)
801         {
802             case  0: arch.SetTriple ("armv7s-apple-ios");   return true;
803             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
804             case  2: arch.SetTriple ("armv6-apple-ios");    return true;
805             case  3: arch.SetTriple ("armv5-apple-ios");    return true;
806             case  4: arch.SetTriple ("armv4-apple-ios");    return true;
807             case  5: arch.SetTriple ("arm-apple-ios");      return true;
808             case  6: arch.SetTriple ("thumbv7s-apple-ios"); return true;
809             case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
810             case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
811             case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
812             case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
813             case 11: arch.SetTriple ("thumb-apple-ios");    return true;
814             default: break;
815         }
816         break;
817 
818     case ArchSpec::eCore_arm_armv7m:
819         switch (idx)
820         {
821             case  0: arch.SetTriple ("armv7m-apple-ios");   return true;
822             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
823             case  2: arch.SetTriple ("armv6-apple-ios");    return true;
824             case  3: arch.SetTriple ("armv5-apple-ios");    return true;
825             case  4: arch.SetTriple ("armv4-apple-ios");    return true;
826             case  5: arch.SetTriple ("arm-apple-ios");      return true;
827             case  6: arch.SetTriple ("thumbv7m-apple-ios"); return true;
828             case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
829             case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
830             case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
831             case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
832             case 11: arch.SetTriple ("thumb-apple-ios");    return true;
833             default: break;
834         }
835         break;
836 
837     case ArchSpec::eCore_arm_armv7em:
838         switch (idx)
839         {
840             case  0: arch.SetTriple ("armv7em-apple-ios");   return true;
841             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
842             case  2: arch.SetTriple ("armv6-apple-ios");    return true;
843             case  3: arch.SetTriple ("armv5-apple-ios");    return true;
844             case  4: arch.SetTriple ("armv4-apple-ios");    return true;
845             case  5: arch.SetTriple ("arm-apple-ios");      return true;
846             case  6: arch.SetTriple ("thumbv7em-apple-ios"); return true;
847             case  7: arch.SetTriple ("thumbv7-apple-ios");  return true;
848             case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
849             case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
850             case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
851             case 11: arch.SetTriple ("thumb-apple-ios");    return true;
852             default: break;
853         }
854         break;
855 
856     case ArchSpec::eCore_arm_armv7:
857         switch (idx)
858         {
859             case 0: arch.SetTriple ("armv7-apple-ios");    return true;
860             case 1: arch.SetTriple ("armv6-apple-ios");    return true;
861             case 2: arch.SetTriple ("armv5-apple-ios");    return true;
862             case 3: arch.SetTriple ("armv4-apple-ios");    return true;
863             case 4: arch.SetTriple ("arm-apple-ios");      return true;
864             case 5: arch.SetTriple ("thumbv7-apple-ios");  return true;
865             case 6: arch.SetTriple ("thumbv6-apple-ios");  return true;
866             case 7: arch.SetTriple ("thumbv5-apple-ios");  return true;
867             case 8: arch.SetTriple ("thumbv4t-apple-ios"); return true;
868             case 9: arch.SetTriple ("thumb-apple-ios");    return true;
869             default: break;
870         }
871         break;
872 
873     case ArchSpec::eCore_arm_armv6:
874         switch (idx)
875         {
876             case 0: arch.SetTriple ("armv6-apple-ios");    return true;
877             case 1: arch.SetTriple ("armv5-apple-ios");    return true;
878             case 2: arch.SetTriple ("armv4-apple-ios");    return true;
879             case 3: arch.SetTriple ("arm-apple-ios");      return true;
880             case 4: arch.SetTriple ("thumbv6-apple-ios");  return true;
881             case 5: arch.SetTriple ("thumbv5-apple-ios");  return true;
882             case 6: arch.SetTriple ("thumbv4t-apple-ios"); return true;
883             case 7: arch.SetTriple ("thumb-apple-ios");    return true;
884             default: break;
885         }
886         break;
887 
888     case ArchSpec::eCore_arm_armv5:
889         switch (idx)
890         {
891             case 0: arch.SetTriple ("armv5-apple-ios");    return true;
892             case 1: arch.SetTriple ("armv4-apple-ios");    return true;
893             case 2: arch.SetTriple ("arm-apple-ios");      return true;
894             case 3: arch.SetTriple ("thumbv5-apple-ios");  return true;
895             case 4: arch.SetTriple ("thumbv4t-apple-ios"); return true;
896             case 5: arch.SetTriple ("thumb-apple-ios");    return true;
897             default: break;
898         }
899         break;
900 
901     case ArchSpec::eCore_arm_armv4:
902         switch (idx)
903         {
904             case 0: arch.SetTriple ("armv4-apple-ios");    return true;
905             case 1: arch.SetTriple ("arm-apple-ios");      return true;
906             case 2: arch.SetTriple ("thumbv4t-apple-ios"); return true;
907             case 3: arch.SetTriple ("thumb-apple-ios");    return true;
908             default: break;
909         }
910         break;
911     }
912     arch.Clear();
913     return false;
914 }
915 
916 
917 const char *
GetDeveloperDirectory()918 PlatformDarwin::GetDeveloperDirectory()
919 {
920     if (m_developer_directory.empty())
921     {
922         bool developer_dir_path_valid = false;
923         char developer_dir_path[PATH_MAX];
924         FileSpec temp_file_spec;
925         if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, temp_file_spec))
926         {
927             if (temp_file_spec.GetPath (developer_dir_path, sizeof(developer_dir_path)))
928             {
929                 char *shared_frameworks = strstr (developer_dir_path, "/SharedFrameworks/LLDB.framework");
930                 if (shared_frameworks)
931                 {
932                     ::snprintf (shared_frameworks,
933                                 sizeof(developer_dir_path) - (shared_frameworks - developer_dir_path),
934                                 "/Developer");
935                     developer_dir_path_valid = true;
936                 }
937                 else
938                 {
939                     char *lib_priv_frameworks = strstr (developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework");
940                     if (lib_priv_frameworks)
941                     {
942                         *lib_priv_frameworks = '\0';
943                         developer_dir_path_valid = true;
944                     }
945                 }
946             }
947         }
948 
949         if (!developer_dir_path_valid)
950         {
951             std::string xcode_dir_path;
952             const char *xcode_select_prefix_dir = getenv ("XCODE_SELECT_PREFIX_DIR");
953             if (xcode_select_prefix_dir)
954                 xcode_dir_path.append (xcode_select_prefix_dir);
955             xcode_dir_path.append ("/usr/share/xcode-select/xcode_dir_path");
956             temp_file_spec.SetFile(xcode_dir_path.c_str(), false);
957             size_t bytes_read = temp_file_spec.ReadFileContents(0, developer_dir_path, sizeof(developer_dir_path), NULL);
958             if (bytes_read > 0)
959             {
960                 developer_dir_path[bytes_read] = '\0';
961                 while (developer_dir_path[bytes_read-1] == '\r' ||
962                        developer_dir_path[bytes_read-1] == '\n')
963                     developer_dir_path[--bytes_read] = '\0';
964                 developer_dir_path_valid = true;
965             }
966         }
967 
968         if (!developer_dir_path_valid)
969         {
970             FileSpec xcode_select_cmd ("/usr/bin/xcode-select", false);
971             if (xcode_select_cmd.Exists())
972             {
973                 int exit_status = -1;
974                 int signo = -1;
975                 std::string command_output;
976                 Error error = Host::RunShellCommand ("/usr/bin/xcode-select --print-path",
977                                                      NULL,                                 // current working directory
978                                                      &exit_status,
979                                                      &signo,
980                                                      &command_output,
981                                                      2,                                     // short timeout
982                                                      NULL);                                 // don't run in a shell
983                 if (error.Success() && exit_status == 0 && !command_output.empty())
984                 {
985                     const char *cmd_output_ptr = command_output.c_str();
986                     developer_dir_path[sizeof (developer_dir_path) - 1] = '\0';
987                     size_t i;
988                     for (i = 0; i < sizeof (developer_dir_path) - 1; i++)
989                     {
990                         if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' || cmd_output_ptr[i] == '\0')
991                             break;
992                         developer_dir_path[i] = cmd_output_ptr[i];
993                     }
994                     developer_dir_path[i] = '\0';
995 
996                     FileSpec devel_dir (developer_dir_path, false);
997                     if (devel_dir.Exists() && devel_dir.IsDirectory())
998                     {
999                         developer_dir_path_valid = true;
1000                     }
1001                 }
1002             }
1003         }
1004 
1005         if (developer_dir_path_valid)
1006         {
1007             temp_file_spec.SetFile (developer_dir_path, false);
1008             if (temp_file_spec.Exists())
1009             {
1010                 m_developer_directory.assign (developer_dir_path);
1011                 return m_developer_directory.c_str();
1012             }
1013         }
1014         // Assign a single NULL character so we know we tried to find the device
1015         // support directory and we don't keep trying to find it over and over.
1016         m_developer_directory.assign (1, '\0');
1017     }
1018 
1019     // We should have put a single NULL character into m_developer_directory
1020     // or it should have a valid path if the code gets here
1021     assert (m_developer_directory.empty() == false);
1022     if (m_developer_directory[0])
1023         return m_developer_directory.c_str();
1024     return NULL;
1025 }
1026 
1027 
1028 BreakpointSP
SetThreadCreationBreakpoint(Target & target)1029 PlatformDarwin::SetThreadCreationBreakpoint (Target &target)
1030 {
1031     BreakpointSP bp_sp;
1032     static const char *g_bp_names[] =
1033     {
1034         "start_wqthread",
1035         "_pthread_wqthread",
1036         "_pthread_start",
1037     };
1038 
1039     static const char *g_bp_modules[] =
1040     {
1041         "libsystem_c.dylib",
1042         "libSystem.B.dylib"
1043     };
1044 
1045     FileSpecList bp_modules;
1046     for (size_t i = 0; i < sizeof(g_bp_modules)/sizeof(const char *); i++)
1047     {
1048         const char *bp_module = g_bp_modules[i];
1049         bp_modules.Append(FileSpec(bp_module, false));
1050     }
1051 
1052     bool internal = true;
1053     LazyBool skip_prologue = eLazyBoolNo;
1054     bp_sp = target.CreateBreakpoint (&bp_modules,
1055                                      NULL,
1056                                      g_bp_names,
1057                                      sizeof(g_bp_names)/sizeof(const char *),
1058                                      eFunctionNameTypeFull,
1059                                      skip_prologue,
1060                                      internal);
1061     bp_sp->SetBreakpointKind("thread-creation");
1062 
1063     return bp_sp;
1064 }
1065 
1066 size_t
GetEnvironment(StringList & env)1067 PlatformDarwin::GetEnvironment (StringList &env)
1068 {
1069     if (IsRemote())
1070     {
1071         if (m_remote_platform_sp)
1072             return m_remote_platform_sp->GetEnvironment(env);
1073         return 0;
1074     }
1075     return Host::GetEnvironment(env);
1076 }
1077