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