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         // A --sysroot option was supplied - add it to our list of SDKs to check
308         if (m_sdk_sysroot)
309         {
310             FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString(), true);
311             const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
312             m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
313             return true;
314         }
315         const char *device_support_dir = GetDeviceSupportDirectory();
316         if (device_support_dir)
317         {
318             const bool find_directories = true;
319             const bool find_files = false;
320             const bool find_other = false;
321 
322             SDKDirectoryInfoCollection builtin_sdk_directory_infos;
323             FileSpec::EnumerateDirectory (m_device_support_directory.c_str(),
324                                           find_directories,
325                                           find_files,
326                                           find_other,
327                                           GetContainedFilesIntoVectorOfStringsCallback,
328                                           &builtin_sdk_directory_infos);
329 
330             // Only add SDK directories that have symbols in them, some SDKs only contain
331             // developer disk images and no symbols, so they aren't useful to us.
332             FileSpec sdk_symbols_symlink_fspec;
333             for (const auto &sdk_directory_info : builtin_sdk_directory_infos)
334             {
335                 sdk_symbols_symlink_fspec = sdk_directory_info.directory;
336                 sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
337                 if (sdk_symbols_symlink_fspec.Exists())
338                 {
339                     m_sdk_directory_infos.push_back(sdk_directory_info);
340                 }
341             }
342 
343             const uint32_t num_installed = m_sdk_directory_infos.size();
344             FileSpec local_sdk_cache("~/Library/Developer/Xcode/iOS DeviceSupport", true);
345             if (local_sdk_cache.Exists())
346             {
347                 char path[PATH_MAX];
348                 if (local_sdk_cache.GetPath(path, sizeof(path)))
349                 {
350                     FileSpec::EnumerateDirectory (path,
351                                                   find_directories,
352                                                   find_files,
353                                                   find_other,
354                                                   GetContainedFilesIntoVectorOfStringsCallback,
355                                                   &m_sdk_directory_infos);
356                     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
357                     // First try for an exact match of major, minor and update
358                     for (uint32_t i=num_installed; i<num_sdk_infos; ++i)
359                     {
360                         m_sdk_directory_infos[i].user_cached = true;
361                     }
362                 }
363             }
364         }
365     }
366     return !m_sdk_directory_infos.empty();
367 }
368 
369 const PlatformRemoteiOS::SDKDirectoryInfo *
370 PlatformRemoteiOS::GetSDKDirectoryForCurrentOSVersion ()
371 {
372     uint32_t i;
373     if (UpdateSDKDirectoryInfosIfNeeded())
374     {
375         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
376 
377         // Check to see if the user specified a build string. If they did, then
378         // be sure to match it.
379         std::vector<bool> check_sdk_info(num_sdk_infos, true);
380         ConstString build(m_sdk_build);
381         if (build)
382         {
383             for (i=0; i<num_sdk_infos; ++i)
384                 check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
385         }
386 
387         // If we are connected we can find the version of the OS the platform
388         // us running on and select the right SDK
389         uint32_t major, minor, update;
390         if (GetOSVersion(major, minor, update))
391         {
392             if (UpdateSDKDirectoryInfosIfNeeded())
393             {
394                 // First try for an exact match of major, minor and update
395                 for (i=0; i<num_sdk_infos; ++i)
396                 {
397                     if (check_sdk_info[i])
398                     {
399                         if (m_sdk_directory_infos[i].version_major == major &&
400                             m_sdk_directory_infos[i].version_minor == minor &&
401                             m_sdk_directory_infos[i].version_update == update)
402                         {
403                             return &m_sdk_directory_infos[i];
404                         }
405                     }
406                 }
407                 // First try for an exact match of major and minor
408                 for (i=0; i<num_sdk_infos; ++i)
409                 {
410                     if (check_sdk_info[i])
411                     {
412                         if (m_sdk_directory_infos[i].version_major == major &&
413                             m_sdk_directory_infos[i].version_minor == minor)
414                         {
415                             return &m_sdk_directory_infos[i];
416                         }
417                     }
418                 }
419                 // Lastly try to match of major version only..
420                 for (i=0; i<num_sdk_infos; ++i)
421                 {
422                     if (check_sdk_info[i])
423                     {
424                         if (m_sdk_directory_infos[i].version_major == major)
425                         {
426                             return &m_sdk_directory_infos[i];
427                         }
428                     }
429                 }
430             }
431         }
432         else if (build)
433         {
434             // No version, just a build number, search for the first one that matches
435             for (i=0; i<num_sdk_infos; ++i)
436                 if (check_sdk_info[i])
437                     return &m_sdk_directory_infos[i];
438         }
439     }
440     return NULL;
441 }
442 
443 const PlatformRemoteiOS::SDKDirectoryInfo *
444 PlatformRemoteiOS::GetSDKDirectoryForLatestOSVersion ()
445 {
446     const PlatformRemoteiOS::SDKDirectoryInfo *result = NULL;
447     if (UpdateSDKDirectoryInfosIfNeeded())
448     {
449         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
450         // First try for an exact match of major, minor and update
451         for (uint32_t i=0; i<num_sdk_infos; ++i)
452         {
453             const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
454             if (sdk_dir_info.version_major != UINT32_MAX)
455             {
456                 if (result == NULL || sdk_dir_info.version_major > result->version_major)
457                 {
458                     result = &sdk_dir_info;
459                 }
460                 else if (sdk_dir_info.version_major == result->version_major)
461                 {
462                     if (sdk_dir_info.version_minor > result->version_minor)
463                     {
464                         result = &sdk_dir_info;
465                     }
466                     else if (sdk_dir_info.version_minor == result->version_minor)
467                     {
468                         if (sdk_dir_info.version_update > result->version_update)
469                         {
470                             result = &sdk_dir_info;
471                         }
472                     }
473                 }
474             }
475         }
476     }
477     return result;
478 }
479 
480 
481 
482 const char *
483 PlatformRemoteiOS::GetDeviceSupportDirectory()
484 {
485     if (m_device_support_directory.empty())
486     {
487         const char *device_support_dir = GetDeveloperDirectory();
488         if (device_support_dir)
489         {
490             m_device_support_directory.assign (device_support_dir);
491             m_device_support_directory.append ("/Platforms/iPhoneOS.platform/DeviceSupport");
492         }
493         else
494         {
495             // Assign a single NULL character so we know we tried to find the device
496             // support directory and we don't keep trying to find it over and over.
497             m_device_support_directory.assign (1, '\0');
498         }
499     }
500     // We should have put a single NULL character into m_device_support_directory
501     // or it should have a valid path if the code gets here
502     assert (m_device_support_directory.empty() == false);
503     if (m_device_support_directory[0])
504         return m_device_support_directory.c_str();
505     return NULL;
506 }
507 
508 
509 const char *
510 PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion()
511 {
512     if (m_sdk_sysroot)
513         return m_sdk_sysroot.GetCString();
514 
515     if (m_device_support_directory_for_os_version.empty())
516     {
517         const PlatformRemoteiOS::SDKDirectoryInfo *sdk_dir_info = GetSDKDirectoryForCurrentOSVersion ();
518         if (sdk_dir_info == NULL)
519             sdk_dir_info = GetSDKDirectoryForLatestOSVersion ();
520         if (sdk_dir_info)
521         {
522             char path[PATH_MAX];
523             if (sdk_dir_info->directory.GetPath(path, sizeof(path)))
524             {
525                 m_device_support_directory_for_os_version = path;
526                 return m_device_support_directory_for_os_version.c_str();
527             }
528         }
529         else
530         {
531             // Assign a single NULL character so we know we tried to find the device
532             // support directory and we don't keep trying to find it over and over.
533             m_device_support_directory_for_os_version.assign (1, '\0');
534         }
535     }
536     // We should have put a single NULL character into m_device_support_directory_for_os_version
537     // or it should have a valid path if the code gets here
538     assert (m_device_support_directory_for_os_version.empty() == false);
539     if (m_device_support_directory_for_os_version[0])
540         return m_device_support_directory_for_os_version.c_str();
541     return NULL;
542 }
543 
544 uint32_t
545 PlatformRemoteiOS::FindFileInAllSDKs (const char *platform_file_path,
546                                       FileSpecList &file_list)
547 {
548     if (platform_file_path && platform_file_path[0] && UpdateSDKDirectoryInfosIfNeeded())
549     {
550         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
551         lldb_private::FileSpec local_file;
552         // First try for an exact match of major, minor and update
553         for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
554         {
555             if (GetFileInSDK (platform_file_path,
556                               sdk_idx,
557                               local_file))
558             {
559                 file_list.Append(local_file);
560             }
561         }
562     }
563     return file_list.GetSize();
564 }
565 
566 bool
567 PlatformRemoteiOS::GetFileInSDK (const char *platform_file_path,
568                                  uint32_t sdk_idx,
569                                  lldb_private::FileSpec &local_file)
570 {
571     if (sdk_idx < m_sdk_directory_infos.size())
572     {
573         char sdkroot_path[PATH_MAX];
574         const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[sdk_idx];
575         if (sdk_dir_info.directory.GetPath(sdkroot_path, sizeof(sdkroot_path)))
576         {
577             const bool symbols_dirs_only = true;
578 
579             return GetFileInSDKRoot (platform_file_path,
580                                      sdkroot_path,
581                                      symbols_dirs_only,
582                                      local_file);
583         }
584     }
585     return false;
586 }
587 
588 
589 bool
590 PlatformRemoteiOS::GetFileInSDKRoot (const char *platform_file_path,
591                                      const char *sdkroot_path,
592                                      bool symbols_dirs_only,
593                                      lldb_private::FileSpec &local_file)
594 {
595     if (sdkroot_path && sdkroot_path[0] && platform_file_path && platform_file_path[0])
596     {
597         char resolved_path[PATH_MAX];
598 
599         if (!symbols_dirs_only)
600         {
601             ::snprintf (resolved_path,
602                         sizeof(resolved_path),
603                         "%s%s",
604                         sdkroot_path,
605                         platform_file_path);
606 
607             local_file.SetFile(resolved_path, true);
608             if (local_file.Exists())
609                 return true;
610         }
611 
612         ::snprintf (resolved_path,
613                     sizeof(resolved_path),
614                     "%s/Symbols.Internal%s",
615                     sdkroot_path,
616                     platform_file_path);
617 
618         local_file.SetFile(resolved_path, true);
619         if (local_file.Exists())
620             return true;
621         ::snprintf (resolved_path,
622                     sizeof(resolved_path),
623                     "%s/Symbols%s",
624                     sdkroot_path,
625                     platform_file_path);
626 
627         local_file.SetFile(resolved_path, true);
628         if (local_file.Exists())
629             return true;
630     }
631     return false;
632 }
633 
634 
635 Error
636 PlatformRemoteiOS::GetSymbolFile (const FileSpec &platform_file,
637                                   const UUID *uuid_ptr,
638                                   FileSpec &local_file)
639 {
640     Error error;
641     char platform_file_path[PATH_MAX];
642     if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
643     {
644         char resolved_path[PATH_MAX];
645 
646         const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion();
647         if (os_version_dir)
648         {
649             ::snprintf (resolved_path,
650                         sizeof(resolved_path),
651                         "%s/%s",
652                         os_version_dir,
653                         platform_file_path);
654 
655             local_file.SetFile(resolved_path, true);
656             if (local_file.Exists())
657                 return error;
658 
659             ::snprintf (resolved_path,
660                         sizeof(resolved_path),
661                         "%s/Symbols.Internal/%s",
662                         os_version_dir,
663                         platform_file_path);
664 
665             local_file.SetFile(resolved_path, true);
666             if (local_file.Exists())
667                 return error;
668             ::snprintf (resolved_path,
669                         sizeof(resolved_path),
670                         "%s/Symbols/%s",
671                         os_version_dir,
672                         platform_file_path);
673 
674             local_file.SetFile(resolved_path, true);
675             if (local_file.Exists())
676                 return error;
677 
678         }
679         local_file = platform_file;
680         if (local_file.Exists())
681             return error;
682 
683         error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
684                                         platform_file_path,
685                                         GetPluginName().GetCString());
686     }
687     else
688     {
689         error.SetErrorString ("invalid platform file argument");
690     }
691     return error;
692 }
693 
694 Error
695 PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec,
696                                     Process* process,
697                                     ModuleSP &module_sp,
698                                     const FileSpecList *module_search_paths_ptr,
699                                     ModuleSP *old_module_sp_ptr,
700                                     bool *did_create_ptr)
701 {
702     // For iOS, the SDK files are all cached locally on the host
703     // system. So first we ask for the file in the cached SDK,
704     // then we attempt to get a shared module for the right architecture
705     // with the right UUID.
706     const FileSpec &platform_file = module_spec.GetFileSpec();
707 
708     Error error;
709     char platform_file_path[PATH_MAX];
710 
711     if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
712     {
713         ModuleSpec platform_module_spec(module_spec);
714 
715         UpdateSDKDirectoryInfosIfNeeded();
716 
717         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
718 
719         // If we are connected we migth be able to correctly deduce the SDK directory
720         // using the OS build.
721         const uint32_t connected_sdk_idx = GetConnectedSDKIndex ();
722         if (connected_sdk_idx < num_sdk_infos)
723         {
724             if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec()))
725             {
726                 module_sp.reset();
727                 error = ResolveExecutable (platform_module_spec,
728                                            module_sp,
729                                            NULL);
730                 if (module_sp)
731                 {
732                     m_last_module_sdk_idx = connected_sdk_idx;
733                     error.Clear();
734                     return error;
735                 }
736             }
737         }
738 
739         // Try the last SDK index if it is set as most files from an SDK
740         // will tend to be valid in that same SDK.
741         if (m_last_module_sdk_idx < num_sdk_infos)
742         {
743             if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec()))
744             {
745                 module_sp.reset();
746                 error = ResolveExecutable (platform_module_spec,
747                                            module_sp,
748                                            NULL);
749                 if (module_sp)
750                 {
751                     error.Clear();
752                     return error;
753                 }
754             }
755         }
756 
757         // First try for an exact match of major, minor and update:
758         // If a particalar SDK version was specified via --version or --build, look for a match on disk.
759         const SDKDirectoryInfo *current_sdk_info = GetSDKDirectoryForCurrentOSVersion();
760         const uint32_t current_sdk_idx = GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
761         if (current_sdk_idx < num_sdk_infos && current_sdk_idx != m_last_module_sdk_idx)
762         {
763             if (GetFileInSDK (platform_file_path, current_sdk_idx, platform_module_spec.GetFileSpec()))
764             {
765                 module_sp.reset();
766                 error = ResolveExecutable (platform_module_spec,
767                                            module_sp,
768                                            NULL);
769                 if (module_sp)
770                 {
771                     m_last_module_sdk_idx = current_sdk_idx;
772                     error.Clear();
773                     return error;
774                 }
775             }
776         }
777 
778         // Second try all SDKs that were found.
779         for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
780         {
781             if (m_last_module_sdk_idx == sdk_idx)
782             {
783                 // Skip the last module SDK index if we already searched
784                 // it above
785                 continue;
786             }
787             if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec()))
788             {
789                 //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
790 
791                 error = ResolveExecutable (platform_module_spec, module_sp, NULL);
792                 if (module_sp)
793                 {
794                     // Remember the index of the last SDK that we found a file
795                     // in in case the wrong SDK was selected.
796                     m_last_module_sdk_idx = sdk_idx;
797                     error.Clear();
798                     return error;
799                 }
800             }
801         }
802     }
803     // Not the module we are looking for... Nothing to see here...
804     module_sp.reset();
805 
806     // This may not be an SDK-related module.  Try whether we can bring in the thing to our local cache.
807     error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
808     if (error.Success())
809         return error;
810 
811     const bool always_create = false;
812     error = ModuleList::GetSharedModule (module_spec,
813                                          module_sp,
814                                          module_search_paths_ptr,
815                                          old_module_sp_ptr,
816                                          did_create_ptr,
817                                          always_create);
818 
819     if (module_sp)
820         module_sp->SetPlatformFileSpec(platform_file);
821 
822     return error;
823 }
824 
825 bool
826 PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
827 {
828     return ARMGetSupportedArchitectureAtIndex (idx, arch);
829 }
830 
831 uint32_t
832 PlatformRemoteiOS::GetConnectedSDKIndex ()
833 {
834     if (IsConnected())
835     {
836         if (m_connected_module_sdk_idx == UINT32_MAX)
837         {
838             std::string build;
839             if (GetRemoteOSBuildString(build))
840             {
841                 const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
842                 for (uint32_t i=0; i<num_sdk_infos; ++i)
843                 {
844                     const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
845                     if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), build.c_str()))
846                     {
847                         m_connected_module_sdk_idx = i;
848                     }
849                 }
850             }
851         }
852     }
853     else
854     {
855         m_connected_module_sdk_idx = UINT32_MAX;
856     }
857     return m_connected_module_sdk_idx;
858 }
859 
860 uint32_t
861 PlatformRemoteiOS::GetSDKIndexBySDKDirectoryInfo (const SDKDirectoryInfo *sdk_info)
862 {
863     if (sdk_info == NULL)
864     {
865         return UINT32_MAX;
866     }
867 
868     return sdk_info - &m_sdk_directory_infos[0];
869 }
870