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