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