xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 //===-- PlatformRemoteDarwinDevice.cpp -----------------------------------*- C++ -*-===//
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     const char *device_support_dir = GetDeveloperDirectory();
346     if (device_support_dir) {
347       m_device_support_directory.assign(device_support_dir);
348       m_device_support_directory.append(platform_dir.c_str());
349     } else {
350       // Assign a single NULL character so we know we tried to find the device
351       // support directory and we don't keep trying to find it over and over.
352       m_device_support_directory.assign(1, '\0');
353     }
354   }
355   // We should have put a single NULL character into m_device_support_directory
356   // or it should have a valid path if the code gets here
357   assert(m_device_support_directory.empty() == false);
358   if (m_device_support_directory[0])
359     return m_device_support_directory.c_str();
360   return nullptr;
361 }
362 
363 const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() {
364   if (m_sdk_sysroot)
365     return m_sdk_sysroot.GetCString();
366 
367   if (m_device_support_directory_for_os_version.empty()) {
368     const PlatformRemoteDarwinDevice::SDKDirectoryInfo *sdk_dir_info =
369         GetSDKDirectoryForCurrentOSVersion();
370     if (sdk_dir_info == nullptr)
371       sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
372     if (sdk_dir_info) {
373       char path[PATH_MAX];
374       if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
375         m_device_support_directory_for_os_version = path;
376         return m_device_support_directory_for_os_version.c_str();
377       }
378     } else {
379       // Assign a single NULL character so we know we tried to find the device
380       // support directory and we don't keep trying to find it over and over.
381       m_device_support_directory_for_os_version.assign(1, '\0');
382     }
383   }
384   // We should have put a single NULL character into
385   // m_device_support_directory_for_os_version or it should have a valid path
386   // if the code gets here
387   assert(m_device_support_directory_for_os_version.empty() == false);
388   if (m_device_support_directory_for_os_version[0])
389     return m_device_support_directory_for_os_version.c_str();
390   return nullptr;
391 }
392 
393 uint32_t PlatformRemoteDarwinDevice::FindFileInAllSDKs(const char *platform_file_path,
394                                               FileSpecList &file_list) {
395   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
396   if (platform_file_path && platform_file_path[0] &&
397       UpdateSDKDirectoryInfosIfNeeded()) {
398     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
399     lldb_private::FileSpec local_file;
400     // First try for an exact match of major, minor and update
401     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
402       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
403                 m_sdk_directory_infos[sdk_idx].directory);
404       if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
405         file_list.Append(local_file);
406       }
407     }
408   }
409   return file_list.GetSize();
410 }
411 
412 bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
413                                      uint32_t sdk_idx,
414                                      lldb_private::FileSpec &local_file) {
415   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
416   if (sdk_idx < m_sdk_directory_infos.size()) {
417     std::string sdkroot_path =
418         m_sdk_directory_infos[sdk_idx].directory.GetPath();
419     local_file.Clear();
420 
421     if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
422       // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
423       // the
424       // SDK root directory and the file path.
425 
426       const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
427       for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
428         local_file.SetFile(sdkroot_path, FileSpec::Style::native);
429         if (paths_to_try[i][0] != '\0')
430           local_file.AppendPathComponent(paths_to_try[i]);
431         local_file.AppendPathComponent(platform_file_path);
432         FileSystem::Instance().Resolve(local_file);
433         if (FileSystem::Instance().Exists(local_file)) {
434           LLDB_LOGF(log, "Found a copy of %s in the SDK dir %s/%s",
435                     platform_file_path, sdkroot_path.c_str(), paths_to_try[i]);
436           return true;
437         }
438         local_file.Clear();
439       }
440     }
441   }
442   return false;
443 }
444 
445 Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
446                                                  const UUID *uuid_ptr,
447                                                  FileSpec &local_file) {
448   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
449   Status error;
450   char platform_file_path[PATH_MAX];
451   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
452     const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
453     if (os_version_dir) {
454       std::string resolved_path =
455           (llvm::Twine(os_version_dir) + "/" + platform_file_path).str();
456 
457       local_file.SetFile(resolved_path, FileSpec::Style::native);
458       FileSystem::Instance().Resolve(local_file);
459       if (FileSystem::Instance().Exists(local_file)) {
460         if (log) {
461           LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s",
462                     platform_file_path, os_version_dir);
463         }
464         return error;
465       }
466 
467       resolved_path = (llvm::Twine(os_version_dir) + "/Symbols.Internal/" +
468                        platform_file_path)
469                           .str();
470 
471       local_file.SetFile(resolved_path, FileSpec::Style::native);
472       FileSystem::Instance().Resolve(local_file);
473       if (FileSystem::Instance().Exists(local_file)) {
474         LLDB_LOGF(
475             log,
476             "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
477             platform_file_path, os_version_dir);
478         return error;
479       }
480       resolved_path =
481           (llvm::Twine(os_version_dir) + "/Symbols/" + platform_file_path)
482               .str();
483 
484       local_file.SetFile(resolved_path, FileSpec::Style::native);
485       FileSystem::Instance().Resolve(local_file);
486       if (FileSystem::Instance().Exists(local_file)) {
487         LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s/Symbols",
488                   platform_file_path, os_version_dir);
489         return error;
490       }
491     }
492     local_file = platform_file;
493     if (FileSystem::Instance().Exists(local_file))
494       return error;
495 
496     error.SetErrorStringWithFormat(
497         "unable to locate a platform file for '%s' in platform '%s'",
498         platform_file_path, GetPluginName().GetCString());
499   } else {
500     error.SetErrorString("invalid platform file argument");
501   }
502   return error;
503 }
504 
505 Status PlatformRemoteDarwinDevice::GetSharedModule(
506     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
507     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
508     bool *did_create_ptr) {
509   // For iOS, the SDK files are all cached locally on the host system. So first
510   // we ask for the file in the cached SDK, then we attempt to get a shared
511   // module for the right architecture with the right UUID.
512   const FileSpec &platform_file = module_spec.GetFileSpec();
513   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
514 
515   Status error;
516   char platform_file_path[PATH_MAX];
517 
518   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
519     ModuleSpec platform_module_spec(module_spec);
520 
521     UpdateSDKDirectoryInfosIfNeeded();
522 
523     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
524 
525     // If we are connected we migth be able to correctly deduce the SDK
526     // directory using the OS build.
527     const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
528     if (connected_sdk_idx < num_sdk_infos) {
529       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
530                 m_sdk_directory_infos[connected_sdk_idx].directory);
531       if (GetFileInSDK(platform_file_path, connected_sdk_idx,
532                        platform_module_spec.GetFileSpec())) {
533         module_sp.reset();
534         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
535         if (module_sp) {
536           m_last_module_sdk_idx = connected_sdk_idx;
537           error.Clear();
538           return error;
539         }
540       }
541     }
542 
543     // Try the last SDK index if it is set as most files from an SDK will tend
544     // to be valid in that same SDK.
545     if (m_last_module_sdk_idx < num_sdk_infos) {
546       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
547                 m_sdk_directory_infos[m_last_module_sdk_idx].directory);
548       if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
549                        platform_module_spec.GetFileSpec())) {
550         module_sp.reset();
551         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
552         if (module_sp) {
553           error.Clear();
554           return error;
555         }
556       }
557     }
558 
559     // First try for an exact match of major, minor and update: If a particalar
560     // SDK version was specified via --version or --build, look for a match on
561     // disk.
562     const SDKDirectoryInfo *current_sdk_info =
563         GetSDKDirectoryForCurrentOSVersion();
564     const uint32_t current_sdk_idx =
565         GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
566     if (current_sdk_idx < num_sdk_infos &&
567         current_sdk_idx != m_last_module_sdk_idx) {
568       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
569                 m_sdk_directory_infos[current_sdk_idx].directory);
570       if (GetFileInSDK(platform_file_path, current_sdk_idx,
571                        platform_module_spec.GetFileSpec())) {
572         module_sp.reset();
573         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
574         if (module_sp) {
575           m_last_module_sdk_idx = current_sdk_idx;
576           error.Clear();
577           return error;
578         }
579       }
580     }
581 
582     // Second try all SDKs that were found.
583     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
584       if (m_last_module_sdk_idx == sdk_idx) {
585         // Skip the last module SDK index if we already searched it above
586         continue;
587       }
588       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
589                 m_sdk_directory_infos[sdk_idx].directory);
590       if (GetFileInSDK(platform_file_path, sdk_idx,
591                        platform_module_spec.GetFileSpec())) {
592         // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
593 
594         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
595         if (module_sp) {
596           // Remember the index of the last SDK that we found a file in in case
597           // the wrong SDK was selected.
598           m_last_module_sdk_idx = sdk_idx;
599           error.Clear();
600           return error;
601         }
602       }
603     }
604   }
605   // Not the module we are looking for... Nothing to see here...
606   module_sp.reset();
607 
608   // This may not be an SDK-related module.  Try whether we can bring in the
609   // thing to our local cache.
610   error = GetSharedModuleWithLocalCache(module_spec, module_sp,
611                                         module_search_paths_ptr,
612                                         old_module_sp_ptr, did_create_ptr);
613   if (error.Success())
614     return error;
615 
616   // See if the file is present in any of the module_search_paths_ptr
617   // directories.
618   if (!module_sp)
619     error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp,
620             module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
621 
622   if (error.Success())
623     return error;
624 
625   const bool always_create = false;
626   error = ModuleList::GetSharedModule(
627       module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
628       did_create_ptr, always_create);
629 
630   if (module_sp)
631     module_sp->SetPlatformFileSpec(platform_file);
632 
633   return error;
634 }
635 
636 uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {
637   if (IsConnected()) {
638     if (m_connected_module_sdk_idx == UINT32_MAX) {
639       std::string build;
640       if (GetRemoteOSBuildString(build)) {
641         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
642         for (uint32_t i = 0; i < num_sdk_infos; ++i) {
643           const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
644           if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
645                      build.c_str())) {
646             m_connected_module_sdk_idx = i;
647           }
648         }
649       }
650     }
651   } else {
652     m_connected_module_sdk_idx = UINT32_MAX;
653   }
654   return m_connected_module_sdk_idx;
655 }
656 
657 uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(
658     const SDKDirectoryInfo *sdk_info) {
659   if (sdk_info == nullptr) {
660     return UINT32_MAX;
661   }
662 
663   return sdk_info - &m_sdk_directory_infos[0];
664 }
665