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