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