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