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