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