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