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