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