1 //===-- PlatformRemoteDarwinDevice.cpp -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PlatformRemoteDarwinDevice.h"
10 
11 #include "lldb/Breakpoint/BreakpointLocation.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ModuleList.h"
14 #include "lldb/Core/ModuleSpec.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Host/FileSystem.h"
17 #include "lldb/Host/Host.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Utility/FileSpec.h"
21 #include "lldb/Utility/Log.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/StreamString.h"
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 
28 PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo(
29     const lldb_private::FileSpec &sdk_dir)
30     : directory(sdk_dir), build(), user_cached(false) {
31   llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
32   llvm::StringRef build_str;
33   std::tie(version, build_str) = ParseVersionBuildDir(dirname_str);
34   build.SetString(build_str);
35 }
36 
37 /// Default Constructor
38 PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice()
39     : PlatformDarwin(false), // This is a remote platform
40       m_sdk_directory_infos(), m_device_support_directory(),
41       m_device_support_directory_for_os_version(), m_build_update(),
42       m_last_module_sdk_idx(UINT32_MAX),
43       m_connected_module_sdk_idx(UINT32_MAX) {}
44 
45 /// Destructor.
46 ///
47 /// The destructor is virtual since this class is designed to be
48 /// inherited from by the plug-in instance.
49 PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() {}
50 
51 void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) {
52   Platform::GetStatus(strm);
53   const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
54   if (sdk_directory)
55     strm.Printf("  SDK Path: \"%s\"\n", sdk_directory);
56   else
57     strm.PutCString("  SDK Path: error: unable to locate SDK\n");
58 
59   const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
60   for (uint32_t i = 0; i < num_sdk_infos; ++i) {
61     const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
62     strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
63                 sdk_dir_info.directory.GetPath().c_str());
64   }
65 }
66 
67 Status PlatformRemoteDarwinDevice::ResolveExecutable(
68     const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
69     const FileSpecList *module_search_paths_ptr) {
70   Status error;
71   // Nothing special to do here, just use the actual file and architecture
72 
73   ModuleSpec resolved_module_spec(ms);
74 
75   // Resolve any executable within a bundle on MacOSX
76   // TODO: verify that this handles shallow bundles, if not then implement one
77   // ourselves
78   Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
79 
80   if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
81     if (resolved_module_spec.GetArchitecture().IsValid() ||
82         resolved_module_spec.GetUUID().IsValid()) {
83       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
84                                           nullptr, nullptr, nullptr);
85 
86       if (exe_module_sp && exe_module_sp->GetObjectFile())
87         return error;
88       exe_module_sp.reset();
89     }
90     // No valid architecture was specified or the exact ARM slice wasn't found
91     // so ask the platform for the architectures that we should be using (in
92     // the correct order) and see if we can find a match that way
93     StreamString arch_names;
94     for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
95              idx, resolved_module_spec.GetArchitecture());
96          ++idx) {
97       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
98                                           nullptr, nullptr, nullptr);
99       // Did we find an executable using one of the
100       if (error.Success()) {
101         if (exe_module_sp && exe_module_sp->GetObjectFile())
102           break;
103         else
104           error.SetErrorToGenericError();
105       }
106 
107       if (idx > 0)
108         arch_names.PutCString(", ");
109       arch_names.PutCString(
110           resolved_module_spec.GetArchitecture().GetArchitectureName());
111     }
112 
113     if (error.Fail() || !exe_module_sp) {
114       if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
115         error.SetErrorStringWithFormat(
116             "'%s' doesn't contain any '%s' platform architectures: %s",
117             resolved_module_spec.GetFileSpec().GetPath().c_str(),
118             GetPluginName().GetCString(), arch_names.GetData());
119       } else {
120         error.SetErrorStringWithFormat(
121             "'%s' is not readable",
122             resolved_module_spec.GetFileSpec().GetPath().c_str());
123       }
124     }
125   } else {
126     error.SetErrorStringWithFormat(
127         "'%s' does not exist",
128         resolved_module_spec.GetFileSpec().GetPath().c_str());
129   }
130 
131   return error;
132 }
133 
134 FileSystem::EnumerateDirectoryResult
135 PlatformRemoteDarwinDevice::GetContainedFilesIntoVectorOfStringsCallback(
136     void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
137   ((PlatformRemoteDarwinDevice::SDKDirectoryInfoCollection *)baton)
138       ->push_back(PlatformRemoteDarwinDevice::SDKDirectoryInfo(FileSpec(path)));
139   return FileSystem::eEnumerateDirectoryResultNext;
140 }
141 
142 bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
143   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
144   std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
145   if (m_sdk_directory_infos.empty()) {
146     // A --sysroot option was supplied - add it to our list of SDKs to check
147     if (m_sdk_sysroot) {
148       FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString());
149       FileSystem::Instance().Resolve(sdk_sysroot_fspec);
150       const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
151       m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
152       if (log) {
153         log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded added "
154                     "--sysroot SDK directory %s",
155                     m_sdk_sysroot.GetCString());
156       }
157       return true;
158     }
159     const char *device_support_dir = GetDeviceSupportDirectory();
160     if (log) {
161       log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded Got "
162                   "DeviceSupport directory %s",
163                   device_support_dir);
164     }
165     if (device_support_dir) {
166       const bool find_directories = true;
167       const bool find_files = false;
168       const bool find_other = false;
169 
170       SDKDirectoryInfoCollection builtin_sdk_directory_infos;
171       FileSystem::Instance().EnumerateDirectory(
172           m_device_support_directory, find_directories, find_files, find_other,
173           GetContainedFilesIntoVectorOfStringsCallback,
174           &builtin_sdk_directory_infos);
175 
176       // Only add SDK directories that have symbols in them, some SDKs only
177       // contain developer disk images and no symbols, so they aren't useful to
178       // us.
179       FileSpec sdk_symbols_symlink_fspec;
180       for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
181         sdk_symbols_symlink_fspec = sdk_directory_info.directory;
182         sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
183         if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) {
184           m_sdk_directory_infos.push_back(sdk_directory_info);
185           if (log) {
186             log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
187                         "added builtin SDK directory %s",
188                         sdk_symbols_symlink_fspec.GetPath().c_str());
189           }
190         }
191       }
192 
193       std::vector<std::string>  device_support_dirnames;
194       GetDeviceSupportDirectoryNames (device_support_dirnames);
195 
196       for (std::string &dirname : device_support_dirnames)
197       {
198         const uint32_t num_installed = m_sdk_directory_infos.size();
199         std::string local_sdk_cache_str = "~/Library/Developer/Xcode/";
200         local_sdk_cache_str += dirname;
201         FileSpec local_sdk_cache(local_sdk_cache_str.c_str());
202         FileSystem::Instance().Resolve(local_sdk_cache);
203         if (FileSystem::Instance().Exists(local_sdk_cache)) {
204           if (log) {
205             log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
206                         "searching %s for additional SDKs",
207                         local_sdk_cache.GetPath().c_str());
208           }
209             char path[PATH_MAX];
210             if (local_sdk_cache.GetPath(path, sizeof(path))) {
211               FileSystem::Instance().EnumerateDirectory(
212                   path, find_directories, find_files, find_other,
213                   GetContainedFilesIntoVectorOfStringsCallback,
214                   &m_sdk_directory_infos);
215               const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
216               // First try for an exact match of major, minor and update
217               for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
218                 m_sdk_directory_infos[i].user_cached = true;
219                 if (log) {
220                 log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
221                             "user SDK directory %s",
222                             m_sdk_directory_infos[i].directory.GetPath().c_str());
223                 }
224             }
225           }
226         }
227       }
228 
229       const char *addtional_platform_dirs = getenv("PLATFORM_SDK_DIRECTORY");
230       if (addtional_platform_dirs) {
231         SDKDirectoryInfoCollection env_var_sdk_directory_infos;
232         FileSystem::Instance().EnumerateDirectory(
233             addtional_platform_dirs, find_directories, find_files, find_other,
234             GetContainedFilesIntoVectorOfStringsCallback,
235             &env_var_sdk_directory_infos);
236         FileSpec sdk_symbols_symlink_fspec;
237         for (const auto &sdk_directory_info : env_var_sdk_directory_infos) {
238           sdk_symbols_symlink_fspec = sdk_directory_info.directory;
239           sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
240           if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) {
241             m_sdk_directory_infos.push_back(sdk_directory_info);
242             if (log) {
243               log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
244                           "added env var SDK directory %s",
245                           sdk_symbols_symlink_fspec.GetPath().c_str());
246             }
247           }
248         }
249       }
250 
251     }
252   }
253   return !m_sdk_directory_infos.empty();
254 }
255 
256 const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
257 PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {
258   uint32_t i;
259   if (UpdateSDKDirectoryInfosIfNeeded()) {
260     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
261 
262     // Check to see if the user specified a build string. If they did, then be
263     // sure to match it.
264     std::vector<bool> check_sdk_info(num_sdk_infos, true);
265     ConstString build(m_sdk_build);
266     if (build) {
267       for (i = 0; i < num_sdk_infos; ++i)
268         check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
269     }
270 
271     // If we are connected we can find the version of the OS the platform us
272     // running on and select the right SDK
273     llvm::VersionTuple version = GetOSVersion();
274     if (!version.empty()) {
275       if (UpdateSDKDirectoryInfosIfNeeded()) {
276         // First try for an exact match of major, minor and update
277         for (i = 0; i < num_sdk_infos; ++i) {
278           if (check_sdk_info[i]) {
279             if (m_sdk_directory_infos[i].version == version)
280               return &m_sdk_directory_infos[i];
281           }
282         }
283         // First try for an exact match of major and minor
284         for (i = 0; i < num_sdk_infos; ++i) {
285           if (check_sdk_info[i]) {
286             if (m_sdk_directory_infos[i].version.getMajor() ==
287                     version.getMajor() &&
288                 m_sdk_directory_infos[i].version.getMinor() ==
289                     version.getMinor()) {
290               return &m_sdk_directory_infos[i];
291             }
292           }
293         }
294         // Lastly try to match of major version only..
295         for (i = 0; i < num_sdk_infos; ++i) {
296           if (check_sdk_info[i]) {
297             if (m_sdk_directory_infos[i].version.getMajor() ==
298                 version.getMajor()) {
299               return &m_sdk_directory_infos[i];
300             }
301           }
302         }
303       }
304     } else if (build) {
305       // No version, just a build number, search for the first one that matches
306       for (i = 0; i < num_sdk_infos; ++i)
307         if (check_sdk_info[i])
308           return &m_sdk_directory_infos[i];
309     }
310   }
311   return nullptr;
312 }
313 
314 const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
315 PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() {
316   const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = nullptr;
317   if (UpdateSDKDirectoryInfosIfNeeded()) {
318     auto max = std::max_element(
319         m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(),
320         [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) {
321           return a.version < b.version;
322         });
323     if (max != m_sdk_directory_infos.end())
324       result = &*max;
325   }
326   return result;
327 }
328 
329 const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectory() {
330   std::string platform_dir = "/Platforms/" + GetPlatformName() + "/DeviceSupport";
331   if (m_device_support_directory.empty()) {
332     const char *device_support_dir = GetDeveloperDirectory();
333     if (device_support_dir) {
334       m_device_support_directory.assign(device_support_dir);
335       m_device_support_directory.append(platform_dir.c_str());
336     } else {
337       // Assign a single NULL character so we know we tried to find the device
338       // support directory and we don't keep trying to find it over and over.
339       m_device_support_directory.assign(1, '\0');
340     }
341   }
342   // We should have put a single NULL character into m_device_support_directory
343   // or it should have a valid path if the code gets here
344   assert(m_device_support_directory.empty() == false);
345   if (m_device_support_directory[0])
346     return m_device_support_directory.c_str();
347   return nullptr;
348 }
349 
350 const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() {
351   if (m_sdk_sysroot)
352     return m_sdk_sysroot.GetCString();
353 
354   if (m_device_support_directory_for_os_version.empty()) {
355     const PlatformRemoteDarwinDevice::SDKDirectoryInfo *sdk_dir_info =
356         GetSDKDirectoryForCurrentOSVersion();
357     if (sdk_dir_info == nullptr)
358       sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
359     if (sdk_dir_info) {
360       char path[PATH_MAX];
361       if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
362         m_device_support_directory_for_os_version = path;
363         return m_device_support_directory_for_os_version.c_str();
364       }
365     } else {
366       // Assign a single NULL character so we know we tried to find the device
367       // support directory and we don't keep trying to find it over and over.
368       m_device_support_directory_for_os_version.assign(1, '\0');
369     }
370   }
371   // We should have put a single NULL character into
372   // m_device_support_directory_for_os_version or it should have a valid path
373   // if the code gets here
374   assert(m_device_support_directory_for_os_version.empty() == false);
375   if (m_device_support_directory_for_os_version[0])
376     return m_device_support_directory_for_os_version.c_str();
377   return nullptr;
378 }
379 
380 uint32_t PlatformRemoteDarwinDevice::FindFileInAllSDKs(const char *platform_file_path,
381                                               FileSpecList &file_list) {
382   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
383   if (platform_file_path && platform_file_path[0] &&
384       UpdateSDKDirectoryInfosIfNeeded()) {
385     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
386     lldb_private::FileSpec local_file;
387     // First try for an exact match of major, minor and update
388     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
389       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
390                 m_sdk_directory_infos[sdk_idx].directory);
391       if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
392         file_list.Append(local_file);
393       }
394     }
395   }
396   return file_list.GetSize();
397 }
398 
399 bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
400                                      uint32_t sdk_idx,
401                                      lldb_private::FileSpec &local_file) {
402   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
403   if (sdk_idx < m_sdk_directory_infos.size()) {
404     std::string sdkroot_path =
405         m_sdk_directory_infos[sdk_idx].directory.GetPath();
406     local_file.Clear();
407 
408     if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
409       // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
410       // the
411       // SDK root directory and the file path.
412 
413       const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
414       for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
415         local_file.SetFile(sdkroot_path, FileSpec::Style::native);
416         if (paths_to_try[i][0] != '\0')
417           local_file.AppendPathComponent(paths_to_try[i]);
418         local_file.AppendPathComponent(platform_file_path);
419         FileSystem::Instance().Resolve(local_file);
420         if (FileSystem::Instance().Exists(local_file)) {
421           if (log)
422             log->Printf("Found a copy of %s in the SDK dir %s/%s",
423                         platform_file_path, sdkroot_path.c_str(),
424                         paths_to_try[i]);
425           return true;
426         }
427         local_file.Clear();
428       }
429     }
430   }
431   return false;
432 }
433 
434 Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
435                                                  const UUID *uuid_ptr,
436                                                  FileSpec &local_file) {
437   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
438   Status error;
439   char platform_file_path[PATH_MAX];
440   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
441     char resolved_path[PATH_MAX];
442 
443     const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
444     if (os_version_dir) {
445       ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
446                  platform_file_path);
447 
448       local_file.SetFile(resolved_path, FileSpec::Style::native);
449       FileSystem::Instance().Resolve(local_file);
450       if (FileSystem::Instance().Exists(local_file)) {
451         if (log) {
452           log->Printf("Found a copy of %s in the DeviceSupport dir %s",
453                       platform_file_path, os_version_dir);
454         }
455         return error;
456       }
457 
458       ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
459                  os_version_dir, platform_file_path);
460 
461       local_file.SetFile(resolved_path, FileSpec::Style::native);
462       FileSystem::Instance().Resolve(local_file);
463       if (FileSystem::Instance().Exists(local_file)) {
464         if (log) {
465           log->Printf(
466               "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
467               platform_file_path, os_version_dir);
468         }
469         return error;
470       }
471       ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
472                  os_version_dir, platform_file_path);
473 
474       local_file.SetFile(resolved_path, FileSpec::Style::native);
475       FileSystem::Instance().Resolve(local_file);
476       if (FileSystem::Instance().Exists(local_file)) {
477         if (log) {
478           log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
479                       platform_file_path, os_version_dir);
480         }
481         return error;
482       }
483     }
484     local_file = platform_file;
485     if (FileSystem::Instance().Exists(local_file))
486       return error;
487 
488     error.SetErrorStringWithFormat(
489         "unable to locate a platform file for '%s' in platform '%s'",
490         platform_file_path, GetPluginName().GetCString());
491   } else {
492     error.SetErrorString("invalid platform file argument");
493   }
494   return error;
495 }
496 
497 Status PlatformRemoteDarwinDevice::GetSharedModule(
498     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
499     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
500     bool *did_create_ptr) {
501   // For iOS, the SDK files are all cached locally on the host system. So first
502   // we ask for the file in the cached SDK, then we attempt to get a shared
503   // module for the right architecture with the right UUID.
504   const FileSpec &platform_file = module_spec.GetFileSpec();
505   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
506 
507   Status error;
508   char platform_file_path[PATH_MAX];
509 
510   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
511     ModuleSpec platform_module_spec(module_spec);
512 
513     UpdateSDKDirectoryInfosIfNeeded();
514 
515     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
516 
517     // If we are connected we migth be able to correctly deduce the SDK
518     // directory using the OS build.
519     const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
520     if (connected_sdk_idx < num_sdk_infos) {
521       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
522                 m_sdk_directory_infos[connected_sdk_idx].directory);
523       if (GetFileInSDK(platform_file_path, connected_sdk_idx,
524                        platform_module_spec.GetFileSpec())) {
525         module_sp.reset();
526         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
527         if (module_sp) {
528           m_last_module_sdk_idx = connected_sdk_idx;
529           error.Clear();
530           return error;
531         }
532       }
533     }
534 
535     // Try the last SDK index if it is set as most files from an SDK will tend
536     // to be valid in that same SDK.
537     if (m_last_module_sdk_idx < num_sdk_infos) {
538       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
539                 m_sdk_directory_infos[m_last_module_sdk_idx].directory);
540       if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
541                        platform_module_spec.GetFileSpec())) {
542         module_sp.reset();
543         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
544         if (module_sp) {
545           error.Clear();
546           return error;
547         }
548       }
549     }
550 
551     // First try for an exact match of major, minor and update: If a particalar
552     // SDK version was specified via --version or --build, look for a match on
553     // disk.
554     const SDKDirectoryInfo *current_sdk_info =
555         GetSDKDirectoryForCurrentOSVersion();
556     const uint32_t current_sdk_idx =
557         GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
558     if (current_sdk_idx < num_sdk_infos &&
559         current_sdk_idx != m_last_module_sdk_idx) {
560       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
561                 m_sdk_directory_infos[current_sdk_idx].directory);
562       if (GetFileInSDK(platform_file_path, current_sdk_idx,
563                        platform_module_spec.GetFileSpec())) {
564         module_sp.reset();
565         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
566         if (module_sp) {
567           m_last_module_sdk_idx = current_sdk_idx;
568           error.Clear();
569           return error;
570         }
571       }
572     }
573 
574     // Second try all SDKs that were found.
575     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
576       if (m_last_module_sdk_idx == sdk_idx) {
577         // Skip the last module SDK index if we already searched it above
578         continue;
579       }
580       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
581                 m_sdk_directory_infos[sdk_idx].directory);
582       if (GetFileInSDK(platform_file_path, sdk_idx,
583                        platform_module_spec.GetFileSpec())) {
584         // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
585 
586         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
587         if (module_sp) {
588           // Remember the index of the last SDK that we found a file in in case
589           // the wrong SDK was selected.
590           m_last_module_sdk_idx = sdk_idx;
591           error.Clear();
592           return error;
593         }
594       }
595     }
596   }
597   // Not the module we are looking for... Nothing to see here...
598   module_sp.reset();
599 
600   // This may not be an SDK-related module.  Try whether we can bring in the
601   // thing to our local cache.
602   error = GetSharedModuleWithLocalCache(module_spec, module_sp,
603                                         module_search_paths_ptr,
604                                         old_module_sp_ptr, did_create_ptr);
605   if (error.Success())
606     return error;
607 
608   // See if the file is present in any of the module_search_paths_ptr
609   // directories.
610   if (!module_sp)
611     error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp,
612             module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
613 
614   if (error.Success())
615     return error;
616 
617   const bool always_create = false;
618   error = ModuleList::GetSharedModule(
619       module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
620       did_create_ptr, always_create);
621 
622   if (module_sp)
623     module_sp->SetPlatformFileSpec(platform_file);
624 
625   return error;
626 }
627 
628 uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {
629   if (IsConnected()) {
630     if (m_connected_module_sdk_idx == UINT32_MAX) {
631       std::string build;
632       if (GetRemoteOSBuildString(build)) {
633         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
634         for (uint32_t i = 0; i < num_sdk_infos; ++i) {
635           const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
636           if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
637                      build.c_str())) {
638             m_connected_module_sdk_idx = i;
639           }
640         }
641       }
642     }
643   } else {
644     m_connected_module_sdk_idx = UINT32_MAX;
645   }
646   return m_connected_module_sdk_idx;
647 }
648 
649 uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(
650     const SDKDirectoryInfo *sdk_info) {
651   if (sdk_info == nullptr) {
652     return UINT32_MAX;
653   }
654 
655   return sdk_info - &m_sdk_directory_infos[0];
656 }
657