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