1 //===-- PlatformRemoteiOS.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 "PlatformRemoteiOS.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/ArchSpec.h"
18 #include "lldb/Core/Error.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/ModuleList.h"
22 #include "lldb/Core/ModuleSpec.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Host/FileSpec.h"
26 #include "lldb/Host/Host.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/Target.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 PlatformRemoteiOS::SDKDirectoryInfo::SDKDirectoryInfo(
34     const lldb_private::FileSpec &sdk_dir)
35     : directory(sdk_dir), build(), version_major(0), version_minor(0),
36       version_update(0), user_cached(false) {
37   const char *dirname_cstr = sdk_dir.GetFilename().GetCString();
38   const char *pos = Args::StringToVersion(dirname_cstr, version_major,
39                                           version_minor, version_update);
40 
41   if (pos && pos[0] == ' ' && pos[1] == '(') {
42     const char *build_start = pos + 2;
43     const char *end_paren = strchr(build_start, ')');
44     if (end_paren && build_start < end_paren)
45       build.SetCStringWithLength(build_start, end_paren - build_start);
46   }
47 }
48 
49 //------------------------------------------------------------------
50 // Static Variables
51 //------------------------------------------------------------------
52 static uint32_t g_initialize_count = 0;
53 
54 //------------------------------------------------------------------
55 // Static Functions
56 //------------------------------------------------------------------
57 void PlatformRemoteiOS::Initialize() {
58   PlatformDarwin::Initialize();
59 
60   if (g_initialize_count++ == 0) {
61     PluginManager::RegisterPlugin(PlatformRemoteiOS::GetPluginNameStatic(),
62                                   PlatformRemoteiOS::GetDescriptionStatic(),
63                                   PlatformRemoteiOS::CreateInstance);
64   }
65 }
66 
67 void PlatformRemoteiOS::Terminate() {
68   if (g_initialize_count > 0) {
69     if (--g_initialize_count == 0) {
70       PluginManager::UnregisterPlugin(PlatformRemoteiOS::CreateInstance);
71     }
72   }
73 
74   PlatformDarwin::Terminate();
75 }
76 
77 PlatformSP PlatformRemoteiOS::CreateInstance(bool force, const ArchSpec *arch) {
78   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
79   if (log) {
80     const char *arch_name;
81     if (arch && arch->GetArchitectureName())
82       arch_name = arch->GetArchitectureName();
83     else
84       arch_name = "<null>";
85 
86     const char *triple_cstr =
87         arch ? arch->GetTriple().getTriple().c_str() : "<null>";
88 
89     log->Printf("PlatformRemoteiOS::%s(force=%s, arch={%s,%s})", __FUNCTION__,
90                 force ? "true" : "false", arch_name, triple_cstr);
91   }
92 
93   bool create = force;
94   if (create == false && arch && arch->IsValid()) {
95     switch (arch->GetMachine()) {
96     case llvm::Triple::arm:
97     case llvm::Triple::aarch64:
98     case llvm::Triple::thumb: {
99       const llvm::Triple &triple = arch->GetTriple();
100       llvm::Triple::VendorType vendor = triple.getVendor();
101       switch (vendor) {
102       case llvm::Triple::Apple:
103         create = true;
104         break;
105 
106 #if defined(__APPLE__)
107       // Only accept "unknown" for the vendor if the host is Apple and
108       // it "unknown" wasn't specified (it was just returned because it
109       // was NOT specified)
110       case llvm::Triple::UnknownArch:
111         create = !arch->TripleVendorWasSpecified();
112         break;
113 
114 #endif
115       default:
116         break;
117       }
118       if (create) {
119         switch (triple.getOS()) {
120         case llvm::Triple::Darwin: // Deprecated, but still support Darwin for
121                                    // historical reasons
122         case llvm::Triple::IOS:    // This is the right triple value for iOS
123                                    // debugging
124           break;
125 
126         default:
127           create = false;
128           break;
129         }
130       }
131     } break;
132     default:
133       break;
134     }
135   }
136 
137   if (create) {
138     if (log)
139       log->Printf("PlatformRemoteiOS::%s() creating platform", __FUNCTION__);
140 
141     return lldb::PlatformSP(new PlatformRemoteiOS());
142   }
143 
144   if (log)
145     log->Printf("PlatformRemoteiOS::%s() aborting creation of platform",
146                 __FUNCTION__);
147 
148   return lldb::PlatformSP();
149 }
150 
151 lldb_private::ConstString PlatformRemoteiOS::GetPluginNameStatic() {
152   static ConstString g_name("remote-ios");
153   return g_name;
154 }
155 
156 const char *PlatformRemoteiOS::GetDescriptionStatic() {
157   return "Remote iOS platform plug-in.";
158 }
159 
160 //------------------------------------------------------------------
161 /// Default Constructor
162 //------------------------------------------------------------------
163 PlatformRemoteiOS::PlatformRemoteiOS()
164     : PlatformDarwin(false), // This is a remote platform
165       m_sdk_directory_infos(), m_device_support_directory(),
166       m_device_support_directory_for_os_version(), m_build_update(),
167       m_last_module_sdk_idx(UINT32_MAX),
168       m_connected_module_sdk_idx(UINT32_MAX) {}
169 
170 //------------------------------------------------------------------
171 /// Destructor.
172 ///
173 /// The destructor is virtual since this class is designed to be
174 /// inherited from by the plug-in instance.
175 //------------------------------------------------------------------
176 PlatformRemoteiOS::~PlatformRemoteiOS() {}
177 
178 void PlatformRemoteiOS::GetStatus(Stream &strm) {
179   Platform::GetStatus(strm);
180   const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
181   if (sdk_directory)
182     strm.Printf("  SDK Path: \"%s\"\n", sdk_directory);
183   else
184     strm.PutCString("  SDK Path: error: unable to locate SDK\n");
185 
186   const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
187   for (uint32_t i = 0; i < num_sdk_infos; ++i) {
188     const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
189     strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
190                 sdk_dir_info.directory.GetPath().c_str());
191   }
192 }
193 
194 Error PlatformRemoteiOS::ResolveExecutable(
195     const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
196     const FileSpecList *module_search_paths_ptr) {
197   Error error;
198   // Nothing special to do here, just use the actual file and architecture
199 
200   ModuleSpec resolved_module_spec(ms);
201 
202   // Resolve any executable within a bundle on MacOSX
203   // TODO: verify that this handles shallow bundles, if not then implement one
204   // ourselves
205   Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
206 
207   if (resolved_module_spec.GetFileSpec().Exists()) {
208     if (resolved_module_spec.GetArchitecture().IsValid() ||
209         resolved_module_spec.GetUUID().IsValid()) {
210       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
211                                           NULL, NULL, NULL);
212 
213       if (exe_module_sp && exe_module_sp->GetObjectFile())
214         return error;
215       exe_module_sp.reset();
216     }
217     // No valid architecture was specified or the exact ARM slice wasn't
218     // found so ask the platform for the architectures that we should be
219     // using (in the correct order) and see if we can find a match that way
220     StreamString arch_names;
221     for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
222              idx, resolved_module_spec.GetArchitecture());
223          ++idx) {
224       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
225                                           NULL, NULL, NULL);
226       // Did we find an executable using one of the
227       if (error.Success()) {
228         if (exe_module_sp && exe_module_sp->GetObjectFile())
229           break;
230         else
231           error.SetErrorToGenericError();
232       }
233 
234       if (idx > 0)
235         arch_names.PutCString(", ");
236       arch_names.PutCString(
237           resolved_module_spec.GetArchitecture().GetArchitectureName());
238     }
239 
240     if (error.Fail() || !exe_module_sp) {
241       if (resolved_module_spec.GetFileSpec().Readable()) {
242         error.SetErrorStringWithFormat(
243             "'%s' doesn't contain any '%s' platform architectures: %s",
244             resolved_module_spec.GetFileSpec().GetPath().c_str(),
245             GetPluginName().GetCString(), arch_names.GetString().c_str());
246       } else {
247         error.SetErrorStringWithFormat(
248             "'%s' is not readable",
249             resolved_module_spec.GetFileSpec().GetPath().c_str());
250       }
251     }
252   } else {
253     error.SetErrorStringWithFormat(
254         "'%s' does not exist",
255         resolved_module_spec.GetFileSpec().GetPath().c_str());
256   }
257 
258   return error;
259 }
260 
261 FileSpec::EnumerateDirectoryResult
262 PlatformRemoteiOS::GetContainedFilesIntoVectorOfStringsCallback(
263     void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) {
264   ((PlatformRemoteiOS::SDKDirectoryInfoCollection *)baton)
265       ->push_back(PlatformRemoteiOS::SDKDirectoryInfo(file_spec));
266   return FileSpec::eEnumerateDirectoryResultNext;
267 }
268 
269 bool PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded() {
270   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
271   if (m_sdk_directory_infos.empty()) {
272     // A --sysroot option was supplied - add it to our list of SDKs to check
273     if (m_sdk_sysroot) {
274       FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString(), true);
275       const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
276       m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
277       if (log) {
278         log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded added "
279                     "--sysroot SDK directory %s",
280                     m_sdk_sysroot.GetCString());
281       }
282       return true;
283     }
284     const char *device_support_dir = GetDeviceSupportDirectory();
285     if (log) {
286       log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded Got "
287                   "DeviceSupport directory %s",
288                   device_support_dir);
289     }
290     if (device_support_dir) {
291       const bool find_directories = true;
292       const bool find_files = false;
293       const bool find_other = false;
294 
295       SDKDirectoryInfoCollection builtin_sdk_directory_infos;
296       FileSpec::EnumerateDirectory(m_device_support_directory.c_str(),
297                                    find_directories, find_files, find_other,
298                                    GetContainedFilesIntoVectorOfStringsCallback,
299                                    &builtin_sdk_directory_infos);
300 
301       // Only add SDK directories that have symbols in them, some SDKs only
302       // contain
303       // developer disk images and no symbols, so they aren't useful to us.
304       FileSpec sdk_symbols_symlink_fspec;
305       for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
306         sdk_symbols_symlink_fspec = sdk_directory_info.directory;
307         sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
308         if (sdk_symbols_symlink_fspec.Exists()) {
309           m_sdk_directory_infos.push_back(sdk_directory_info);
310           if (log) {
311             log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded "
312                         "added builtin SDK directory %s",
313                         sdk_symbols_symlink_fspec.GetPath().c_str());
314           }
315         }
316       }
317 
318       const uint32_t num_installed = m_sdk_directory_infos.size();
319       FileSpec local_sdk_cache("~/Library/Developer/Xcode/iOS DeviceSupport",
320                                true);
321       if (local_sdk_cache.Exists()) {
322         if (log) {
323           log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded "
324                       "searching %s for additional SDKs",
325                       local_sdk_cache.GetPath().c_str());
326         }
327         char path[PATH_MAX];
328         if (local_sdk_cache.GetPath(path, sizeof(path))) {
329           FileSpec::EnumerateDirectory(
330               path, find_directories, find_files, find_other,
331               GetContainedFilesIntoVectorOfStringsCallback,
332               &m_sdk_directory_infos);
333           const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
334           // First try for an exact match of major, minor and update
335           for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
336             m_sdk_directory_infos[i].user_cached = true;
337             if (log) {
338               log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded "
339                           "user SDK directory %s",
340                           m_sdk_directory_infos[i].directory.GetPath().c_str());
341             }
342           }
343         }
344       }
345     }
346   }
347   return !m_sdk_directory_infos.empty();
348 }
349 
350 const PlatformRemoteiOS::SDKDirectoryInfo *
351 PlatformRemoteiOS::GetSDKDirectoryForCurrentOSVersion() {
352   uint32_t i;
353   if (UpdateSDKDirectoryInfosIfNeeded()) {
354     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
355 
356     // Check to see if the user specified a build string. If they did, then
357     // be sure to match it.
358     std::vector<bool> check_sdk_info(num_sdk_infos, true);
359     ConstString build(m_sdk_build);
360     if (build) {
361       for (i = 0; i < num_sdk_infos; ++i)
362         check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
363     }
364 
365     // If we are connected we can find the version of the OS the platform
366     // us running on and select the right SDK
367     uint32_t major, minor, update;
368     if (GetOSVersion(major, minor, update)) {
369       if (UpdateSDKDirectoryInfosIfNeeded()) {
370         // First try for an exact match of major, minor and update
371         for (i = 0; i < num_sdk_infos; ++i) {
372           if (check_sdk_info[i]) {
373             if (m_sdk_directory_infos[i].version_major == major &&
374                 m_sdk_directory_infos[i].version_minor == minor &&
375                 m_sdk_directory_infos[i].version_update == update) {
376               return &m_sdk_directory_infos[i];
377             }
378           }
379         }
380         // First try for an exact match of major and minor
381         for (i = 0; i < num_sdk_infos; ++i) {
382           if (check_sdk_info[i]) {
383             if (m_sdk_directory_infos[i].version_major == major &&
384                 m_sdk_directory_infos[i].version_minor == minor) {
385               return &m_sdk_directory_infos[i];
386             }
387           }
388         }
389         // Lastly try to match of major version only..
390         for (i = 0; i < num_sdk_infos; ++i) {
391           if (check_sdk_info[i]) {
392             if (m_sdk_directory_infos[i].version_major == major) {
393               return &m_sdk_directory_infos[i];
394             }
395           }
396         }
397       }
398     } else if (build) {
399       // No version, just a build number, search for the first one that matches
400       for (i = 0; i < num_sdk_infos; ++i)
401         if (check_sdk_info[i])
402           return &m_sdk_directory_infos[i];
403     }
404   }
405   return NULL;
406 }
407 
408 const PlatformRemoteiOS::SDKDirectoryInfo *
409 PlatformRemoteiOS::GetSDKDirectoryForLatestOSVersion() {
410   const PlatformRemoteiOS::SDKDirectoryInfo *result = NULL;
411   if (UpdateSDKDirectoryInfosIfNeeded()) {
412     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
413     // First try for an exact match of major, minor and update
414     for (uint32_t i = 0; i < num_sdk_infos; ++i) {
415       const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
416       if (sdk_dir_info.version_major != UINT32_MAX) {
417         if (result == NULL ||
418             sdk_dir_info.version_major > result->version_major) {
419           result = &sdk_dir_info;
420         } else if (sdk_dir_info.version_major == result->version_major) {
421           if (sdk_dir_info.version_minor > result->version_minor) {
422             result = &sdk_dir_info;
423           } else if (sdk_dir_info.version_minor == result->version_minor) {
424             if (sdk_dir_info.version_update > result->version_update) {
425               result = &sdk_dir_info;
426             }
427           }
428         }
429       }
430     }
431   }
432   return result;
433 }
434 
435 const char *PlatformRemoteiOS::GetDeviceSupportDirectory() {
436   if (m_device_support_directory.empty()) {
437     const char *device_support_dir = GetDeveloperDirectory();
438     if (device_support_dir) {
439       m_device_support_directory.assign(device_support_dir);
440       m_device_support_directory.append(
441           "/Platforms/iPhoneOS.platform/DeviceSupport");
442     } else {
443       // Assign a single NULL character so we know we tried to find the device
444       // support directory and we don't keep trying to find it over and over.
445       m_device_support_directory.assign(1, '\0');
446     }
447   }
448   // We should have put a single NULL character into m_device_support_directory
449   // or it should have a valid path if the code gets here
450   assert(m_device_support_directory.empty() == false);
451   if (m_device_support_directory[0])
452     return m_device_support_directory.c_str();
453   return NULL;
454 }
455 
456 const char *PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion() {
457   if (m_sdk_sysroot)
458     return m_sdk_sysroot.GetCString();
459 
460   if (m_device_support_directory_for_os_version.empty()) {
461     const PlatformRemoteiOS::SDKDirectoryInfo *sdk_dir_info =
462         GetSDKDirectoryForCurrentOSVersion();
463     if (sdk_dir_info == NULL)
464       sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
465     if (sdk_dir_info) {
466       char path[PATH_MAX];
467       if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
468         m_device_support_directory_for_os_version = path;
469         return m_device_support_directory_for_os_version.c_str();
470       }
471     } else {
472       // Assign a single NULL character so we know we tried to find the device
473       // support directory and we don't keep trying to find it over and over.
474       m_device_support_directory_for_os_version.assign(1, '\0');
475     }
476   }
477   // We should have put a single NULL character into
478   // m_device_support_directory_for_os_version
479   // or it should have a valid path if the code gets here
480   assert(m_device_support_directory_for_os_version.empty() == false);
481   if (m_device_support_directory_for_os_version[0])
482     return m_device_support_directory_for_os_version.c_str();
483   return NULL;
484 }
485 
486 uint32_t PlatformRemoteiOS::FindFileInAllSDKs(const char *platform_file_path,
487                                               FileSpecList &file_list) {
488   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST |
489                                                     LIBLLDB_LOG_VERBOSE);
490   if (platform_file_path && platform_file_path[0] &&
491       UpdateSDKDirectoryInfosIfNeeded()) {
492     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
493     lldb_private::FileSpec local_file;
494     // First try for an exact match of major, minor and update
495     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
496       if (log) {
497         log->Printf("Searching for %s in sdk path %s", platform_file_path,
498                     m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str());
499       }
500       if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
501         file_list.Append(local_file);
502       }
503     }
504   }
505   return file_list.GetSize();
506 }
507 
508 bool PlatformRemoteiOS::GetFileInSDK(const char *platform_file_path,
509                                      uint32_t sdk_idx,
510                                      lldb_private::FileSpec &local_file) {
511   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
512   if (sdk_idx < m_sdk_directory_infos.size()) {
513     std::string sdkroot_path =
514         m_sdk_directory_infos[sdk_idx].directory.GetPath();
515     local_file.Clear();
516 
517     if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
518       // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
519       // the
520       // SDK root directory and the file path.
521 
522       const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
523       for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
524         local_file.SetFile(sdkroot_path.c_str(), false);
525         if (paths_to_try[i][0] != '\0')
526           local_file.AppendPathComponent(paths_to_try[i]);
527         local_file.AppendPathComponent(platform_file_path);
528         local_file.ResolvePath();
529         if (local_file.Exists()) {
530           if (log)
531             log->Printf("Found a copy of %s in the SDK dir %s/%s",
532                         platform_file_path, sdkroot_path.c_str(),
533                         paths_to_try[i]);
534           return true;
535         }
536         local_file.Clear();
537       }
538     }
539   }
540   return false;
541 }
542 
543 Error PlatformRemoteiOS::GetSymbolFile(const FileSpec &platform_file,
544                                        const UUID *uuid_ptr,
545                                        FileSpec &local_file) {
546   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
547   Error error;
548   char platform_file_path[PATH_MAX];
549   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
550     char resolved_path[PATH_MAX];
551 
552     const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
553     if (os_version_dir) {
554       ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
555                  platform_file_path);
556 
557       local_file.SetFile(resolved_path, true);
558       if (local_file.Exists()) {
559         if (log) {
560           log->Printf("Found a copy of %s in the DeviceSupport dir %s",
561                       platform_file_path, os_version_dir);
562         }
563         return error;
564       }
565 
566       ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
567                  os_version_dir, platform_file_path);
568 
569       local_file.SetFile(resolved_path, true);
570       if (local_file.Exists()) {
571         if (log) {
572           log->Printf(
573               "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
574               platform_file_path, os_version_dir);
575         }
576         return error;
577       }
578       ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
579                  os_version_dir, platform_file_path);
580 
581       local_file.SetFile(resolved_path, true);
582       if (local_file.Exists()) {
583         if (log) {
584           log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
585                       platform_file_path, os_version_dir);
586         }
587         return error;
588       }
589     }
590     local_file = platform_file;
591     if (local_file.Exists())
592       return error;
593 
594     error.SetErrorStringWithFormat(
595         "unable to locate a platform file for '%s' in platform '%s'",
596         platform_file_path, GetPluginName().GetCString());
597   } else {
598     error.SetErrorString("invalid platform file argument");
599   }
600   return error;
601 }
602 
603 Error PlatformRemoteiOS::GetSharedModule(
604     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
605     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
606     bool *did_create_ptr) {
607   // For iOS, the SDK files are all cached locally on the host
608   // system. So first we ask for the file in the cached SDK,
609   // then we attempt to get a shared module for the right architecture
610   // with the right UUID.
611   const FileSpec &platform_file = module_spec.GetFileSpec();
612   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST |
613                                                     LIBLLDB_LOG_VERBOSE);
614 
615   Error error;
616   char platform_file_path[PATH_MAX];
617 
618   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
619     ModuleSpec platform_module_spec(module_spec);
620 
621     UpdateSDKDirectoryInfosIfNeeded();
622 
623     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
624 
625     // If we are connected we migth be able to correctly deduce the SDK
626     // directory
627     // using the OS build.
628     const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
629     if (connected_sdk_idx < num_sdk_infos) {
630       if (log) {
631         log->Printf("Searching for %s in sdk path %s", platform_file_path,
632                     m_sdk_directory_infos[connected_sdk_idx]
633                         .directory.GetPath()
634                         .c_str());
635       }
636       if (GetFileInSDK(platform_file_path, connected_sdk_idx,
637                        platform_module_spec.GetFileSpec())) {
638         module_sp.reset();
639         error = ResolveExecutable(platform_module_spec, module_sp, NULL);
640         if (module_sp) {
641           m_last_module_sdk_idx = connected_sdk_idx;
642           error.Clear();
643           return error;
644         }
645       }
646     }
647 
648     // Try the last SDK index if it is set as most files from an SDK
649     // will tend to be valid in that same SDK.
650     if (m_last_module_sdk_idx < num_sdk_infos) {
651       if (log) {
652         log->Printf("Searching for %s in sdk path %s", platform_file_path,
653                     m_sdk_directory_infos[m_last_module_sdk_idx]
654                         .directory.GetPath()
655                         .c_str());
656       }
657       if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
658                        platform_module_spec.GetFileSpec())) {
659         module_sp.reset();
660         error = ResolveExecutable(platform_module_spec, module_sp, NULL);
661         if (module_sp) {
662           error.Clear();
663           return error;
664         }
665       }
666     }
667 
668     // First try for an exact match of major, minor and update:
669     // If a particalar SDK version was specified via --version or --build, look
670     // for a match on disk.
671     const SDKDirectoryInfo *current_sdk_info =
672         GetSDKDirectoryForCurrentOSVersion();
673     const uint32_t current_sdk_idx =
674         GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
675     if (current_sdk_idx < num_sdk_infos &&
676         current_sdk_idx != m_last_module_sdk_idx) {
677       if (log) {
678         log->Printf(
679             "Searching for %s in sdk path %s", platform_file_path,
680             m_sdk_directory_infos[current_sdk_idx].directory.GetPath().c_str());
681       }
682       if (GetFileInSDK(platform_file_path, current_sdk_idx,
683                        platform_module_spec.GetFileSpec())) {
684         module_sp.reset();
685         error = ResolveExecutable(platform_module_spec, module_sp, NULL);
686         if (module_sp) {
687           m_last_module_sdk_idx = current_sdk_idx;
688           error.Clear();
689           return error;
690         }
691       }
692     }
693 
694     // Second try all SDKs that were found.
695     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
696       if (m_last_module_sdk_idx == sdk_idx) {
697         // Skip the last module SDK index if we already searched
698         // it above
699         continue;
700       }
701       if (log) {
702         log->Printf("Searching for %s in sdk path %s", platform_file_path,
703                     m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str());
704       }
705       if (GetFileInSDK(platform_file_path, sdk_idx,
706                        platform_module_spec.GetFileSpec())) {
707         // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
708 
709         error = ResolveExecutable(platform_module_spec, module_sp, NULL);
710         if (module_sp) {
711           // Remember the index of the last SDK that we found a file
712           // in in case the wrong SDK was selected.
713           m_last_module_sdk_idx = sdk_idx;
714           error.Clear();
715           return error;
716         }
717       }
718     }
719   }
720   // Not the module we are looking for... Nothing to see here...
721   module_sp.reset();
722 
723   // This may not be an SDK-related module.  Try whether we can bring in the
724   // thing to our local cache.
725   error = GetSharedModuleWithLocalCache(module_spec, module_sp,
726                                         module_search_paths_ptr,
727                                         old_module_sp_ptr, did_create_ptr);
728   if (error.Success())
729     return error;
730 
731   // See if the file is present in any of the module_search_paths_ptr
732   // directories.
733   if (!module_sp && module_search_paths_ptr && platform_file) {
734     // create a vector of all the file / directory names in platform_file
735     // e.g. this might be
736     // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
737     //
738     // We'll need to look in the module_search_paths_ptr directories for
739     // both "UIFoundation" and "UIFoundation.framework" -- most likely the
740     // latter will be the one we find there.
741 
742     FileSpec platform_pull_apart(platform_file);
743     std::vector<std::string> path_parts;
744     ConstString unix_root_dir("/");
745     while (true) {
746       ConstString part = platform_pull_apart.GetLastPathComponent();
747       platform_pull_apart.RemoveLastPathComponent();
748       if (part.IsEmpty() || part == unix_root_dir)
749         break;
750       path_parts.push_back(part.AsCString());
751     }
752     const size_t path_parts_size = path_parts.size();
753 
754     size_t num_module_search_paths = module_search_paths_ptr->GetSize();
755     for (size_t i = 0; i < num_module_search_paths; ++i) {
756       // Create a new FileSpec with this module_search_paths_ptr
757       // plus just the filename ("UIFoundation"), then the parent
758       // dir plus filename ("UIFoundation.framework/UIFoundation")
759       // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
760 
761       for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
762         FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
763 
764         // Add the components backwards.  For
765         // .../PrivateFrameworks/UIFoundation.framework/UIFoundation
766         // path_parts is
767         //   [0] UIFoundation
768         //   [1] UIFoundation.framework
769         //   [2] PrivateFrameworks
770         //
771         // and if 'j' is 2, we want to append path_parts[1] and then
772         // path_parts[0], aka
773         // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
774         // path.
775 
776         for (int k = j; k >= 0; --k) {
777           path_to_try.AppendPathComponent(path_parts[k]);
778         }
779 
780         if (path_to_try.Exists()) {
781           ModuleSpec new_module_spec(module_spec);
782           new_module_spec.GetFileSpec() = path_to_try;
783           Error new_error(Platform::GetSharedModule(
784               new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
785               did_create_ptr));
786 
787           if (module_sp) {
788             module_sp->SetPlatformFileSpec(path_to_try);
789             return new_error;
790           }
791         }
792       }
793     }
794   }
795 
796   const bool always_create = false;
797   error = ModuleList::GetSharedModule(
798       module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
799       did_create_ptr, always_create);
800 
801   if (module_sp)
802     module_sp->SetPlatformFileSpec(platform_file);
803 
804   return error;
805 }
806 
807 bool PlatformRemoteiOS::GetSupportedArchitectureAtIndex(uint32_t idx,
808                                                         ArchSpec &arch) {
809   return ARMGetSupportedArchitectureAtIndex(idx, arch);
810 }
811 
812 uint32_t PlatformRemoteiOS::GetConnectedSDKIndex() {
813   if (IsConnected()) {
814     if (m_connected_module_sdk_idx == UINT32_MAX) {
815       std::string build;
816       if (GetRemoteOSBuildString(build)) {
817         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
818         for (uint32_t i = 0; i < num_sdk_infos; ++i) {
819           const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
820           if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
821                      build.c_str())) {
822             m_connected_module_sdk_idx = i;
823           }
824         }
825       }
826     }
827   } else {
828     m_connected_module_sdk_idx = UINT32_MAX;
829   }
830   return m_connected_module_sdk_idx;
831 }
832 
833 uint32_t PlatformRemoteiOS::GetSDKIndexBySDKDirectoryInfo(
834     const SDKDirectoryInfo *sdk_info) {
835   if (sdk_info == NULL) {
836     return UINT32_MAX;
837   }
838 
839   return sdk_info - &m_sdk_directory_infos[0];
840 }
841