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