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