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