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