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