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