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 PlatformSP
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::aarch64:
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 because it
109                     // was NOT specified)
110                     case llvm::Triple::UnknownArch:
111                         create = !arch->TripleVendorWasSpecified();
112                         break;
113 
114 #endif
115                     default:
116                         break;
117                 }
118                 if (create)
119                 {
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 because 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 lldb::PlatformSP(new PlatformRemoteiOS ());
148     return lldb::PlatformSP();
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             if (exe_file.Readable())
277             {
278                 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
279                                                 exe_file.GetPath().c_str(),
280                                                 GetPluginName().GetCString(),
281                                                 arch_names.GetString().c_str());
282             }
283             else
284             {
285                 error.SetErrorStringWithFormat("'%s' is not readable", exe_file.GetPath().c_str());
286             }
287         }
288     }
289     else
290     {
291         error.SetErrorStringWithFormat ("'%s' does not exist",
292                                         exe_file.GetPath().c_str());
293     }
294 
295     return error;
296 }
297 
298 FileSpec::EnumerateDirectoryResult
299 PlatformRemoteiOS::GetContainedFilesIntoVectorOfStringsCallback (void *baton,
300                                                                  FileSpec::FileType file_type,
301                                                                  const FileSpec &file_spec)
302 {
303     ((PlatformRemoteiOS::SDKDirectoryInfoCollection *)baton)->push_back(PlatformRemoteiOS::SDKDirectoryInfo(file_spec));
304     return FileSpec::eEnumerateDirectoryResultNext;
305 }
306 
307 bool
308 PlatformRemoteiOS::UpdateSDKDirectoryInfosInNeeded()
309 {
310     if (m_sdk_directory_infos.empty())
311     {
312         const char *device_support_dir = GetDeviceSupportDirectory();
313         if (device_support_dir)
314         {
315             const bool find_directories = true;
316             const bool find_files = false;
317             const bool find_other = false;
318             FileSpec::EnumerateDirectory (m_device_support_directory.c_str(),
319                                           find_directories,
320                                           find_files,
321                                           find_other,
322                                           GetContainedFilesIntoVectorOfStringsCallback,
323                                           &m_sdk_directory_infos);
324 
325             const uint32_t num_installed = m_sdk_directory_infos.size();
326             FileSpec local_sdk_cache("~/Library/Developer/Xcode/iOS DeviceSupport", true);
327             if (local_sdk_cache.Exists())
328             {
329                 char path[PATH_MAX];
330                 if (local_sdk_cache.GetPath(path, sizeof(path)))
331                 {
332                     FileSpec::EnumerateDirectory (path,
333                                                   find_directories,
334                                                   find_files,
335                                                   find_other,
336                                                   GetContainedFilesIntoVectorOfStringsCallback,
337                                                   &m_sdk_directory_infos);
338                     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
339                     // First try for an exact match of major, minor and update
340                     for (uint32_t i=num_installed; i<num_sdk_infos; ++i)
341                     {
342                         m_sdk_directory_infos[i].user_cached = true;
343                     }
344                 }
345             }
346         }
347     }
348     return !m_sdk_directory_infos.empty();
349 }
350 
351 const PlatformRemoteiOS::SDKDirectoryInfo *
352 PlatformRemoteiOS::GetSDKDirectoryForCurrentOSVersion ()
353 {
354     uint32_t i;
355     if (UpdateSDKDirectoryInfosInNeeded())
356     {
357         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
358 
359         // Check to see if the user specified a build string. If they did, then
360         // be sure to match it.
361         std::vector<bool> check_sdk_info(num_sdk_infos, true);
362         ConstString build(m_sdk_build);
363         if (build)
364         {
365             for (i=0; i<num_sdk_infos; ++i)
366                 check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
367         }
368 
369         // If we are connected we can find the version of the OS the platform
370         // us running on and select the right SDK
371         uint32_t major, minor, update;
372         if (GetOSVersion(major, minor, update))
373         {
374             if (UpdateSDKDirectoryInfosInNeeded())
375             {
376                 // First try for an exact match of major, minor and update
377                 for (i=0; i<num_sdk_infos; ++i)
378                 {
379                     if (check_sdk_info[i])
380                     {
381                         if (m_sdk_directory_infos[i].version_major == major &&
382                             m_sdk_directory_infos[i].version_minor == minor &&
383                             m_sdk_directory_infos[i].version_update == update)
384                         {
385                             return &m_sdk_directory_infos[i];
386                         }
387                     }
388                 }
389                 // First try for an exact match of major and minor
390                 for (i=0; i<num_sdk_infos; ++i)
391                 {
392                     if (check_sdk_info[i])
393                     {
394                         if (m_sdk_directory_infos[i].version_major == major &&
395                             m_sdk_directory_infos[i].version_minor == minor)
396                         {
397                             return &m_sdk_directory_infos[i];
398                         }
399                     }
400                 }
401                 // Lastly try to match of major version only..
402                 for (i=0; i<num_sdk_infos; ++i)
403                 {
404                     if (check_sdk_info[i])
405                     {
406                         if (m_sdk_directory_infos[i].version_major == major)
407                         {
408                             return &m_sdk_directory_infos[i];
409                         }
410                     }
411                 }
412             }
413         }
414         else if (build)
415         {
416             // No version, just a build number, search for the first one that matches
417             for (i=0; i<num_sdk_infos; ++i)
418                 if (check_sdk_info[i])
419                     return &m_sdk_directory_infos[i];
420         }
421     }
422     return NULL;
423 }
424 
425 const PlatformRemoteiOS::SDKDirectoryInfo *
426 PlatformRemoteiOS::GetSDKDirectoryForLatestOSVersion ()
427 {
428     const PlatformRemoteiOS::SDKDirectoryInfo *result = NULL;
429     if (UpdateSDKDirectoryInfosInNeeded())
430     {
431         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
432         // First try for an exact match of major, minor and update
433         for (uint32_t i=0; i<num_sdk_infos; ++i)
434         {
435             const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
436             if (sdk_dir_info.version_major != UINT32_MAX)
437             {
438                 if (result == NULL || sdk_dir_info.version_major > result->version_major)
439                 {
440                     result = &sdk_dir_info;
441                 }
442                 else if (sdk_dir_info.version_major == result->version_major)
443                 {
444                     if (sdk_dir_info.version_minor > result->version_minor)
445                     {
446                         result = &sdk_dir_info;
447                     }
448                     else if (sdk_dir_info.version_minor == result->version_minor)
449                     {
450                         if (sdk_dir_info.version_update > result->version_update)
451                         {
452                             result = &sdk_dir_info;
453                         }
454                     }
455                 }
456             }
457         }
458     }
459     return result;
460 }
461 
462 
463 
464 const char *
465 PlatformRemoteiOS::GetDeviceSupportDirectory()
466 {
467     if (m_device_support_directory.empty())
468     {
469         const char *device_support_dir = GetDeveloperDirectory();
470         if (device_support_dir)
471         {
472             m_device_support_directory.assign (device_support_dir);
473             m_device_support_directory.append ("/Platforms/iPhoneOS.platform/DeviceSupport");
474         }
475         else
476         {
477             // Assign a single NULL character so we know we tried to find the device
478             // support directory and we don't keep trying to find it over and over.
479             m_device_support_directory.assign (1, '\0');
480         }
481     }
482     // We should have put a single NULL character into m_device_support_directory
483     // or it should have a valid path if the code gets here
484     assert (m_device_support_directory.empty() == false);
485     if (m_device_support_directory[0])
486         return m_device_support_directory.c_str();
487     return NULL;
488 }
489 
490 
491 const char *
492 PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion()
493 {
494     if (m_sdk_sysroot)
495         return m_sdk_sysroot.GetCString();
496 
497     if (m_device_support_directory_for_os_version.empty())
498     {
499         const PlatformRemoteiOS::SDKDirectoryInfo *sdk_dir_info = GetSDKDirectoryForCurrentOSVersion ();
500         if (sdk_dir_info == NULL)
501             sdk_dir_info = GetSDKDirectoryForLatestOSVersion ();
502         if (sdk_dir_info)
503         {
504             char path[PATH_MAX];
505             if (sdk_dir_info->directory.GetPath(path, sizeof(path)))
506             {
507                 m_device_support_directory_for_os_version = path;
508                 return m_device_support_directory_for_os_version.c_str();
509             }
510         }
511         else
512         {
513             // Assign a single NULL character so we know we tried to find the device
514             // support directory and we don't keep trying to find it over and over.
515             m_device_support_directory_for_os_version.assign (1, '\0');
516         }
517     }
518     // We should have put a single NULL character into m_device_support_directory_for_os_version
519     // or it should have a valid path if the code gets here
520     assert (m_device_support_directory_for_os_version.empty() == false);
521     if (m_device_support_directory_for_os_version[0])
522         return m_device_support_directory_for_os_version.c_str();
523     return NULL;
524 }
525 
526 uint32_t
527 PlatformRemoteiOS::FindFileInAllSDKs (const char *platform_file_path,
528                                       FileSpecList &file_list)
529 {
530     if (platform_file_path && platform_file_path[0] && UpdateSDKDirectoryInfosInNeeded())
531     {
532         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
533         lldb_private::FileSpec local_file;
534         // First try for an exact match of major, minor and update
535         for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
536         {
537             if (GetFileInSDK (platform_file_path,
538                               sdk_idx,
539                               local_file))
540             {
541                 file_list.Append(local_file);
542             }
543         }
544     }
545     return file_list.GetSize();
546 }
547 
548 bool
549 PlatformRemoteiOS::GetFileInSDK (const char *platform_file_path,
550                                  uint32_t sdk_idx,
551                                  lldb_private::FileSpec &local_file)
552 {
553     if (sdk_idx < m_sdk_directory_infos.size())
554     {
555         char sdkroot_path[PATH_MAX];
556         const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[sdk_idx];
557         if (sdk_dir_info.directory.GetPath(sdkroot_path, sizeof(sdkroot_path)))
558         {
559             const bool symbols_dirs_only = true;
560 
561             return GetFileInSDKRoot (platform_file_path,
562                                      sdkroot_path,
563                                      symbols_dirs_only,
564                                      local_file);
565         }
566     }
567     return false;
568 }
569 
570 
571 bool
572 PlatformRemoteiOS::GetFileInSDKRoot (const char *platform_file_path,
573                                      const char *sdkroot_path,
574                                      bool symbols_dirs_only,
575                                      lldb_private::FileSpec &local_file)
576 {
577     if (sdkroot_path && sdkroot_path[0] && platform_file_path && platform_file_path[0])
578     {
579         char resolved_path[PATH_MAX];
580 
581         if (!symbols_dirs_only)
582         {
583             ::snprintf (resolved_path,
584                         sizeof(resolved_path),
585                         "%s/%s",
586                         sdkroot_path,
587                         platform_file_path);
588 
589             local_file.SetFile(resolved_path, true);
590             if (local_file.Exists())
591                 return true;
592         }
593 
594         ::snprintf (resolved_path,
595                     sizeof(resolved_path),
596                     "%s/Symbols.Internal/%s",
597                     sdkroot_path,
598                     platform_file_path);
599 
600         local_file.SetFile(resolved_path, true);
601         if (local_file.Exists())
602             return true;
603         ::snprintf (resolved_path,
604                     sizeof(resolved_path),
605                     "%s/Symbols/%s",
606                     sdkroot_path,
607                     platform_file_path);
608 
609         local_file.SetFile(resolved_path, true);
610         if (local_file.Exists())
611             return true;
612     }
613     return false;
614 }
615 
616 
617 Error
618 PlatformRemoteiOS::GetSymbolFile (const FileSpec &platform_file,
619                                   const UUID *uuid_ptr,
620                                   FileSpec &local_file)
621 {
622     Error error;
623     char platform_file_path[PATH_MAX];
624     if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
625     {
626         char resolved_path[PATH_MAX];
627 
628         const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion();
629         if (os_version_dir)
630         {
631             ::snprintf (resolved_path,
632                         sizeof(resolved_path),
633                         "%s/%s",
634                         os_version_dir,
635                         platform_file_path);
636 
637             local_file.SetFile(resolved_path, true);
638             if (local_file.Exists())
639                 return error;
640 
641             ::snprintf (resolved_path,
642                         sizeof(resolved_path),
643                         "%s/Symbols.Internal/%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             ::snprintf (resolved_path,
651                         sizeof(resolved_path),
652                         "%s/Symbols/%s",
653                         os_version_dir,
654                         platform_file_path);
655 
656             local_file.SetFile(resolved_path, true);
657             if (local_file.Exists())
658                 return error;
659 
660         }
661         local_file = platform_file;
662         if (local_file.Exists())
663             return error;
664 
665         error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
666                                         platform_file_path,
667                                         GetPluginName().GetCString());
668     }
669     else
670     {
671         error.SetErrorString ("invalid platform file argument");
672     }
673     return error;
674 }
675 
676 Error
677 PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec,
678                                     ModuleSP &module_sp,
679                                     const FileSpecList *module_search_paths_ptr,
680                                     ModuleSP *old_module_sp_ptr,
681                                     bool *did_create_ptr)
682 {
683     // For iOS, the SDK files are all cached locally on the host
684     // system. So first we ask for the file in the cached SDK,
685     // then we attempt to get a shared module for the right architecture
686     // with the right UUID.
687     const FileSpec &platform_file = module_spec.GetFileSpec();
688 
689     FileSpec local_file;
690     const UUID *module_uuid_ptr = module_spec.GetUUIDPtr();
691     Error error;
692     char platform_file_path[PATH_MAX];
693 
694     if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
695     {
696         FileSpec local_file;
697         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
698         // Try the last SDK index if it is set as most files from an SDK
699         // will tend to be valid in that same SDK.
700         if (m_last_module_sdk_idx < num_sdk_infos)
701         {
702             if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, local_file))
703             {
704                 //printf ("sdk[%u] last: '%s'\n", m_last_module_sdk_idx, local_file.GetPath().c_str());
705                 module_sp.reset();
706                 error = ResolveExecutable (local_file,
707                                            module_spec.GetArchitecture(),
708                                            module_sp,
709                                            NULL);
710                 if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr)))
711                 {
712                     //printf ("sdk[%u] last found\n", m_last_module_sdk_idx);
713                     error.Clear();
714                     return error;
715                 }
716             }
717         }
718 
719         // First try for an exact match of major, minor and update
720         for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
721         {
722             if (m_last_module_sdk_idx == sdk_idx)
723             {
724                 // Skip the last module SDK index if we already searched
725                 // it above
726                 continue;
727             }
728             if (GetFileInSDK (platform_file_path, sdk_idx, local_file))
729             {
730                 //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
731 
732                 error = ResolveExecutable (local_file,
733                                            module_spec.GetArchitecture(),
734                                            module_sp,
735                                            NULL);
736                 if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr)))
737                 {
738                     // Remember the index of the last SDK that we found a file
739                     // in in case the wrong SDK was selected.
740                     m_last_module_sdk_idx = sdk_idx;
741                     //printf ("sdk[%u]: found (setting last to %u)\n", sdk_idx, m_last_module_sdk_idx);
742                     error.Clear();
743                     return error;
744                 }
745             }
746         }
747     }
748     // Not the module we are looking for... Nothing to see here...
749     module_sp.reset();
750 
751     // This may not be an SDK-related module.  Try whether we can bring in the thing to our local cache.
752     error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
753     if (error.Success())
754         return error;
755 
756     const bool always_create = false;
757     error = ModuleList::GetSharedModule (module_spec,
758                                          module_sp,
759                                          module_search_paths_ptr,
760                                          old_module_sp_ptr,
761                                          did_create_ptr,
762                                          always_create);
763 
764     if (module_sp)
765         module_sp->SetPlatformFileSpec(platform_file);
766 
767     return error;
768 }
769 
770 bool
771 PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
772 {
773     return ARMGetSupportedArchitectureAtIndex (idx, arch);
774 }
775