JDevlieghere created this revision.
JDevlieghere added reviewers: jasonmolenda, labath.

When loading kexts in `PlatformDarwinKernel`, we use the BundleID as the 
filename to to create shared modules. In `GetSharedModule` we call 
`ExamineKextForMatchingUUID` for any BundleID it finds that is a match, to see 
if the UUID is also a match. Until now we were using 
`Host::ResolveExecutableInBundle` whcih calls a CoreFoundation API to obtain 
the executable. However, it's possible that the executable has a variant suffix 
(e.g. foo_development) and these files were ignored.

This patch replaces that call with logic that looks for all the binaries in the 
bundle. Because of the way `ExamineKextForMatchingUUID` works, it's fine to try 
to load executables that are not valid and we can just iterate over the list 
until we found a match.

(I put it up for review so I can get feedback while I look into adding a test)


https://reviews.llvm.org/D47539

Files:
  source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
  source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h


Index: source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
===================================================================
--- source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
+++ source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
@@ -127,6 +127,9 @@
                                       const lldb_private::FileSpec &file_spec,
                                       bool recurse);
 
+  std::vector<lldb_private::FileSpec>
+  SearchForExecutablesRecursively(const lldb_private::ConstString &dir);
+
   static void AddKextToMap(PlatformDarwinKernel *thisp,
                            const lldb_private::FileSpec &file_spec);
 
Index: source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
===================================================================
--- source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -779,35 +779,59 @@
   return error;
 }
 
+std::vector<lldb_private::FileSpec>
+PlatformDarwinKernel::SearchForExecutablesRecursively(const ConstString &dir) {
+  std::vector<lldb_private::FileSpec> executables;
+
+  auto callback = [&](llvm::sys::fs::file_type ft,
+                      const lldb_private::FileSpec &file_spec)
+      -> lldb_private::FileSpec::EnumerateDirectoryResult {
+    llvm::SmallString<64> file_path;
+    file_spec.GetPath(file_path, false);
+    if (llvm::sys::fs::can_execute(file_path))
+      executables.push_back(file_spec);
+    return FileSpec::eEnumerateDirectoryResultNext;
+  };
+
+  const bool find_directories = false;
+  const bool find_files = true;
+  const bool find_other = false;
+  FileSpec::EnumerateDirectory(dir.GetCString(), find_directories, find_files,
+                               find_other, callback);
+
+  return executables;
+}
+
 Status PlatformDarwinKernel::ExamineKextForMatchingUUID(
     const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid,
     const ArchSpec &arch, ModuleSP &exe_module_sp) {
-  Status error;
-  FileSpec exe_file = kext_bundle_path;
-  Host::ResolveExecutableInBundle(exe_file);
-  if (exe_file.Exists()) {
-    ModuleSpec exe_spec(exe_file);
-    exe_spec.GetUUID() = uuid;
-    if (!uuid.IsValid()) {
-      exe_spec.GetArchitecture() = arch;
-    }
+  for (const auto &exe_file :
+       SearchForExecutablesRecursively(kext_bundle_path.GetDirectory())) {
+    if (exe_file.Exists()) {
+      ModuleSpec exe_spec(exe_file);
+      exe_spec.GetUUID() = uuid;
+      if (!uuid.IsValid()) {
+        exe_spec.GetArchitecture() = arch;
+      }
 
-    // First try to create a ModuleSP with the file / arch and see if the UUID
-    // matches. If that fails (this exec file doesn't have the correct uuid),
-    // don't call GetSharedModule (which may call in to the DebugSymbols
-    // framework and therefore can be slow.)
-    ModuleSP module_sp(new Module(exe_spec));
-    if (module_sp && module_sp->GetObjectFile() &&
-        module_sp->MatchesModuleSpec(exe_spec)) {
-      error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, NULL, NULL,
-                                          NULL);
-      if (exe_module_sp && exe_module_sp->GetObjectFile()) {
-        return error;
+      // First try to create a ModuleSP with the file / arch and see if the 
UUID
+      // matches. If that fails (this exec file doesn't have the correct uuid),
+      // don't call GetSharedModule (which may call in to the DebugSymbols
+      // framework and therefore can be slow.)
+      ModuleSP module_sp(new Module(exe_spec));
+      if (module_sp && module_sp->GetObjectFile() &&
+          module_sp->MatchesModuleSpec(exe_spec)) {
+        Status error = ModuleList::GetSharedModule(exe_spec, exe_module_sp,
+                                                   NULL, NULL, NULL);
+        if (exe_module_sp && exe_module_sp->GetObjectFile()) {
+          return error;
+        }
       }
+      exe_module_sp.reset();
     }
-    exe_module_sp.reset();
   }
-  return error;
+
+  return {};
 }
 
 bool PlatformDarwinKernel::GetSupportedArchitectureAtIndex(uint32_t idx,


Index: source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
===================================================================
--- source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
+++ source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
@@ -127,6 +127,9 @@
                                       const lldb_private::FileSpec &file_spec,
                                       bool recurse);
 
+  std::vector<lldb_private::FileSpec>
+  SearchForExecutablesRecursively(const lldb_private::ConstString &dir);
+
   static void AddKextToMap(PlatformDarwinKernel *thisp,
                            const lldb_private::FileSpec &file_spec);
 
Index: source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
===================================================================
--- source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -779,35 +779,59 @@
   return error;
 }
 
+std::vector<lldb_private::FileSpec>
+PlatformDarwinKernel::SearchForExecutablesRecursively(const ConstString &dir) {
+  std::vector<lldb_private::FileSpec> executables;
+
+  auto callback = [&](llvm::sys::fs::file_type ft,
+                      const lldb_private::FileSpec &file_spec)
+      -> lldb_private::FileSpec::EnumerateDirectoryResult {
+    llvm::SmallString<64> file_path;
+    file_spec.GetPath(file_path, false);
+    if (llvm::sys::fs::can_execute(file_path))
+      executables.push_back(file_spec);
+    return FileSpec::eEnumerateDirectoryResultNext;
+  };
+
+  const bool find_directories = false;
+  const bool find_files = true;
+  const bool find_other = false;
+  FileSpec::EnumerateDirectory(dir.GetCString(), find_directories, find_files,
+                               find_other, callback);
+
+  return executables;
+}
+
 Status PlatformDarwinKernel::ExamineKextForMatchingUUID(
     const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid,
     const ArchSpec &arch, ModuleSP &exe_module_sp) {
-  Status error;
-  FileSpec exe_file = kext_bundle_path;
-  Host::ResolveExecutableInBundle(exe_file);
-  if (exe_file.Exists()) {
-    ModuleSpec exe_spec(exe_file);
-    exe_spec.GetUUID() = uuid;
-    if (!uuid.IsValid()) {
-      exe_spec.GetArchitecture() = arch;
-    }
+  for (const auto &exe_file :
+       SearchForExecutablesRecursively(kext_bundle_path.GetDirectory())) {
+    if (exe_file.Exists()) {
+      ModuleSpec exe_spec(exe_file);
+      exe_spec.GetUUID() = uuid;
+      if (!uuid.IsValid()) {
+        exe_spec.GetArchitecture() = arch;
+      }
 
-    // First try to create a ModuleSP with the file / arch and see if the UUID
-    // matches. If that fails (this exec file doesn't have the correct uuid),
-    // don't call GetSharedModule (which may call in to the DebugSymbols
-    // framework and therefore can be slow.)
-    ModuleSP module_sp(new Module(exe_spec));
-    if (module_sp && module_sp->GetObjectFile() &&
-        module_sp->MatchesModuleSpec(exe_spec)) {
-      error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, NULL, NULL,
-                                          NULL);
-      if (exe_module_sp && exe_module_sp->GetObjectFile()) {
-        return error;
+      // First try to create a ModuleSP with the file / arch and see if the UUID
+      // matches. If that fails (this exec file doesn't have the correct uuid),
+      // don't call GetSharedModule (which may call in to the DebugSymbols
+      // framework and therefore can be slow.)
+      ModuleSP module_sp(new Module(exe_spec));
+      if (module_sp && module_sp->GetObjectFile() &&
+          module_sp->MatchesModuleSpec(exe_spec)) {
+        Status error = ModuleList::GetSharedModule(exe_spec, exe_module_sp,
+                                                   NULL, NULL, NULL);
+        if (exe_module_sp && exe_module_sp->GetObjectFile()) {
+          return error;
+        }
       }
+      exe_module_sp.reset();
     }
-    exe_module_sp.reset();
   }
-  return error;
+
+  return {};
 }
 
 bool PlatformDarwinKernel::GetSupportedArchitectureAtIndex(uint32_t idx,
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to