1 //===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "PlatformDarwin.h"
11 
12 // C Includes
13 #include <string.h>
14 
15 // C++ Includes
16 #include <algorithm>
17 #include <mutex>
18 
19 // Other libraries and framework includes
20 #include "clang/Basic/VersionTuple.h"
21 // Project includes
22 #include "lldb/Breakpoint/BreakpointLocation.h"
23 #include "lldb/Breakpoint/BreakpointSite.h"
24 #include "lldb/Core/Debugger.h"
25 #include "lldb/Core/Error.h"
26 #include "lldb/Core/Log.h"
27 #include "lldb/Core/Module.h"
28 #include "lldb/Core/ModuleSpec.h"
29 #include "lldb/Core/Timer.h"
30 #include "lldb/Host/Host.h"
31 #include "lldb/Host/HostInfo.h"
32 #include "lldb/Host/FileSystem.h"
33 #include "lldb/Host/Symbols.h"
34 #include "lldb/Host/StringConvert.h"
35 #include "lldb/Host/XML.h"
36 #include "lldb/Interpreter/CommandInterpreter.h"
37 #include "lldb/Symbol/ObjectFile.h"
38 #include "lldb/Symbol/SymbolFile.h"
39 #include "lldb/Symbol/SymbolVendor.h"
40 #include "lldb/Target/Process.h"
41 #include "lldb/Target/Target.h"
42 #include "llvm/ADT/STLExtras.h"
43 
44 using namespace lldb;
45 using namespace lldb_private;
46 
47 
48 //------------------------------------------------------------------
49 /// Default Constructor
50 //------------------------------------------------------------------
51 PlatformDarwin::PlatformDarwin (bool is_host) :
52     PlatformPOSIX(is_host),  // This is the local host platform
53     m_developer_directory ()
54 {
55 }
56 
57 //------------------------------------------------------------------
58 /// Destructor.
59 ///
60 /// The destructor is virtual since this class is designed to be
61 /// inherited from by the plug-in instance.
62 //------------------------------------------------------------------
63 PlatformDarwin::~PlatformDarwin()
64 {
65 }
66 
67 FileSpecList
68 PlatformDarwin::LocateExecutableScriptingResources (Target *target,
69                                                     Module &module,
70                                                     Stream* feedback_stream)
71 {
72     FileSpecList file_list;
73     if (target && target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython)
74     {
75         // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
76         // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
77         // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
78         // which should be stripped while leaving "this.binary.file" as-is.
79         ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
80 
81         FileSpec module_spec = module.GetFileSpec();
82 
83         if (module_spec)
84         {
85             SymbolVendor *symbols = module.GetSymbolVendor ();
86             if (symbols)
87             {
88                 SymbolFile *symfile = symbols->GetSymbolFile();
89                 if (symfile)
90                 {
91                     ObjectFile *objfile = symfile->GetObjectFile();
92                     if (objfile)
93                     {
94                         FileSpec symfile_spec (objfile->GetFileSpec());
95                         if (symfile_spec && symfile_spec.Exists())
96                         {
97                             while (module_spec.GetFilename())
98                             {
99                                 std::string module_basename (module_spec.GetFilename().GetCString());
100                                 std::string original_module_basename (module_basename);
101 
102                                 bool was_keyword = false;
103 
104                                 // FIXME: for Python, we cannot allow certain characters in module
105                                 // filenames we import. Theoretically, different scripting languages may
106                                 // have different sets of forbidden tokens in filenames, and that should
107                                 // be dealt with by each ScriptInterpreter. For now, we just replace dots
108                                 // with underscores, but if we ever support anything other than Python
109                                 // we will need to rework this
110                                 std::replace(module_basename.begin(), module_basename.end(), '.', '_');
111                                 std::replace(module_basename.begin(), module_basename.end(), ' ', '_');
112                                 std::replace(module_basename.begin(), module_basename.end(), '-', '_');
113                                 if (script_interpreter && script_interpreter->IsReservedWord(module_basename.c_str()))
114                                 {
115                                     module_basename.insert(module_basename.begin(), '_');
116                                     was_keyword = true;
117                                 }
118 
119                                 StreamString path_string;
120                                 StreamString original_path_string;
121                                 // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
122                                 // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
123                                 path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), module_basename.c_str());
124                                 original_path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), original_module_basename.c_str());
125                                 FileSpec script_fspec(path_string.GetData(), true);
126                                 FileSpec orig_script_fspec(original_path_string.GetData(), true);
127 
128                                 // if we did some replacements of reserved characters, and a file with the untampered name
129                                 // exists, then warn the user that the file as-is shall not be loaded
130                                 if (feedback_stream)
131                                 {
132                                     if (module_basename != original_module_basename
133                                         && orig_script_fspec.Exists())
134                                     {
135                                         const char* reason_for_complaint = was_keyword ? "conflicts with a keyword" : "contains reserved characters";
136                                         if (script_fspec.Exists())
137                                             feedback_stream->Printf("warning: the symbol file '%s' contains a debug script. However, its name"
138                                                                     " '%s' %s and as such cannot be loaded. LLDB will"
139                                                                     " load '%s' instead. Consider removing the file with the malformed name to"
140                                                                     " eliminate this warning.\n",
141                                                                     symfile_spec.GetPath().c_str(),
142                                                                     original_path_string.GetData(),
143                                                                     reason_for_complaint,
144                                                                     path_string.GetData());
145                                         else
146                                             feedback_stream->Printf("warning: the symbol file '%s' contains a debug script. However, its name"
147                                                                     " %s and as such cannot be loaded. If you intend"
148                                                                     " to have this script loaded, please rename '%s' to '%s' and retry.\n",
149                                                                     symfile_spec.GetPath().c_str(),
150                                                                     reason_for_complaint,
151                                                                     original_path_string.GetData(),
152                                                                     path_string.GetData());
153                                     }
154                                 }
155 
156                                 if (script_fspec.Exists())
157                                 {
158                                     file_list.Append (script_fspec);
159                                     break;
160                                 }
161 
162                                 // If we didn't find the python file, then keep
163                                 // stripping the extensions and try again
164                                 ConstString filename_no_extension (module_spec.GetFileNameStrippingExtension());
165                                 if (module_spec.GetFilename() == filename_no_extension)
166                                     break;
167 
168                                 module_spec.GetFilename() = filename_no_extension;
169                             }
170                         }
171                     }
172                 }
173             }
174         }
175     }
176     return file_list;
177 }
178 
179 Error
180 PlatformDarwin::ResolveExecutable (const ModuleSpec &module_spec,
181                                    lldb::ModuleSP &exe_module_sp,
182                                    const FileSpecList *module_search_paths_ptr)
183 {
184     Error error;
185     // Nothing special to do here, just use the actual file and architecture
186 
187     char exe_path[PATH_MAX];
188     ModuleSpec resolved_module_spec(module_spec);
189 
190     if (IsHost())
191     {
192         // If we have "ls" as the exe_file, resolve the executable loation based on
193         // the current path variables
194         if (!resolved_module_spec.GetFileSpec().Exists())
195         {
196             module_spec.GetFileSpec().GetPath (exe_path, sizeof(exe_path));
197             resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
198         }
199 
200         if (!resolved_module_spec.GetFileSpec().Exists())
201             resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
202 
203         // Resolve any executable within a bundle on MacOSX
204         Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
205 
206         if (resolved_module_spec.GetFileSpec().Exists())
207             error.Clear();
208         else
209         {
210             const uint32_t permissions = resolved_module_spec.GetFileSpec().GetPermissions();
211             if (permissions && (permissions & eFilePermissionsEveryoneR) == 0)
212                 error.SetErrorStringWithFormat ("executable '%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
213             else
214                 error.SetErrorStringWithFormat ("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
215         }
216     }
217     else
218     {
219         if (m_remote_platform_sp)
220         {
221             error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
222         }
223         else
224         {
225             // We may connect to a process and use the provided executable (Don't use local $PATH).
226 
227             // Resolve any executable within a bundle on MacOSX
228             Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
229 
230             if (resolved_module_spec.GetFileSpec().Exists())
231                 error.Clear();
232             else
233                 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetFilename().AsCString(""));
234         }
235     }
236 
237 
238     if (error.Success())
239     {
240         if (resolved_module_spec.GetArchitecture().IsValid())
241         {
242             error = ModuleList::GetSharedModule (resolved_module_spec,
243                                                  exe_module_sp,
244                                                  module_search_paths_ptr,
245                                                  NULL,
246                                                  NULL);
247 
248             if (error.Fail() || exe_module_sp.get() == NULL || exe_module_sp->GetObjectFile() == NULL)
249             {
250                 exe_module_sp.reset();
251                 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
252                                                 resolved_module_spec.GetFileSpec().GetPath().c_str(),
253                                                 resolved_module_spec.GetArchitecture().GetArchitectureName());
254             }
255         }
256         else
257         {
258             // No valid architecture was specified, ask the platform for
259             // the architectures that we should be using (in the correct order)
260             // and see if we can find a match that way
261             StreamString arch_names;
262             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
263             {
264                 error = GetSharedModule (resolved_module_spec,
265                                          NULL,
266                                          exe_module_sp,
267                                          module_search_paths_ptr,
268                                          NULL,
269                                          NULL);
270                 // Did we find an executable using one of the
271                 if (error.Success())
272                 {
273                     if (exe_module_sp && exe_module_sp->GetObjectFile())
274                         break;
275                     else
276                         error.SetErrorToGenericError();
277                 }
278 
279                 if (idx > 0)
280                     arch_names.PutCString (", ");
281                 arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
282             }
283 
284             if (error.Fail() || !exe_module_sp)
285             {
286                 if (resolved_module_spec.GetFileSpec().Readable())
287                 {
288                     error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
289                                                     resolved_module_spec.GetFileSpec().GetPath().c_str(),
290                                                     GetPluginName().GetCString(),
291                                                     arch_names.GetString().c_str());
292                 }
293                 else
294                 {
295                     error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
296                 }
297             }
298         }
299     }
300 
301     return error;
302 }
303 
304 Error
305 PlatformDarwin::ResolveSymbolFile (Target &target,
306                                    const ModuleSpec &sym_spec,
307                                    FileSpec &sym_file)
308 {
309     Error error;
310     sym_file = sym_spec.GetSymbolFileSpec();
311     if (sym_file.Exists())
312     {
313         if (sym_file.GetFileType() == FileSpec::eFileTypeDirectory)
314         {
315             sym_file = Symbols::FindSymbolFileInBundle (sym_file,
316                                                         sym_spec.GetUUIDPtr(),
317                                                         sym_spec.GetArchitecturePtr());
318         }
319     }
320     else
321     {
322         if (sym_spec.GetUUID().IsValid())
323         {
324 
325         }
326     }
327     return error;
328 
329 }
330 
331 static lldb_private::Error
332 MakeCacheFolderForFile (const FileSpec& module_cache_spec)
333 {
334     FileSpec module_cache_folder = module_cache_spec.CopyByRemovingLastPathComponent();
335     return FileSystem::MakeDirectory(module_cache_folder, eFilePermissionsDirectoryDefault);
336 }
337 
338 static lldb_private::Error
339 BringInRemoteFile (Platform* platform,
340                    const lldb_private::ModuleSpec &module_spec,
341                    const FileSpec& module_cache_spec)
342 {
343     MakeCacheFolderForFile(module_cache_spec);
344     Error err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec);
345     return err;
346 }
347 
348 lldb_private::Error
349 PlatformDarwin::GetSharedModuleWithLocalCache (const lldb_private::ModuleSpec &module_spec,
350                                                lldb::ModuleSP &module_sp,
351                                                const lldb_private::FileSpecList *module_search_paths_ptr,
352                                                lldb::ModuleSP *old_module_sp_ptr,
353                                                bool *did_create_ptr)
354 {
355 
356     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
357     if (log)
358         log->Printf("[%s] Trying to find module %s/%s - platform path %s/%s symbol path %s/%s",
359                      (IsHost() ? "host" : "remote"),
360                      module_spec.GetFileSpec().GetDirectory().AsCString(),
361                      module_spec.GetFileSpec().GetFilename().AsCString(),
362                      module_spec.GetPlatformFileSpec().GetDirectory().AsCString(),
363                      module_spec.GetPlatformFileSpec().GetFilename().AsCString(),
364                      module_spec.GetSymbolFileSpec().GetDirectory().AsCString(),
365                      module_spec.GetSymbolFileSpec().GetFilename().AsCString());
366 
367     Error err;
368 
369     err = ModuleList::GetSharedModule(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
370     if (module_sp)
371         return err;
372 
373     if (!IsHost())
374     {
375         std::string cache_path(GetLocalCacheDirectory());
376         // Only search for a locally cached file if we have a valid cache path
377         if (!cache_path.empty())
378         {
379             std::string module_path (module_spec.GetFileSpec().GetPath());
380             cache_path.append(module_path);
381             FileSpec module_cache_spec(cache_path.c_str(),false);
382 
383             // if rsync is supported, always bring in the file - rsync will be very efficient
384             // when files are the same on the local and remote end of the connection
385             if (this->GetSupportsRSync())
386             {
387                 err = BringInRemoteFile (this, module_spec, module_cache_spec);
388                 if (err.Fail())
389                     return err;
390                 if (module_cache_spec.Exists())
391                 {
392                     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
393                     if (log)
394                         log->Printf("[%s] module %s/%s was rsynced and is now there",
395                                      (IsHost() ? "host" : "remote"),
396                                      module_spec.GetFileSpec().GetDirectory().AsCString(),
397                                      module_spec.GetFileSpec().GetFilename().AsCString());
398                     ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
399                     module_sp.reset(new Module(local_spec));
400                     module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
401                     return Error();
402                 }
403             }
404 
405             // try to find the module in the cache
406             if (module_cache_spec.Exists())
407             {
408                 // get the local and remote MD5 and compare
409                 if (m_remote_platform_sp)
410                 {
411                     // when going over the *slow* GDB remote transfer mechanism we first check
412                     // the hashes of the files - and only do the actual transfer if they differ
413                     uint64_t high_local,high_remote,low_local,low_remote;
414                     FileSystem::CalculateMD5(module_cache_spec, low_local, high_local);
415                     m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), low_remote, high_remote);
416                     if (low_local != low_remote || high_local != high_remote)
417                     {
418                         // bring in the remote file
419                         Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
420                         if (log)
421                             log->Printf("[%s] module %s/%s needs to be replaced from remote copy",
422                                          (IsHost() ? "host" : "remote"),
423                                          module_spec.GetFileSpec().GetDirectory().AsCString(),
424                                          module_spec.GetFileSpec().GetFilename().AsCString());
425                         Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
426                         if (err.Fail())
427                             return err;
428                     }
429                 }
430 
431                 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
432                 module_sp.reset(new Module(local_spec));
433                 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
434                 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
435                     if (log)
436                         log->Printf("[%s] module %s/%s was found in the cache",
437                                      (IsHost() ? "host" : "remote"),
438                                      module_spec.GetFileSpec().GetDirectory().AsCString(),
439                                      module_spec.GetFileSpec().GetFilename().AsCString());
440                 return Error();
441             }
442 
443             // bring in the remote module file
444             if (log)
445                 log->Printf("[%s] module %s/%s needs to come in remotely",
446                              (IsHost() ? "host" : "remote"),
447                              module_spec.GetFileSpec().GetDirectory().AsCString(),
448                              module_spec.GetFileSpec().GetFilename().AsCString());
449             Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
450             if (err.Fail())
451                 return err;
452             if (module_cache_spec.Exists())
453             {
454                 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
455                 if (log)
456                     log->Printf("[%s] module %s/%s is now cached and fine",
457                                  (IsHost() ? "host" : "remote"),
458                                  module_spec.GetFileSpec().GetDirectory().AsCString(),
459                                  module_spec.GetFileSpec().GetFilename().AsCString());
460                 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
461                 module_sp.reset(new Module(local_spec));
462                 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
463                 return Error();
464             }
465             else
466                 return Error("unable to obtain valid module file");
467         }
468         else
469             return Error("no cache path");
470     }
471     else
472         return Error ("unable to resolve module");
473 }
474 
475 Error
476 PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec,
477                                  Process* process,
478                                  ModuleSP &module_sp,
479                                  const FileSpecList *module_search_paths_ptr,
480                                  ModuleSP *old_module_sp_ptr,
481                                  bool *did_create_ptr)
482 {
483     Error error;
484     module_sp.reset();
485 
486     if (IsRemote())
487     {
488         // If we have a remote platform always, let it try and locate
489         // the shared module first.
490         if (m_remote_platform_sp)
491         {
492             error = m_remote_platform_sp->GetSharedModule (module_spec,
493                                                            process,
494                                                            module_sp,
495                                                            module_search_paths_ptr,
496                                                            old_module_sp_ptr,
497                                                            did_create_ptr);
498         }
499     }
500 
501     if (!module_sp)
502     {
503         // Fall back to the local platform and find the file locally
504         error = Platform::GetSharedModule (module_spec,
505                                            process,
506                                            module_sp,
507                                            module_search_paths_ptr,
508                                            old_module_sp_ptr,
509                                            did_create_ptr);
510 
511         const FileSpec &platform_file = module_spec.GetFileSpec();
512         if (!module_sp && module_search_paths_ptr && platform_file)
513         {
514             // We can try to pull off part of the file path up to the bundle
515             // directory level and try any module search paths...
516             FileSpec bundle_directory;
517             if (Host::GetBundleDirectory (platform_file, bundle_directory))
518             {
519                 if (platform_file == bundle_directory)
520                 {
521                     ModuleSpec new_module_spec (module_spec);
522                     new_module_spec.GetFileSpec() = bundle_directory;
523                     if (Host::ResolveExecutableInBundle (new_module_spec.GetFileSpec()))
524                     {
525                         Error new_error (Platform::GetSharedModule (new_module_spec,
526                                                                     process,
527                                                                     module_sp,
528                                                                     NULL,
529                                                                     old_module_sp_ptr,
530                                                                     did_create_ptr));
531 
532                         if (module_sp)
533                             return new_error;
534                     }
535                 }
536                 else
537                 {
538                     char platform_path[PATH_MAX];
539                     char bundle_dir[PATH_MAX];
540                     platform_file.GetPath (platform_path, sizeof(platform_path));
541                     const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
542                     char new_path[PATH_MAX];
543                     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
544                     for (size_t i=0; i<num_module_search_paths; ++i)
545                     {
546                         const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
547                         if (search_path_len < sizeof(new_path))
548                         {
549                             snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
550                             FileSpec new_file_spec (new_path, false);
551                             if (new_file_spec.Exists())
552                             {
553                                 ModuleSpec new_module_spec (module_spec);
554                                 new_module_spec.GetFileSpec() = new_file_spec;
555                                 Error new_error (Platform::GetSharedModule (new_module_spec,
556                                                                             process,
557                                                                             module_sp,
558                                                                             NULL,
559                                                                             old_module_sp_ptr,
560                                                                             did_create_ptr));
561 
562                                 if (module_sp)
563                                 {
564                                     module_sp->SetPlatformFileSpec(new_file_spec);
565                                     return new_error;
566                                 }
567                             }
568                         }
569                     }
570                 }
571             }
572         }
573     }
574     if (module_sp)
575         module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
576     return error;
577 }
578 
579 size_t
580 PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
581 {
582     const uint8_t *trap_opcode = NULL;
583     uint32_t trap_opcode_size = 0;
584     bool bp_is_thumb = false;
585 
586     llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
587     switch (machine)
588     {
589     case llvm::Triple::x86:
590     case llvm::Triple::x86_64:
591         {
592             static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
593             trap_opcode = g_i386_breakpoint_opcode;
594             trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
595         }
596         break;
597 
598     case llvm::Triple::aarch64:
599         {
600             // TODO: fix this with actual darwin breakpoint opcode for arm64.
601             // right now debugging uses the Z packets with GDB remote so this
602             // is not needed, but the size needs to be correct...
603             static const uint8_t g_arm64_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
604             trap_opcode = g_arm64_breakpoint_opcode;
605             trap_opcode_size = sizeof(g_arm64_breakpoint_opcode);
606         }
607         break;
608 
609     case llvm::Triple::thumb:
610         bp_is_thumb = true; // Fall through...
611     case llvm::Triple::arm:
612         {
613             static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
614             static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
615 
616             // Auto detect arm/thumb if it wasn't explicitly specified
617             if (!bp_is_thumb)
618             {
619                 lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
620                 if (bp_loc_sp)
621                     bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA;
622             }
623             if (bp_is_thumb)
624             {
625                 trap_opcode = g_thumb_breakpooint_opcode;
626                 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
627                 break;
628             }
629             trap_opcode = g_arm_breakpoint_opcode;
630             trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
631         }
632         break;
633 
634     case llvm::Triple::ppc:
635     case llvm::Triple::ppc64:
636         {
637             static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
638             trap_opcode = g_ppc_breakpoint_opcode;
639             trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
640         }
641         break;
642 
643     default:
644         assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()");
645         break;
646     }
647 
648     if (trap_opcode && trap_opcode_size)
649     {
650         if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
651             return trap_opcode_size;
652     }
653     return 0;
654 
655 }
656 
657 bool
658 PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
659 {
660     bool success = false;
661     if (IsHost())
662     {
663         success = Platform::GetProcessInfo (pid, process_info);
664     }
665     else
666     {
667         if (m_remote_platform_sp)
668             success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
669     }
670     return success;
671 }
672 
673 uint32_t
674 PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
675                                ProcessInstanceInfoList &process_infos)
676 {
677     uint32_t match_count = 0;
678     if (IsHost())
679     {
680         // Let the base class figure out the host details
681         match_count = Platform::FindProcesses (match_info, process_infos);
682     }
683     else
684     {
685         // If we are remote, we can only return results if we are connected
686         if (m_remote_platform_sp)
687             match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
688     }
689     return match_count;
690 }
691 
692 bool
693 PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
694 {
695     if (!module_sp)
696         return false;
697 
698     ObjectFile *obj_file = module_sp->GetObjectFile();
699     if (!obj_file)
700         return false;
701 
702     ObjectFile::Type obj_type = obj_file->GetType();
703     if (obj_type == ObjectFile::eTypeDynamicLinker)
704         return true;
705     else
706         return false;
707 }
708 
709 bool
710 PlatformDarwin::x86GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
711 {
712     ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
713     if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h)
714     {
715         switch (idx)
716         {
717             case 0:
718                 arch = host_arch;
719                 return true;
720 
721             case 1:
722                 arch.SetTriple("x86_64-apple-macosx");
723                 return true;
724 
725             case 2:
726                 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
727                 return true;
728 
729             default: return false;
730         }
731     }
732     else
733     {
734         if (idx == 0)
735         {
736             arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
737             return arch.IsValid();
738         }
739         else if (idx == 1)
740         {
741             ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
742             ArchSpec platform_arch64(HostInfo::GetArchitecture(HostInfo::eArchKind64));
743             if (platform_arch.IsExactMatch(platform_arch64))
744             {
745                 // This macosx platform supports both 32 and 64 bit. Since we already
746                 // returned the 64 bit arch for idx == 0, return the 32 bit arch
747                 // for idx == 1
748                 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
749                 return arch.IsValid();
750             }
751         }
752     }
753     return false;
754 }
755 
756 // The architecture selection rules for arm processors
757 // These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f processor.
758 
759 bool
760 PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
761 {
762     ArchSpec system_arch (GetSystemArchitecture());
763 
764     const ArchSpec::Core system_core = system_arch.GetCore();
765     switch (system_core)
766     {
767     default:
768         switch (idx)
769         {
770             case  0: arch.SetTriple ("arm64-apple-ios");    return true;
771             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
772             case  2: arch.SetTriple ("armv7f-apple-ios");   return true;
773             case  3: arch.SetTriple ("armv7k-apple-ios");   return true;
774             case  4: arch.SetTriple ("armv7s-apple-ios");   return true;
775             case  5: arch.SetTriple ("armv7m-apple-ios");   return true;
776             case  6: arch.SetTriple ("armv7em-apple-ios");  return true;
777             case  7: arch.SetTriple ("armv6m-apple-ios");   return true;
778             case  8: arch.SetTriple ("armv6-apple-ios");    return true;
779             case  9: arch.SetTriple ("armv5-apple-ios");    return true;
780             case 10: arch.SetTriple ("armv4-apple-ios");    return true;
781             case 11: arch.SetTriple ("arm-apple-ios");      return true;
782             case 12: arch.SetTriple ("thumbv7-apple-ios");  return true;
783             case 13: arch.SetTriple ("thumbv7f-apple-ios"); return true;
784             case 14: arch.SetTriple ("thumbv7k-apple-ios"); return true;
785             case 15: arch.SetTriple ("thumbv7s-apple-ios"); return true;
786             case 16: arch.SetTriple ("thumbv7m-apple-ios"); return true;
787             case 17: arch.SetTriple ("thumbv7em-apple-ios"); return true;
788             case 18: arch.SetTriple ("thumbv6m-apple-ios"); return true;
789             case 19: arch.SetTriple ("thumbv6-apple-ios");  return true;
790             case 20: arch.SetTriple ("thumbv5-apple-ios");  return true;
791             case 21: arch.SetTriple ("thumbv4t-apple-ios"); return true;
792             case 22: arch.SetTriple ("thumb-apple-ios");    return true;
793             default: break;
794         }
795         break;
796 
797     case ArchSpec::eCore_arm_arm64:
798         switch (idx)
799         {
800             case  0: arch.SetTriple ("arm64-apple-ios");   return true;
801             case  1: arch.SetTriple ("armv7s-apple-ios");   return true;
802             case  2: arch.SetTriple ("armv7f-apple-ios");   return true;
803             case  3: arch.SetTriple ("armv7m-apple-ios");   return true;
804             case  4: arch.SetTriple ("armv7em-apple-ios");  return true;
805             case  5: arch.SetTriple ("armv7-apple-ios");    return true;
806             case  6: arch.SetTriple ("armv6m-apple-ios");   return true;
807             case  7: arch.SetTriple ("armv6-apple-ios");    return true;
808             case  8: arch.SetTriple ("armv5-apple-ios");    return true;
809             case  9: arch.SetTriple ("armv4-apple-ios");    return true;
810             case 10: arch.SetTriple ("arm-apple-ios");      return true;
811             case 11: arch.SetTriple ("thumbv7-apple-ios");  return true;
812             case 12: arch.SetTriple ("thumbv7f-apple-ios"); return true;
813             case 13: arch.SetTriple ("thumbv7k-apple-ios"); return true;
814             case 14: arch.SetTriple ("thumbv7s-apple-ios"); return true;
815             case 15: arch.SetTriple ("thumbv7m-apple-ios"); return true;
816             case 16: arch.SetTriple ("thumbv7em-apple-ios"); return true;
817             case 17: arch.SetTriple ("thumbv6m-apple-ios"); return true;
818             case 18: arch.SetTriple ("thumbv6-apple-ios");  return true;
819             case 19: arch.SetTriple ("thumbv5-apple-ios");  return true;
820             case 20: arch.SetTriple ("thumbv4t-apple-ios"); return true;
821             case 21: arch.SetTriple ("thumb-apple-ios");    return true;
822         default: break;
823         }
824         break;
825 
826     case ArchSpec::eCore_arm_armv7f:
827         switch (idx)
828         {
829             case  0: arch.SetTriple ("armv7f-apple-ios");   return true;
830             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
831             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
832             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
833             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
834             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
835             case  6: arch.SetTriple ("arm-apple-ios");      return true;
836             case  7: arch.SetTriple ("thumbv7f-apple-ios"); return true;
837             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
838             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
839             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
840             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
841             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
842             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
843             default: break;
844         }
845         break;
846 
847     case ArchSpec::eCore_arm_armv7k:
848         switch (idx)
849         {
850             case  0: arch.SetTriple ("armv7k-apple-ios");   return true;
851             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
852             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
853             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
854             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
855             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
856             case  6: arch.SetTriple ("arm-apple-ios");      return true;
857             case  7: arch.SetTriple ("thumbv7k-apple-ios"); return true;
858             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
859             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
860             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
861             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
862             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
863             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
864             default: break;
865         }
866         break;
867 
868     case ArchSpec::eCore_arm_armv7s:
869         switch (idx)
870         {
871             case  0: arch.SetTriple ("armv7s-apple-ios");   return true;
872             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
873             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
874             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
875             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
876             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
877             case  6: arch.SetTriple ("arm-apple-ios");      return true;
878             case  7: arch.SetTriple ("thumbv7s-apple-ios"); return true;
879             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
880             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
881             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
882             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
883             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
884             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
885             default: break;
886         }
887         break;
888 
889     case ArchSpec::eCore_arm_armv7m:
890         switch (idx)
891         {
892             case  0: arch.SetTriple ("armv7m-apple-ios");   return true;
893             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
894             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
895             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
896             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
897             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
898             case  6: arch.SetTriple ("arm-apple-ios");      return true;
899             case  7: arch.SetTriple ("thumbv7m-apple-ios"); return true;
900             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
901             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
902             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
903             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
904             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
905             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
906             default: break;
907         }
908         break;
909 
910     case ArchSpec::eCore_arm_armv7em:
911         switch (idx)
912         {
913             case  0: arch.SetTriple ("armv7em-apple-ios");  return true;
914             case  1: arch.SetTriple ("armv7-apple-ios");    return true;
915             case  2: arch.SetTriple ("armv6m-apple-ios");   return true;
916             case  3: arch.SetTriple ("armv6-apple-ios");    return true;
917             case  4: arch.SetTriple ("armv5-apple-ios");    return true;
918             case  5: arch.SetTriple ("armv4-apple-ios");    return true;
919             case  6: arch.SetTriple ("arm-apple-ios");      return true;
920             case  7: arch.SetTriple ("thumbv7em-apple-ios"); return true;
921             case  8: arch.SetTriple ("thumbv7-apple-ios");  return true;
922             case  9: arch.SetTriple ("thumbv6m-apple-ios"); return true;
923             case 10: arch.SetTriple ("thumbv6-apple-ios");  return true;
924             case 11: arch.SetTriple ("thumbv5-apple-ios");  return true;
925             case 12: arch.SetTriple ("thumbv4t-apple-ios"); return true;
926             case 13: arch.SetTriple ("thumb-apple-ios");    return true;
927             default: break;
928         }
929         break;
930 
931     case ArchSpec::eCore_arm_armv7:
932         switch (idx)
933         {
934             case  0: arch.SetTriple ("armv7-apple-ios");    return true;
935             case  1: arch.SetTriple ("armv6m-apple-ios");   return true;
936             case  2: arch.SetTriple ("armv6-apple-ios");    return true;
937             case  3: arch.SetTriple ("armv5-apple-ios");    return true;
938             case  4: arch.SetTriple ("armv4-apple-ios");    return true;
939             case  5: arch.SetTriple ("arm-apple-ios");      return true;
940             case  6: arch.SetTriple ("thumbv7-apple-ios");  return true;
941             case  7: arch.SetTriple ("thumbv6m-apple-ios"); return true;
942             case  8: arch.SetTriple ("thumbv6-apple-ios");  return true;
943             case  9: arch.SetTriple ("thumbv5-apple-ios");  return true;
944             case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
945             case 11: arch.SetTriple ("thumb-apple-ios");    return true;
946             default: break;
947         }
948         break;
949 
950     case ArchSpec::eCore_arm_armv6m:
951         switch (idx)
952         {
953             case 0: arch.SetTriple ("armv6m-apple-ios");   return true;
954             case 1: arch.SetTriple ("armv6-apple-ios");    return true;
955             case 2: arch.SetTriple ("armv5-apple-ios");    return true;
956             case 3: arch.SetTriple ("armv4-apple-ios");    return true;
957             case 4: arch.SetTriple ("arm-apple-ios");      return true;
958             case 5: arch.SetTriple ("thumbv6m-apple-ios"); return true;
959             case 6: arch.SetTriple ("thumbv6-apple-ios");  return true;
960             case 7: arch.SetTriple ("thumbv5-apple-ios");  return true;
961             case 8: arch.SetTriple ("thumbv4t-apple-ios"); return true;
962             case 9: arch.SetTriple ("thumb-apple-ios");    return true;
963             default: break;
964         }
965         break;
966 
967     case ArchSpec::eCore_arm_armv6:
968         switch (idx)
969         {
970             case 0: arch.SetTriple ("armv6-apple-ios");    return true;
971             case 1: arch.SetTriple ("armv5-apple-ios");    return true;
972             case 2: arch.SetTriple ("armv4-apple-ios");    return true;
973             case 3: arch.SetTriple ("arm-apple-ios");      return true;
974             case 4: arch.SetTriple ("thumbv6-apple-ios");  return true;
975             case 5: arch.SetTriple ("thumbv5-apple-ios");  return true;
976             case 6: arch.SetTriple ("thumbv4t-apple-ios"); return true;
977             case 7: arch.SetTriple ("thumb-apple-ios");    return true;
978             default: break;
979         }
980         break;
981 
982     case ArchSpec::eCore_arm_armv5:
983         switch (idx)
984         {
985             case 0: arch.SetTriple ("armv5-apple-ios");    return true;
986             case 1: arch.SetTriple ("armv4-apple-ios");    return true;
987             case 2: arch.SetTriple ("arm-apple-ios");      return true;
988             case 3: arch.SetTriple ("thumbv5-apple-ios");  return true;
989             case 4: arch.SetTriple ("thumbv4t-apple-ios"); return true;
990             case 5: arch.SetTriple ("thumb-apple-ios");    return true;
991             default: break;
992         }
993         break;
994 
995     case ArchSpec::eCore_arm_armv4:
996         switch (idx)
997         {
998             case 0: arch.SetTriple ("armv4-apple-ios");    return true;
999             case 1: arch.SetTriple ("arm-apple-ios");      return true;
1000             case 2: arch.SetTriple ("thumbv4t-apple-ios"); return true;
1001             case 3: arch.SetTriple ("thumb-apple-ios");    return true;
1002             default: break;
1003         }
1004         break;
1005     }
1006     arch.Clear();
1007     return false;
1008 }
1009 
1010 
1011 const char *
1012 PlatformDarwin::GetDeveloperDirectory()
1013 {
1014     Mutex::Locker locker (m_mutex);
1015     if (m_developer_directory.empty())
1016     {
1017         bool developer_dir_path_valid = false;
1018         char developer_dir_path[PATH_MAX];
1019         FileSpec temp_file_spec;
1020         if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, temp_file_spec))
1021         {
1022             if (temp_file_spec.GetPath (developer_dir_path, sizeof(developer_dir_path)))
1023             {
1024                 char *shared_frameworks = strstr (developer_dir_path, "/SharedFrameworks/LLDB.framework");
1025                 if (shared_frameworks)
1026                 {
1027                     ::snprintf (shared_frameworks,
1028                                 sizeof(developer_dir_path) - (shared_frameworks - developer_dir_path),
1029                                 "/Developer");
1030                     developer_dir_path_valid = true;
1031                 }
1032                 else
1033                 {
1034                     char *lib_priv_frameworks = strstr (developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework");
1035                     if (lib_priv_frameworks)
1036                     {
1037                         *lib_priv_frameworks = '\0';
1038                         developer_dir_path_valid = true;
1039                     }
1040                 }
1041             }
1042         }
1043 
1044         if (!developer_dir_path_valid)
1045         {
1046             std::string xcode_dir_path;
1047             const char *xcode_select_prefix_dir = getenv ("XCODE_SELECT_PREFIX_DIR");
1048             if (xcode_select_prefix_dir)
1049                 xcode_dir_path.append (xcode_select_prefix_dir);
1050             xcode_dir_path.append ("/usr/share/xcode-select/xcode_dir_path");
1051             temp_file_spec.SetFile(xcode_dir_path.c_str(), false);
1052             size_t bytes_read = temp_file_spec.ReadFileContents(0, developer_dir_path, sizeof(developer_dir_path), NULL);
1053             if (bytes_read > 0)
1054             {
1055                 developer_dir_path[bytes_read] = '\0';
1056                 while (developer_dir_path[bytes_read-1] == '\r' ||
1057                        developer_dir_path[bytes_read-1] == '\n')
1058                     developer_dir_path[--bytes_read] = '\0';
1059                 developer_dir_path_valid = true;
1060             }
1061         }
1062 
1063         if (!developer_dir_path_valid)
1064         {
1065             FileSpec xcode_select_cmd ("/usr/bin/xcode-select", false);
1066             if (xcode_select_cmd.Exists())
1067             {
1068                 int exit_status = -1;
1069                 int signo = -1;
1070                 std::string command_output;
1071                 Error error = Host::RunShellCommand ("/usr/bin/xcode-select --print-path",
1072                                                      NULL,                                 // current working directory
1073                                                      &exit_status,
1074                                                      &signo,
1075                                                      &command_output,
1076                                                      2,                                     // short timeout
1077                                                      false);                                // don't run in a shell
1078                 if (error.Success() && exit_status == 0 && !command_output.empty())
1079                 {
1080                     const char *cmd_output_ptr = command_output.c_str();
1081                     developer_dir_path[sizeof (developer_dir_path) - 1] = '\0';
1082                     size_t i;
1083                     for (i = 0; i < sizeof (developer_dir_path) - 1; i++)
1084                     {
1085                         if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' || cmd_output_ptr[i] == '\0')
1086                             break;
1087                         developer_dir_path[i] = cmd_output_ptr[i];
1088                     }
1089                     developer_dir_path[i] = '\0';
1090 
1091                     FileSpec devel_dir (developer_dir_path, false);
1092                     if (devel_dir.Exists() && devel_dir.IsDirectory())
1093                     {
1094                         developer_dir_path_valid = true;
1095                     }
1096                 }
1097             }
1098         }
1099 
1100         if (developer_dir_path_valid)
1101         {
1102             temp_file_spec.SetFile (developer_dir_path, false);
1103             if (temp_file_spec.Exists())
1104             {
1105                 m_developer_directory.assign (developer_dir_path);
1106                 return m_developer_directory.c_str();
1107             }
1108         }
1109         // Assign a single NULL character so we know we tried to find the device
1110         // support directory and we don't keep trying to find it over and over.
1111         m_developer_directory.assign (1, '\0');
1112     }
1113 
1114     // We should have put a single NULL character into m_developer_directory
1115     // or it should have a valid path if the code gets here
1116     assert (m_developer_directory.empty() == false);
1117     if (m_developer_directory[0])
1118         return m_developer_directory.c_str();
1119     return NULL;
1120 }
1121 
1122 
1123 BreakpointSP
1124 PlatformDarwin::SetThreadCreationBreakpoint (Target &target)
1125 {
1126     BreakpointSP bp_sp;
1127     static const char *g_bp_names[] =
1128     {
1129         "start_wqthread",
1130         "_pthread_wqthread",
1131         "_pthread_start",
1132     };
1133 
1134     static const char *g_bp_modules[] =
1135     {
1136         "libsystem_c.dylib",
1137         "libSystem.B.dylib"
1138     };
1139 
1140     FileSpecList bp_modules;
1141     for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++)
1142     {
1143         const char *bp_module = g_bp_modules[i];
1144         bp_modules.Append(FileSpec(bp_module, false));
1145     }
1146 
1147     bool internal = true;
1148     bool hardware = false;
1149     LazyBool skip_prologue = eLazyBoolNo;
1150     bp_sp = target.CreateBreakpoint (&bp_modules,
1151                                      NULL,
1152                                      g_bp_names,
1153                                      llvm::array_lengthof(g_bp_names),
1154                                      eFunctionNameTypeFull,
1155                                      eLanguageTypeUnknown,
1156                                      skip_prologue,
1157                                      internal,
1158                                      hardware);
1159     bp_sp->SetBreakpointKind("thread-creation");
1160 
1161     return bp_sp;
1162 }
1163 
1164 
1165 int32_t
1166 PlatformDarwin::GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info)
1167 {
1168     const FileSpec &shell = launch_info.GetShell();
1169     if (!shell)
1170         return 1;
1171 
1172     std::string shell_string = shell.GetPath();
1173     const char *shell_name = strrchr (shell_string.c_str(), '/');
1174     if (shell_name == NULL)
1175         shell_name = shell_string.c_str();
1176     else
1177         shell_name++;
1178 
1179     if (strcmp (shell_name, "sh") == 0)
1180     {
1181         // /bin/sh re-exec's itself as /bin/bash requiring another resume.
1182         // But it only does this if the COMMAND_MODE environment variable
1183         // is set to "legacy".
1184         const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector();
1185         if (envp != NULL)
1186         {
1187             for (int i = 0; envp[i] != NULL; i++)
1188             {
1189                 if (strcmp (envp[i], "COMMAND_MODE=legacy" ) == 0)
1190                     return 2;
1191             }
1192         }
1193         return 1;
1194     }
1195     else if (strcmp (shell_name, "csh") == 0
1196             || strcmp (shell_name, "tcsh") == 0
1197             || strcmp (shell_name, "zsh") == 0)
1198     {
1199         // csh and tcsh always seem to re-exec themselves.
1200         return 2;
1201     }
1202     else
1203         return 1;
1204 }
1205 
1206 void
1207 PlatformDarwin::CalculateTrapHandlerSymbolNames ()
1208 {
1209     m_trap_handlers.push_back (ConstString ("_sigtramp"));
1210 }
1211 
1212 
1213 static const char *const sdk_strings[] = {
1214     "MacOSX",
1215     "iPhoneSimulator",
1216     "iPhoneOS",
1217 };
1218 
1219 static FileSpec
1220 CheckPathForXcode(const FileSpec &fspec)
1221 {
1222     if (fspec.Exists())
1223     {
1224         const char substr[] = ".app/Contents/";
1225 
1226         std::string path_to_shlib = fspec.GetPath();
1227         size_t pos = path_to_shlib.rfind(substr);
1228         if (pos != std::string::npos)
1229         {
1230             path_to_shlib.erase(pos + strlen(substr));
1231             FileSpec ret (path_to_shlib.c_str(), false);
1232 
1233             FileSpec xcode_binary_path = ret;
1234             xcode_binary_path.AppendPathComponent("MacOS");
1235             xcode_binary_path.AppendPathComponent("Xcode");
1236 
1237             if (xcode_binary_path.Exists())
1238             {
1239                 return ret;
1240             }
1241         }
1242     }
1243     return FileSpec();
1244 }
1245 
1246 static FileSpec
1247 GetXcodeContentsPath ()
1248 {
1249     static FileSpec g_xcode_filespec;
1250     static std::once_flag g_once_flag;
1251     std::call_once(g_once_flag, []() {
1252 
1253 
1254         FileSpec fspec;
1255 
1256         // First get the program file spec. If lldb.so or LLDB.framework is running
1257         // in a program and that program is Xcode, the path returned with be the path
1258         // to Xcode.app/Contents/MacOS/Xcode, so this will be the correct Xcode to use.
1259         fspec = HostInfo::GetProgramFileSpec();
1260 
1261         if (fspec)
1262         {
1263             // Ignore the current binary if it is python.
1264             std::string basename_lower = fspec.GetFilename ().GetCString ();
1265             std::transform(basename_lower.begin (), basename_lower.end (), basename_lower.begin (), tolower);
1266             if (basename_lower != "python")
1267             {
1268                 g_xcode_filespec = CheckPathForXcode(fspec);
1269             }
1270         }
1271 
1272         // Next check DEVELOPER_DIR environment variable
1273         if (!g_xcode_filespec)
1274         {
1275             const char *developer_dir_env_var = getenv("DEVELOPER_DIR");
1276             if (developer_dir_env_var && developer_dir_env_var[0])
1277             {
1278                 g_xcode_filespec = CheckPathForXcode(FileSpec(developer_dir_env_var, true));
1279             }
1280 
1281             // Fall back to using "xcrun" to find the selected Xcode
1282             if (!g_xcode_filespec)
1283             {
1284                 int status = 0;
1285                 int signo = 0;
1286                 std::string output;
1287                 const char *command = "/usr/bin/xcode-select -p";
1288                 lldb_private::Error error = Host::RunShellCommand (command,   // shell command to run
1289                                                                    NULL,      // current working directory
1290                                                                    &status,   // Put the exit status of the process in here
1291                                                                    &signo,    // Put the signal that caused the process to exit in here
1292                                                                    &output,   // Get the output from the command and place it in this string
1293                                                                    3);        // Timeout in seconds to wait for shell program to finish
1294                 if (status == 0 && !output.empty())
1295                 {
1296                     size_t first_non_newline = output.find_last_not_of("\r\n");
1297                     if (first_non_newline != std::string::npos)
1298                     {
1299                         output.erase(first_non_newline+1);
1300                     }
1301                     output.append("/..");
1302 
1303                     g_xcode_filespec = CheckPathForXcode(FileSpec(output.c_str(), false));
1304                 }
1305             }
1306         }
1307     });
1308 
1309     return g_xcode_filespec;
1310 }
1311 
1312 bool
1313 PlatformDarwin::SDKSupportsModules (SDKType sdk_type, uint32_t major, uint32_t minor, uint32_t micro)
1314 {
1315     switch (sdk_type)
1316     {
1317         case SDKType::MacOSX:
1318             if (major > 10 || (major == 10 && minor >= 10))
1319                 return true;
1320             break;
1321         case SDKType::iPhoneOS:
1322         case SDKType::iPhoneSimulator:
1323             if (major >= 8)
1324                 return true;
1325             break;
1326     }
1327 
1328     return false;
1329 }
1330 
1331 bool
1332 PlatformDarwin::SDKSupportsModules (SDKType desired_type, const FileSpec &sdk_path)
1333 {
1334     ConstString last_path_component = sdk_path.GetLastPathComponent();
1335 
1336     if (last_path_component)
1337     {
1338         const llvm::StringRef sdk_name = last_path_component.GetStringRef();
1339 
1340         llvm::StringRef version_part;
1341 
1342         if (sdk_name.startswith(sdk_strings[(int)desired_type]))
1343         {
1344             version_part = sdk_name.drop_front(strlen(sdk_strings[(int)desired_type]));
1345         }
1346         else
1347         {
1348             return false;
1349         }
1350 
1351         const size_t major_dot_offset = version_part.find('.');
1352         if (major_dot_offset == llvm::StringRef::npos)
1353             return false;
1354 
1355         const llvm::StringRef major_version = version_part.slice(0, major_dot_offset);
1356         const llvm::StringRef minor_part = version_part.drop_front(major_dot_offset + 1);
1357 
1358         const size_t minor_dot_offset = minor_part.find('.');
1359         if (minor_dot_offset == llvm::StringRef::npos)
1360             return false;
1361 
1362         const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset);
1363 
1364         unsigned int major = 0;
1365         unsigned int minor = 0;
1366         unsigned int micro = 0;
1367 
1368         if (major_version.getAsInteger(10, major))
1369             return false;
1370 
1371         if (minor_version.getAsInteger(10, minor))
1372             return false;
1373 
1374         return SDKSupportsModules(desired_type, major, minor, micro);
1375     }
1376 
1377     return false;
1378 }
1379 
1380 FileSpec::EnumerateDirectoryResult
1381 PlatformDarwin::DirectoryEnumerator(void *baton,
1382                                     FileSpec::FileType file_type,
1383                                     const FileSpec &spec)
1384 {
1385     SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo*>(baton);
1386 
1387     if (SDKSupportsModules(enumerator_info->sdk_type, spec))
1388     {
1389         enumerator_info->found_path = spec;
1390         return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1391     }
1392 
1393     return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1394 }
1395 
1396 FileSpec
1397 PlatformDarwin::FindSDKInXcodeForModules (SDKType sdk_type,
1398                                           const FileSpec &sdks_spec)
1399 {
1400     // Look inside Xcode for the required installed iOS SDK version
1401 
1402     if (!sdks_spec.IsDirectory())
1403         return FileSpec();
1404 
1405     const bool find_directories = true;
1406     const bool find_files = false;
1407     const bool find_other = true; // include symlinks
1408 
1409     SDKEnumeratorInfo enumerator_info;
1410 
1411     enumerator_info.sdk_type = sdk_type;
1412 
1413     FileSpec::EnumerateDirectory(sdks_spec.GetPath().c_str(),
1414                                  find_directories,
1415                                  find_files,
1416                                  find_other,
1417                                  DirectoryEnumerator,
1418                                  &enumerator_info);
1419 
1420     if (enumerator_info.found_path.IsDirectory())
1421         return enumerator_info.found_path;
1422     else
1423         return FileSpec();
1424 }
1425 
1426 FileSpec
1427 PlatformDarwin::GetSDKDirectoryForModules (SDKType sdk_type)
1428 {
1429     switch (sdk_type)
1430     {
1431         case SDKType::MacOSX:
1432         case SDKType::iPhoneSimulator:
1433         case SDKType::iPhoneOS:
1434             break;
1435     }
1436 
1437     FileSpec sdks_spec = GetXcodeContentsPath();
1438     sdks_spec.AppendPathComponent("Developer");
1439     sdks_spec.AppendPathComponent("Platforms");
1440 
1441     switch (sdk_type)
1442     {
1443         case SDKType::MacOSX:
1444             sdks_spec.AppendPathComponent("MacOSX.platform");
1445             break;
1446         case SDKType::iPhoneSimulator:
1447             sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
1448             break;
1449         case SDKType::iPhoneOS:
1450             sdks_spec.AppendPathComponent("iPhoneOS.platform");
1451             break;
1452     }
1453 
1454     sdks_spec.AppendPathComponent("Developer");
1455     sdks_spec.AppendPathComponent("SDKs");
1456 
1457     if (sdk_type == SDKType::MacOSX)
1458     {
1459         uint32_t major = 0;
1460         uint32_t minor = 0;
1461         uint32_t micro = 0;
1462 
1463         if (HostInfo::GetOSVersion(major, minor, micro))
1464         {
1465             if (SDKSupportsModules(SDKType::MacOSX, major, minor, micro))
1466             {
1467                 // We slightly prefer the exact SDK for this machine.  See if it is there.
1468 
1469                 FileSpec native_sdk_spec = sdks_spec;
1470                 StreamString native_sdk_name;
1471                 native_sdk_name.Printf("MacOSX%u.%u.sdk", major, minor);
1472                 native_sdk_spec.AppendPathComponent(native_sdk_name.GetString().c_str());
1473 
1474                 if (native_sdk_spec.Exists())
1475                 {
1476                     return native_sdk_spec;
1477                 }
1478             }
1479         }
1480     }
1481 
1482     return FindSDKInXcodeForModules(sdk_type, sdks_spec);
1483 }
1484 
1485 void
1486 PlatformDarwin::AddClangModuleCompilationOptionsForSDKType (Target *target, std::vector<std::string> &options, SDKType sdk_type)
1487 {
1488     const std::vector<std::string> apple_arguments =
1489     {
1490         "-x", "objective-c++",
1491         "-fobjc-arc",
1492         "-fblocks",
1493         "-D_ISO646_H",
1494         "-D__ISO646_H"
1495     };
1496 
1497     options.insert(options.end(),
1498                    apple_arguments.begin(),
1499                    apple_arguments.end());
1500 
1501     StreamString minimum_version_option;
1502     uint32_t versions[3] = { 0, 0, 0 };
1503     bool use_current_os_version = false;
1504     switch (sdk_type)
1505     {
1506         case SDKType::iPhoneOS:
1507 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
1508             use_current_os_version = true;
1509 #else
1510             use_current_os_version = false;
1511 #endif
1512             break;
1513 
1514         case SDKType::iPhoneSimulator:
1515             use_current_os_version = false;
1516             break;
1517 
1518         case SDKType::MacOSX:
1519 #if defined (__i386__) || defined (__x86_64__)
1520             use_current_os_version = true;
1521 #else
1522             use_current_os_version = false;
1523 #endif
1524             break;
1525     }
1526 
1527     bool versions_valid = false;
1528     if (use_current_os_version)
1529         versions_valid = GetOSVersion(versions[0], versions[1], versions[2]);
1530     else if (target)
1531     {
1532         // Our OS doesn't match our executable so we need to get the min OS version from the object file
1533         ModuleSP exe_module_sp = target->GetExecutableModule();
1534         if (exe_module_sp)
1535         {
1536             ObjectFile *object_file = exe_module_sp->GetObjectFile();
1537             if (object_file)
1538                 versions_valid = object_file->GetMinimumOSVersion(versions, 3) > 0;
1539         }
1540     }
1541     // Only add the version-min options if we got a version from somewhere
1542     if (versions_valid && versions[0] != UINT32_MAX)
1543     {
1544         // Make any invalid versions be zero if needed
1545         if (versions[1] == UINT32_MAX)
1546             versions[1] = 0;
1547         if (versions[2] == UINT32_MAX)
1548             versions[2] = 0;
1549 
1550         switch (sdk_type)
1551         {
1552         case SDKType::iPhoneOS:
1553             minimum_version_option.PutCString("-mios-version-min=");
1554             minimum_version_option.PutCString(clang::VersionTuple(versions[0], versions[1], versions[2]).getAsString().c_str());
1555             break;
1556         case SDKType::iPhoneSimulator:
1557             minimum_version_option.PutCString("-mios-simulator-version-min=");
1558             minimum_version_option.PutCString(clang::VersionTuple(versions[0], versions[1], versions[2]).getAsString().c_str());
1559             break;
1560         case SDKType::MacOSX:
1561             minimum_version_option.PutCString("-mmacosx-version-min=");
1562             minimum_version_option.PutCString(clang::VersionTuple(versions[0], versions[1], versions[2]).getAsString().c_str());
1563         }
1564         options.push_back(minimum_version_option.GetString());
1565     }
1566 
1567     FileSpec sysroot_spec;
1568     // Scope for mutex locker below
1569     {
1570         Mutex::Locker locker (m_mutex);
1571         sysroot_spec = GetSDKDirectoryForModules(sdk_type);
1572     }
1573 
1574     if (sysroot_spec.IsDirectory())
1575     {
1576         options.push_back("-isysroot");
1577         options.push_back(sysroot_spec.GetPath());
1578     }
1579 }
1580 
1581 ConstString
1582 PlatformDarwin::GetFullNameForDylib (ConstString basename)
1583 {
1584     if (basename.IsEmpty())
1585         return basename;
1586 
1587     StreamString stream;
1588     stream.Printf("lib%s.dylib", basename.GetCString());
1589     return ConstString(stream.GetData());
1590 }
1591 
1592 bool
1593 PlatformDarwin::GetOSVersion (uint32_t &major,
1594                               uint32_t &minor,
1595                               uint32_t &update,
1596                               Process *process)
1597 {
1598     if (process && strstr(GetPluginName().GetCString(), "-simulator"))
1599     {
1600         lldb_private::ProcessInstanceInfo proc_info;
1601         if (Host::GetProcessInfo(process->GetID(), proc_info))
1602         {
1603             Args &env = proc_info.GetEnvironmentEntries();
1604             const size_t n = env.GetArgumentCount();
1605             const llvm::StringRef k_runtime_version("SIMULATOR_RUNTIME_VERSION=");
1606             const llvm::StringRef k_dyld_root_path("DYLD_ROOT_PATH=");
1607             std::string dyld_root_path;
1608 
1609             for (size_t i=0; i<n; ++i)
1610             {
1611                 const char *env_cstr = env.GetArgumentAtIndex(i);
1612                 if (env_cstr)
1613                 {
1614                     llvm::StringRef env_str(env_cstr);
1615                     if (env_str.startswith(k_runtime_version))
1616                     {
1617                         llvm::StringRef version_str(env_str.substr(k_runtime_version.size()));
1618                         Args::StringToVersion (version_str.data(), major, minor, update);
1619                         if (major != UINT32_MAX)
1620                             return true;
1621                     }
1622                     else if (env_str.startswith(k_dyld_root_path))
1623                     {
1624                         dyld_root_path = env_str.substr(k_dyld_root_path.size()).str();
1625                     }
1626                 }
1627             }
1628 
1629             if (!dyld_root_path.empty())
1630             {
1631                 dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
1632                 ApplePropertyList system_version_plist(dyld_root_path.c_str());
1633                 std::string product_version;
1634                 if (system_version_plist.GetValueAsString("ProductVersion", product_version))
1635                 {
1636                     Args::StringToVersion (product_version.c_str(), major, minor, update);
1637                     return major != UINT32_MAX;
1638                 }
1639             }
1640 
1641         }
1642         // For simulator platforms, do NOT call back through Platform::GetOSVersion()
1643         // as it might call Process::GetHostOSVersion() which we don't want as it will be
1644         // incorrect
1645         return false;
1646     }
1647 
1648     return Platform::GetOSVersion(major, minor, update, process);
1649 }
1650 
1651 lldb_private::FileSpec
1652 PlatformDarwin::LocateExecutable (const char *basename)
1653 {
1654     // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled in with
1655     // any executable directories that should be searched.
1656     static std::vector<FileSpec> g_executable_dirs;
1657 
1658     // Find the global list of directories that we will search for
1659     // executables once so we don't keep doing the work over and over.
1660     static std::once_flag g_once_flag;
1661     std::call_once(g_once_flag,  []() {
1662 
1663         // When locating executables, trust the DEVELOPER_DIR first if it is set
1664         FileSpec xcode_contents_dir = GetXcodeContentsPath();
1665         if (xcode_contents_dir)
1666         {
1667             FileSpec xcode_lldb_resources = xcode_contents_dir;
1668             xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
1669             xcode_lldb_resources.AppendPathComponent("LLDB.framework");
1670             xcode_lldb_resources.AppendPathComponent("Resources");
1671             if (xcode_lldb_resources.Exists())
1672             {
1673                 FileSpec dir;
1674                 dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
1675                 g_executable_dirs.push_back(dir);
1676             }
1677         }
1678     });
1679 
1680     // Now search the global list of executable directories for the executable we
1681     // are looking for
1682     for (const auto &executable_dir : g_executable_dirs)
1683     {
1684         FileSpec executable_file;
1685         executable_file.GetDirectory() = executable_dir.GetDirectory();
1686         executable_file.GetFilename().SetCString(basename);
1687         if (executable_file.Exists())
1688             return executable_file;
1689     }
1690 
1691     return FileSpec();
1692 }
1693