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   }
236   return !m_sdk_directory_infos.empty();
237 }
238 
239 const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
240 PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {
241   uint32_t i;
242   if (UpdateSDKDirectoryInfosIfNeeded()) {
243     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
244 
245     // Check to see if the user specified a build string. If they did, then be
246     // sure to match it.
247     std::vector<bool> check_sdk_info(num_sdk_infos, true);
248     ConstString build(m_sdk_build);
249     if (build) {
250       for (i = 0; i < num_sdk_infos; ++i)
251         check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
252     }
253 
254     // If we are connected we can find the version of the OS the platform us
255     // running on and select the right SDK
256     llvm::VersionTuple version = GetOSVersion();
257     if (!version.empty()) {
258       if (UpdateSDKDirectoryInfosIfNeeded()) {
259         // First try for an exact match of major, minor and update
260         for (i = 0; i < num_sdk_infos; ++i) {
261           if (check_sdk_info[i]) {
262             if (m_sdk_directory_infos[i].version == version)
263               return &m_sdk_directory_infos[i];
264           }
265         }
266         // First try for an exact match of major and minor
267         for (i = 0; i < num_sdk_infos; ++i) {
268           if (check_sdk_info[i]) {
269             if (m_sdk_directory_infos[i].version.getMajor() ==
270                     version.getMajor() &&
271                 m_sdk_directory_infos[i].version.getMinor() ==
272                     version.getMinor()) {
273               return &m_sdk_directory_infos[i];
274             }
275           }
276         }
277         // Lastly try to match of major version only..
278         for (i = 0; i < num_sdk_infos; ++i) {
279           if (check_sdk_info[i]) {
280             if (m_sdk_directory_infos[i].version.getMajor() ==
281                 version.getMajor()) {
282               return &m_sdk_directory_infos[i];
283             }
284           }
285         }
286       }
287     } else if (build) {
288       // No version, just a build number, search for the first one that matches
289       for (i = 0; i < num_sdk_infos; ++i)
290         if (check_sdk_info[i])
291           return &m_sdk_directory_infos[i];
292     }
293   }
294   return NULL;
295 }
296 
297 const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
298 PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() {
299   const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL;
300   if (UpdateSDKDirectoryInfosIfNeeded()) {
301     auto max = std::max_element(
302         m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(),
303         [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) {
304           return a.version < b.version;
305         });
306     if (max != m_sdk_directory_infos.end())
307       result = &*max;
308   }
309   return result;
310 }
311 
312 const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectory() {
313   std::string platform_dir = "/Platforms/" + GetPlatformName() + "/DeviceSupport";
314   if (m_device_support_directory.empty()) {
315     const char *device_support_dir = GetDeveloperDirectory();
316     if (device_support_dir) {
317       m_device_support_directory.assign(device_support_dir);
318       m_device_support_directory.append(platform_dir.c_str());
319     } else {
320       // Assign a single NULL character so we know we tried to find the device
321       // support directory and we don't keep trying to find it over and over.
322       m_device_support_directory.assign(1, '\0');
323     }
324   }
325   // We should have put a single NULL character into m_device_support_directory
326   // or it should have a valid path if the code gets here
327   assert(m_device_support_directory.empty() == false);
328   if (m_device_support_directory[0])
329     return m_device_support_directory.c_str();
330   return NULL;
331 }
332 
333 const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() {
334   if (m_sdk_sysroot)
335     return m_sdk_sysroot.GetCString();
336 
337   if (m_device_support_directory_for_os_version.empty()) {
338     const PlatformRemoteDarwinDevice::SDKDirectoryInfo *sdk_dir_info =
339         GetSDKDirectoryForCurrentOSVersion();
340     if (sdk_dir_info == NULL)
341       sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
342     if (sdk_dir_info) {
343       char path[PATH_MAX];
344       if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
345         m_device_support_directory_for_os_version = path;
346         return m_device_support_directory_for_os_version.c_str();
347       }
348     } else {
349       // Assign a single NULL character so we know we tried to find the device
350       // support directory and we don't keep trying to find it over and over.
351       m_device_support_directory_for_os_version.assign(1, '\0');
352     }
353   }
354   // We should have put a single NULL character into
355   // m_device_support_directory_for_os_version or it should have a valid path
356   // if the code gets here
357   assert(m_device_support_directory_for_os_version.empty() == false);
358   if (m_device_support_directory_for_os_version[0])
359     return m_device_support_directory_for_os_version.c_str();
360   return NULL;
361 }
362 
363 uint32_t PlatformRemoteDarwinDevice::FindFileInAllSDKs(const char *platform_file_path,
364                                               FileSpecList &file_list) {
365   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
366   if (platform_file_path && platform_file_path[0] &&
367       UpdateSDKDirectoryInfosIfNeeded()) {
368     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
369     lldb_private::FileSpec local_file;
370     // First try for an exact match of major, minor and update
371     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
372       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
373                 m_sdk_directory_infos[sdk_idx].directory);
374       if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
375         file_list.Append(local_file);
376       }
377     }
378   }
379   return file_list.GetSize();
380 }
381 
382 bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
383                                      uint32_t sdk_idx,
384                                      lldb_private::FileSpec &local_file) {
385   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
386   if (sdk_idx < m_sdk_directory_infos.size()) {
387     std::string sdkroot_path =
388         m_sdk_directory_infos[sdk_idx].directory.GetPath();
389     local_file.Clear();
390 
391     if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
392       // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
393       // the
394       // SDK root directory and the file path.
395 
396       const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
397       for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
398         local_file.SetFile(sdkroot_path, false, FileSpec::Style::native);
399         if (paths_to_try[i][0] != '\0')
400           local_file.AppendPathComponent(paths_to_try[i]);
401         local_file.AppendPathComponent(platform_file_path);
402         local_file.ResolvePath();
403         if (local_file.Exists()) {
404           if (log)
405             log->Printf("Found a copy of %s in the SDK dir %s/%s",
406                         platform_file_path, sdkroot_path.c_str(),
407                         paths_to_try[i]);
408           return true;
409         }
410         local_file.Clear();
411       }
412     }
413   }
414   return false;
415 }
416 
417 Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
418                                                  const UUID *uuid_ptr,
419                                                  FileSpec &local_file) {
420   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
421   Status error;
422   char platform_file_path[PATH_MAX];
423   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
424     char resolved_path[PATH_MAX];
425 
426     const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
427     if (os_version_dir) {
428       ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
429                  platform_file_path);
430 
431       local_file.SetFile(resolved_path, true, FileSpec::Style::native);
432       if (local_file.Exists()) {
433         if (log) {
434           log->Printf("Found a copy of %s in the DeviceSupport dir %s",
435                       platform_file_path, os_version_dir);
436         }
437         return error;
438       }
439 
440       ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
441                  os_version_dir, platform_file_path);
442 
443       local_file.SetFile(resolved_path, true, FileSpec::Style::native);
444       if (local_file.Exists()) {
445         if (log) {
446           log->Printf(
447               "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
448               platform_file_path, os_version_dir);
449         }
450         return error;
451       }
452       ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
453                  os_version_dir, platform_file_path);
454 
455       local_file.SetFile(resolved_path, true, FileSpec::Style::native);
456       if (local_file.Exists()) {
457         if (log) {
458           log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
459                       platform_file_path, os_version_dir);
460         }
461         return error;
462       }
463     }
464     local_file = platform_file;
465     if (local_file.Exists())
466       return error;
467 
468     error.SetErrorStringWithFormat(
469         "unable to locate a platform file for '%s' in platform '%s'",
470         platform_file_path, GetPluginName().GetCString());
471   } else {
472     error.SetErrorString("invalid platform file argument");
473   }
474   return error;
475 }
476 
477 Status PlatformRemoteDarwinDevice::GetSharedModule(
478     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
479     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
480     bool *did_create_ptr) {
481   // For iOS, the SDK files are all cached locally on the host system. So first
482   // we ask for the file in the cached SDK, then we attempt to get a shared
483   // module for the right architecture with the right UUID.
484   const FileSpec &platform_file = module_spec.GetFileSpec();
485   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
486 
487   Status error;
488   char platform_file_path[PATH_MAX];
489 
490   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
491     ModuleSpec platform_module_spec(module_spec);
492 
493     UpdateSDKDirectoryInfosIfNeeded();
494 
495     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
496 
497     // If we are connected we migth be able to correctly deduce the SDK
498     // directory using the OS build.
499     const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
500     if (connected_sdk_idx < num_sdk_infos) {
501       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
502                 m_sdk_directory_infos[connected_sdk_idx].directory);
503       if (GetFileInSDK(platform_file_path, connected_sdk_idx,
504                        platform_module_spec.GetFileSpec())) {
505         module_sp.reset();
506         error = ResolveExecutable(platform_module_spec, module_sp, NULL);
507         if (module_sp) {
508           m_last_module_sdk_idx = connected_sdk_idx;
509           error.Clear();
510           return error;
511         }
512       }
513     }
514 
515     // Try the last SDK index if it is set as most files from an SDK will tend
516     // to be valid in that same SDK.
517     if (m_last_module_sdk_idx < num_sdk_infos) {
518       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
519                 m_sdk_directory_infos[m_last_module_sdk_idx].directory);
520       if (GetFileInSDK(platform_file_path, m_last_module_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           error.Clear();
526           return error;
527         }
528       }
529     }
530 
531     // First try for an exact match of major, minor and update: If a particalar
532     // SDK version was specified via --version or --build, look for a match on
533     // disk.
534     const SDKDirectoryInfo *current_sdk_info =
535         GetSDKDirectoryForCurrentOSVersion();
536     const uint32_t current_sdk_idx =
537         GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
538     if (current_sdk_idx < num_sdk_infos &&
539         current_sdk_idx != m_last_module_sdk_idx) {
540       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
541                 m_sdk_directory_infos[current_sdk_idx].directory);
542       if (GetFileInSDK(platform_file_path, current_sdk_idx,
543                        platform_module_spec.GetFileSpec())) {
544         module_sp.reset();
545         error = ResolveExecutable(platform_module_spec, module_sp, NULL);
546         if (module_sp) {
547           m_last_module_sdk_idx = current_sdk_idx;
548           error.Clear();
549           return error;
550         }
551       }
552     }
553 
554     // Second try all SDKs that were found.
555     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
556       if (m_last_module_sdk_idx == sdk_idx) {
557         // Skip the last module SDK index if we already searched it above
558         continue;
559       }
560       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
561                 m_sdk_directory_infos[sdk_idx].directory);
562       if (GetFileInSDK(platform_file_path, sdk_idx,
563                        platform_module_spec.GetFileSpec())) {
564         // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
565 
566         error = ResolveExecutable(platform_module_spec, module_sp, NULL);
567         if (module_sp) {
568           // Remember the index of the last SDK that we found a file in in case
569           // the wrong SDK was selected.
570           m_last_module_sdk_idx = sdk_idx;
571           error.Clear();
572           return error;
573         }
574       }
575     }
576   }
577   // Not the module we are looking for... Nothing to see here...
578   module_sp.reset();
579 
580   // This may not be an SDK-related module.  Try whether we can bring in the
581   // thing to our local cache.
582   error = GetSharedModuleWithLocalCache(module_spec, module_sp,
583                                         module_search_paths_ptr,
584                                         old_module_sp_ptr, did_create_ptr);
585   if (error.Success())
586     return error;
587 
588   // See if the file is present in any of the module_search_paths_ptr
589   // directories.
590   if (!module_sp)
591     error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp,
592             module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
593 
594   if (error.Success())
595     return error;
596 
597   const bool always_create = false;
598   error = ModuleList::GetSharedModule(
599       module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
600       did_create_ptr, always_create);
601 
602   if (module_sp)
603     module_sp->SetPlatformFileSpec(platform_file);
604 
605   return error;
606 }
607 
608 uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {
609   if (IsConnected()) {
610     if (m_connected_module_sdk_idx == UINT32_MAX) {
611       std::string build;
612       if (GetRemoteOSBuildString(build)) {
613         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
614         for (uint32_t i = 0; i < num_sdk_infos; ++i) {
615           const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
616           if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
617                      build.c_str())) {
618             m_connected_module_sdk_idx = i;
619           }
620         }
621       }
622     }
623   } else {
624     m_connected_module_sdk_idx = UINT32_MAX;
625   }
626   return m_connected_module_sdk_idx;
627 }
628 
629 uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(
630     const SDKDirectoryInfo *sdk_info) {
631   if (sdk_info == NULL) {
632     return UINT32_MAX;
633   }
634 
635   return sdk_info - &m_sdk_directory_infos[0];
636 }
637