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/Host.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Utility/FileSpec.h"
25 #include "lldb/Utility/Log.h"
26 #include "lldb/Utility/Status.h"
27 #include "lldb/Utility/StreamString.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo(
33     const lldb_private::FileSpec &sdk_dir)
34     : directory(sdk_dir), build(), user_cached(false) {
35   llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
36   llvm::StringRef build_str;
37   std::tie(version, build_str) = ParseVersionBuildDir(dirname_str);
38   build.SetString(build_str);
39 }
40 
41 //------------------------------------------------------------------
42 /// Default Constructor
43 //------------------------------------------------------------------
44 PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice()
45     : PlatformDarwin(false), // This is a remote platform
46       m_sdk_directory_infos(), m_device_support_directory(),
47       m_device_support_directory_for_os_version(), m_build_update(),
48       m_last_module_sdk_idx(UINT32_MAX),
49       m_connected_module_sdk_idx(UINT32_MAX) {}
50 
51 //------------------------------------------------------------------
52 /// Destructor.
53 ///
54 /// The destructor is virtual since this class is designed to be
55 /// inherited from by the plug-in instance.
56 //------------------------------------------------------------------
57 PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() {}
58 
59 void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) {
60   Platform::GetStatus(strm);
61   const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
62   if (sdk_directory)
63     strm.Printf("  SDK Path: \"%s\"\n", sdk_directory);
64   else
65     strm.PutCString("  SDK Path: error: unable to locate SDK\n");
66 
67   const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
68   for (uint32_t i = 0; i < num_sdk_infos; ++i) {
69     const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
70     strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
71                 sdk_dir_info.directory.GetPath().c_str());
72   }
73 }
74 
75 Status PlatformRemoteDarwinDevice::ResolveExecutable(
76     const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
77     const FileSpecList *module_search_paths_ptr) {
78   Status error;
79   // Nothing special to do here, just use the actual file and architecture
80 
81   ModuleSpec resolved_module_spec(ms);
82 
83   // Resolve any executable within a bundle on MacOSX
84   // TODO: verify that this handles shallow bundles, if not then implement one
85   // ourselves
86   Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
87 
88   if (resolved_module_spec.GetFileSpec().Exists()) {
89     if (resolved_module_spec.GetArchitecture().IsValid() ||
90         resolved_module_spec.GetUUID().IsValid()) {
91       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
92                                           NULL, NULL, NULL);
93 
94       if (exe_module_sp && exe_module_sp->GetObjectFile())
95         return error;
96       exe_module_sp.reset();
97     }
98     // No valid architecture was specified or the exact ARM slice wasn't found
99     // so ask the platform for the architectures that we should be using (in
100     // the correct order) and see if we can find a match that way
101     StreamString arch_names;
102     for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
103              idx, resolved_module_spec.GetArchitecture());
104          ++idx) {
105       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
106                                           NULL, NULL, NULL);
107       // Did we find an executable using one of the
108       if (error.Success()) {
109         if (exe_module_sp && exe_module_sp->GetObjectFile())
110           break;
111         else
112           error.SetErrorToGenericError();
113       }
114 
115       if (idx > 0)
116         arch_names.PutCString(", ");
117       arch_names.PutCString(
118           resolved_module_spec.GetArchitecture().GetArchitectureName());
119     }
120 
121     if (error.Fail() || !exe_module_sp) {
122       if (resolved_module_spec.GetFileSpec().Readable()) {
123         error.SetErrorStringWithFormat(
124             "'%s' doesn't contain any '%s' platform architectures: %s",
125             resolved_module_spec.GetFileSpec().GetPath().c_str(),
126             GetPluginName().GetCString(), arch_names.GetData());
127       } else {
128         error.SetErrorStringWithFormat(
129             "'%s' is not readable",
130             resolved_module_spec.GetFileSpec().GetPath().c_str());
131       }
132     }
133   } else {
134     error.SetErrorStringWithFormat(
135         "'%s' does not exist",
136         resolved_module_spec.GetFileSpec().GetPath().c_str());
137   }
138 
139   return error;
140 }
141 
142 FileSpec::EnumerateDirectoryResult
143 PlatformRemoteDarwinDevice::GetContainedFilesIntoVectorOfStringsCallback(
144     void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
145   ((PlatformRemoteDarwinDevice::SDKDirectoryInfoCollection *)baton)
146       ->push_back(PlatformRemoteDarwinDevice::SDKDirectoryInfo(file_spec));
147   return FileSpec::eEnumerateDirectoryResultNext;
148 }
149 
150 bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
151   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
152   std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
153   if (m_sdk_directory_infos.empty()) {
154     // A --sysroot option was supplied - add it to our list of SDKs to check
155     if (m_sdk_sysroot) {
156       FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString(), true);
157       const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
158       m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
159       if (log) {
160         log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded added "
161                     "--sysroot SDK directory %s",
162                     m_sdk_sysroot.GetCString());
163       }
164       return true;
165     }
166     const char *device_support_dir = GetDeviceSupportDirectory();
167     if (log) {
168       log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded Got "
169                   "DeviceSupport directory %s",
170                   device_support_dir);
171     }
172     if (device_support_dir) {
173       const bool find_directories = true;
174       const bool find_files = false;
175       const bool find_other = false;
176 
177       SDKDirectoryInfoCollection builtin_sdk_directory_infos;
178       FileSpec::EnumerateDirectory(m_device_support_directory, find_directories,
179                                    find_files, find_other,
180                                    GetContainedFilesIntoVectorOfStringsCallback,
181                                    &builtin_sdk_directory_infos);
182 
183       // Only add SDK directories that have symbols in them, some SDKs only
184       // contain developer disk images and no symbols, so they aren't useful to
185       // us.
186       FileSpec sdk_symbols_symlink_fspec;
187       for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
188         sdk_symbols_symlink_fspec = sdk_directory_info.directory;
189         sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
190         if (sdk_symbols_symlink_fspec.Exists()) {
191           m_sdk_directory_infos.push_back(sdk_directory_info);
192           if (log) {
193             log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
194                         "added builtin SDK directory %s",
195                         sdk_symbols_symlink_fspec.GetPath().c_str());
196           }
197         }
198       }
199 
200       std::vector<std::string>  device_support_dirnames;
201       GetDeviceSupportDirectoryNames (device_support_dirnames);
202 
203       for (std::string &dirname : device_support_dirnames)
204       {
205         const uint32_t num_installed = m_sdk_directory_infos.size();
206         std::string local_sdk_cache_str = "~/Library/Developer/Xcode/";
207         local_sdk_cache_str += dirname;
208         FileSpec local_sdk_cache(local_sdk_cache_str.c_str(), true);
209         if (local_sdk_cache.Exists()) {
210             if (log) {
211             log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
212                         "searching %s for additional SDKs",
213                         local_sdk_cache.GetPath().c_str());
214             }
215             char path[PATH_MAX];
216             if (local_sdk_cache.GetPath(path, sizeof(path))) {
217             FileSpec::EnumerateDirectory(
218                 path, find_directories, find_files, find_other,
219                 GetContainedFilesIntoVectorOfStringsCallback,
220                 &m_sdk_directory_infos);
221             const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
222             // First try for an exact match of major, minor and update
223             for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
224                 m_sdk_directory_infos[i].user_cached = true;
225                 if (log) {
226                 log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
227                             "user SDK directory %s",
228                             m_sdk_directory_infos[i].directory.GetPath().c_str());
229                 }
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         FileSpec::EnumerateDirectory(addtional_platform_dirs, find_directories,
239                                      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 (sdk_symbols_symlink_fspec.Exists()) {
247             m_sdk_directory_infos.push_back(sdk_directory_info);
248             if (log) {
249               log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
250                           "added env var SDK directory %s",
251                           sdk_symbols_symlink_fspec.GetPath().c_str());
252             }
253           }
254         }
255       }
256 
257     }
258   }
259   return !m_sdk_directory_infos.empty();
260 }
261 
262 const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
263 PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {
264   uint32_t i;
265   if (UpdateSDKDirectoryInfosIfNeeded()) {
266     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
267 
268     // Check to see if the user specified a build string. If they did, then be
269     // sure to match it.
270     std::vector<bool> check_sdk_info(num_sdk_infos, true);
271     ConstString build(m_sdk_build);
272     if (build) {
273       for (i = 0; i < num_sdk_infos; ++i)
274         check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
275     }
276 
277     // If we are connected we can find the version of the OS the platform us
278     // running on and select the right SDK
279     llvm::VersionTuple version = GetOSVersion();
280     if (!version.empty()) {
281       if (UpdateSDKDirectoryInfosIfNeeded()) {
282         // First try for an exact match of major, minor and update
283         for (i = 0; i < num_sdk_infos; ++i) {
284           if (check_sdk_info[i]) {
285             if (m_sdk_directory_infos[i].version == version)
286               return &m_sdk_directory_infos[i];
287           }
288         }
289         // First try for an exact match of major and minor
290         for (i = 0; i < num_sdk_infos; ++i) {
291           if (check_sdk_info[i]) {
292             if (m_sdk_directory_infos[i].version.getMajor() ==
293                     version.getMajor() &&
294                 m_sdk_directory_infos[i].version.getMinor() ==
295                     version.getMinor()) {
296               return &m_sdk_directory_infos[i];
297             }
298           }
299         }
300         // Lastly try to match of major version only..
301         for (i = 0; i < num_sdk_infos; ++i) {
302           if (check_sdk_info[i]) {
303             if (m_sdk_directory_infos[i].version.getMajor() ==
304                 version.getMajor()) {
305               return &m_sdk_directory_infos[i];
306             }
307           }
308         }
309       }
310     } else if (build) {
311       // No version, just a build number, search for the first one that matches
312       for (i = 0; i < num_sdk_infos; ++i)
313         if (check_sdk_info[i])
314           return &m_sdk_directory_infos[i];
315     }
316   }
317   return NULL;
318 }
319 
320 const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
321 PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() {
322   const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL;
323   if (UpdateSDKDirectoryInfosIfNeeded()) {
324     auto max = std::max_element(
325         m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(),
326         [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) {
327           return a.version < b.version;
328         });
329     if (max != m_sdk_directory_infos.end())
330       result = &*max;
331   }
332   return result;
333 }
334 
335 const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectory() {
336   std::string platform_dir = "/Platforms/" + GetPlatformName() + "/DeviceSupport";
337   if (m_device_support_directory.empty()) {
338     const char *device_support_dir = GetDeveloperDirectory();
339     if (device_support_dir) {
340       m_device_support_directory.assign(device_support_dir);
341       m_device_support_directory.append(platform_dir.c_str());
342     } else {
343       // Assign a single NULL character so we know we tried to find the device
344       // support directory and we don't keep trying to find it over and over.
345       m_device_support_directory.assign(1, '\0');
346     }
347   }
348   // We should have put a single NULL character into m_device_support_directory
349   // or it should have a valid path if the code gets here
350   assert(m_device_support_directory.empty() == false);
351   if (m_device_support_directory[0])
352     return m_device_support_directory.c_str();
353   return NULL;
354 }
355 
356 const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() {
357   if (m_sdk_sysroot)
358     return m_sdk_sysroot.GetCString();
359 
360   if (m_device_support_directory_for_os_version.empty()) {
361     const PlatformRemoteDarwinDevice::SDKDirectoryInfo *sdk_dir_info =
362         GetSDKDirectoryForCurrentOSVersion();
363     if (sdk_dir_info == NULL)
364       sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
365     if (sdk_dir_info) {
366       char path[PATH_MAX];
367       if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
368         m_device_support_directory_for_os_version = path;
369         return m_device_support_directory_for_os_version.c_str();
370       }
371     } else {
372       // Assign a single NULL character so we know we tried to find the device
373       // support directory and we don't keep trying to find it over and over.
374       m_device_support_directory_for_os_version.assign(1, '\0');
375     }
376   }
377   // We should have put a single NULL character into
378   // m_device_support_directory_for_os_version or it should have a valid path
379   // if the code gets here
380   assert(m_device_support_directory_for_os_version.empty() == false);
381   if (m_device_support_directory_for_os_version[0])
382     return m_device_support_directory_for_os_version.c_str();
383   return NULL;
384 }
385 
386 uint32_t PlatformRemoteDarwinDevice::FindFileInAllSDKs(const char *platform_file_path,
387                                               FileSpecList &file_list) {
388   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
389   if (platform_file_path && platform_file_path[0] &&
390       UpdateSDKDirectoryInfosIfNeeded()) {
391     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
392     lldb_private::FileSpec local_file;
393     // First try for an exact match of major, minor and update
394     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
395       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
396                 m_sdk_directory_infos[sdk_idx].directory);
397       if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
398         file_list.Append(local_file);
399       }
400     }
401   }
402   return file_list.GetSize();
403 }
404 
405 bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
406                                      uint32_t sdk_idx,
407                                      lldb_private::FileSpec &local_file) {
408   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
409   if (sdk_idx < m_sdk_directory_infos.size()) {
410     std::string sdkroot_path =
411         m_sdk_directory_infos[sdk_idx].directory.GetPath();
412     local_file.Clear();
413 
414     if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
415       // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
416       // the
417       // SDK root directory and the file path.
418 
419       const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
420       for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
421         local_file.SetFile(sdkroot_path, false, FileSpec::Style::native);
422         if (paths_to_try[i][0] != '\0')
423           local_file.AppendPathComponent(paths_to_try[i]);
424         local_file.AppendPathComponent(platform_file_path);
425         local_file.ResolvePath();
426         if (local_file.Exists()) {
427           if (log)
428             log->Printf("Found a copy of %s in the SDK dir %s/%s",
429                         platform_file_path, sdkroot_path.c_str(),
430                         paths_to_try[i]);
431           return true;
432         }
433         local_file.Clear();
434       }
435     }
436   }
437   return false;
438 }
439 
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     char resolved_path[PATH_MAX];
448 
449     const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
450     if (os_version_dir) {
451       ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
452                  platform_file_path);
453 
454       local_file.SetFile(resolved_path, true, FileSpec::Style::native);
455       if (local_file.Exists()) {
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, true, FileSpec::Style::native);
467       if (local_file.Exists()) {
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, true, FileSpec::Style::native);
479       if (local_file.Exists()) {
480         if (log) {
481           log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
482                       platform_file_path, os_version_dir);
483         }
484         return error;
485       }
486     }
487     local_file = platform_file;
488     if (local_file.Exists())
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 
500 Status PlatformRemoteDarwinDevice::GetSharedModule(
501     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
502     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
503     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, NULL);
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, NULL);
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, NULL);
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, NULL);
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,
607                                         old_module_sp_ptr, 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 (module_spec, process, module_sp,
615             module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
616 
617   if (error.Success())
618     return error;
619 
620   const bool always_create = false;
621   error = ModuleList::GetSharedModule(
622       module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
623       did_create_ptr, always_create);
624 
625   if (module_sp)
626     module_sp->SetPlatformFileSpec(platform_file);
627 
628   return error;
629 }
630 
631 uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {
632   if (IsConnected()) {
633     if (m_connected_module_sdk_idx == UINT32_MAX) {
634       std::string build;
635       if (GetRemoteOSBuildString(build)) {
636         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
637         for (uint32_t i = 0; i < num_sdk_infos; ++i) {
638           const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
639           if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
640                      build.c_str())) {
641             m_connected_module_sdk_idx = i;
642           }
643         }
644       }
645     }
646   } else {
647     m_connected_module_sdk_idx = UINT32_MAX;
648   }
649   return m_connected_module_sdk_idx;
650 }
651 
652 uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(
653     const SDKDirectoryInfo *sdk_info) {
654   if (sdk_info == NULL) {
655     return UINT32_MAX;
656   }
657 
658   return sdk_info - &m_sdk_directory_infos[0];
659 }
660