[llvm] 171ffd4 - [ORC] StaticLibraryDefinitionGenerator -- support in-memory universal binaries.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 13 08:54:01 PST 2023


Author: Lang Hames
Date: 2023-02-13T08:53:53-08:00
New Revision: 171ffd499e16f365ab1987697922c5e5b3efa113

URL: https://github.com/llvm/llvm-project/commit/171ffd499e16f365ab1987697922c5e5b3efa113
DIFF: https://github.com/llvm/llvm-project/commit/171ffd499e16f365ab1987697922c5e5b3efa113.diff

LOG: [ORC] StaticLibraryDefinitionGenerator -- support in-memory universal binaries.

Add new StaticLibraryDefinitionGenerator::Create methods to support construction
from in-memory universal binaries.

Added: 
    

Modified: 
    llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
    llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index 812313b68c7e2..4d2b228bea807 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -36,6 +36,10 @@ class Function;
 class Module;
 class Value;
 
+namespace object {
+class MachOUniversalBinary;
+}
+
 namespace orc {
 
 class ObjectLayer;
@@ -281,6 +285,13 @@ class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
   Load(ObjectLayer &L, const char *FileName, const Triple &TT,
        GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
 
+  /// Try to create a StaticLibrarySearchGenerator from the given memory buffer
+  /// and Archive object.
+  static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+  Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+         std::unique_ptr<object::Archive> Archive,
+         GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
+
   /// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
   /// This call will succeed if the buffer contains a valid archive, otherwise
   /// it will return an error.
@@ -288,6 +299,16 @@ class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
   Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
          GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
 
+  /// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
+  ///
+  /// This call will succeed if the buffer contains a valid static library or a
+  /// MachO universal binary containing a static library that is compatible
+  /// with the given triple. Otherwise it will return an error.
+  static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+  Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+         const Triple &TT,
+         GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
+
   /// Returns a list of filenames of dynamic libraries that this archive has
   /// imported. This class does not load these libraries by itself. User is
   /// responsible for making sure these libraries are avaliable to the JITDylib.
@@ -302,11 +323,14 @@ class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
 private:
   StaticLibraryDefinitionGenerator(ObjectLayer &L,
                                    std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+                                   std::unique_ptr<object::Archive> Archive,
                                    GetObjectFileInterface GetObjFileInterface,
                                    Error &Err);
-
   Error buildObjectFilesMap();
 
+  static Expected<std::pair<size_t, size_t>>
+  getSliceRangeForArch(object::MachOUniversalBinary &UB, const Triple &TT);
+
   ObjectLayer &L;
   GetObjectFileInterface GetObjFileInterface;
   std::set<std::string> ImportedDynamicLibraries;

diff  --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 409174dac3c28..b21c81abbfec1 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -299,32 +299,22 @@ StaticLibraryDefinitionGenerator::Load(
   // If this is a universal binary then search for a slice matching the given
   // Triple.
   if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) {
-    for (const auto &Obj : UB->objects()) {
-      auto ObjTT = Obj.getTriple();
-      if (ObjTT.getArch() == TT.getArch() &&
-          ObjTT.getSubArch() == TT.getSubArch() &&
-          (TT.getVendor() == Triple::UnknownVendor ||
-           ObjTT.getVendor() == TT.getVendor())) {
-        // We found a match. Create an instance from a buffer covering this
-        // slice.
-        auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(),
-                                                      Obj.getOffset());
-        if (!SliceBuffer)
-          return make_error<StringError>(
-              Twine("Could not create buffer for ") + TT.str() + " slice of " +
-                  FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) +
-                  " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) +
-                  ": " + SliceBuffer.getError().message(),
-              SliceBuffer.getError());
-        return Create(L, std::move(*SliceBuffer),
-                      std::move(GetObjFileInterface));
-      }
-    }
 
-    return make_error<StringError>(Twine("Universal binary ") + FileName +
-                                       " does not contain a slice for " +
-                                       TT.str(),
-                                   inconvertibleErrorCode());
+    auto SliceRange = getSliceRangeForArch(*UB, TT);
+    if (!SliceRange)
+      return SliceRange.takeError();
+
+    auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, SliceRange->second,
+                                                  SliceRange->first);
+    if (!SliceBuffer)
+      return make_error<StringError>(
+          Twine("Could not create buffer for ") + TT.str() + " slice of " +
+              FileName + ": [ " + formatv("{0:x}", SliceRange->first) + " .. " +
+              formatv("{0:x}", SliceRange->first + SliceRange->second) + ": " +
+              SliceBuffer.getError().message(),
+          SliceBuffer.getError());
+
+    return Create(L, std::move(*SliceBuffer), std::move(GetObjFileInterface));
   }
 
   return make_error<StringError>(Twine("Unrecognized file type for ") +
@@ -335,12 +325,15 @@ StaticLibraryDefinitionGenerator::Load(
 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
 StaticLibraryDefinitionGenerator::Create(
     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+    std::unique_ptr<object::Archive> Archive,
     GetObjectFileInterface GetObjFileInterface) {
+
   Error Err = Error::success();
 
   std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
       new StaticLibraryDefinitionGenerator(
-          L, std::move(ArchiveBuffer), std::move(GetObjFileInterface), Err));
+          L, std::move(ArchiveBuffer), std::move(Archive),
+          std::move(GetObjFileInterface), Err));
 
   if (Err)
     return std::move(Err);
@@ -348,6 +341,57 @@ StaticLibraryDefinitionGenerator::Create(
   return std::move(ADG);
 }
 
+Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+StaticLibraryDefinitionGenerator::Create(
+    ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+    GetObjectFileInterface GetObjFileInterface) {
+
+  auto Archive = object::Archive::create(ArchiveBuffer->getMemBufferRef());
+  if (!Archive)
+    return Archive.takeError();
+
+  return Create(L, std::move(ArchiveBuffer), std::move(*Archive),
+                std::move(GetObjFileInterface));
+}
+
+Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
+StaticLibraryDefinitionGenerator::Create(
+    ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+    const Triple &TT, GetObjectFileInterface GetObjFileInterface) {
+
+  auto B = object::createBinary(ArchiveBuffer->getMemBufferRef());
+  if (!B)
+    return B.takeError();
+
+  // If this is a regular archive then create an instance from it.
+  if (isa<object::Archive>(*B))
+    return Create(L, std::move(ArchiveBuffer), std::move(GetObjFileInterface));
+
+  // If this is a universal binary then search for a slice matching the given
+  // Triple.
+  if (auto *UB = cast<object::MachOUniversalBinary>(B->get())) {
+    auto SliceRange = getSliceRangeForArch(*UB, TT);
+    if (!SliceRange)
+      return SliceRange.takeError();
+
+    MemoryBufferRef SliceRef(
+        StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first,
+                  SliceRange->second),
+        ArchiveBuffer->getBufferIdentifier());
+
+    auto Archive = object::Archive::create(SliceRef);
+    if (!Archive)
+      return Archive.takeError();
+
+    return Create(L, std::move(ArchiveBuffer), std::move(*Archive),
+                  std::move(GetObjFileInterface));
+  }
+
+  return make_error<StringError>(Twine("Unrecognized file type for ") +
+                                     ArchiveBuffer->getBufferIdentifier(),
+                                 inconvertibleErrorCode());
+}
+
 Error StaticLibraryDefinitionGenerator::tryToGenerate(
     LookupState &LS, LookupKind K, JITDylib &JD,
     JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
@@ -417,12 +461,33 @@ Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() {
   return Error::success();
 }
 
+Expected<std::pair<size_t, size_t>>
+StaticLibraryDefinitionGenerator::getSliceRangeForArch(
+    object::MachOUniversalBinary &UB, const Triple &TT) {
+
+  for (const auto &Obj : UB.objects()) {
+    auto ObjTT = Obj.getTriple();
+    if (ObjTT.getArch() == TT.getArch() &&
+        ObjTT.getSubArch() == TT.getSubArch() &&
+        (TT.getVendor() == Triple::UnknownVendor ||
+         ObjTT.getVendor() == TT.getVendor())) {
+      // We found a match. Return the range for the slice.
+      return std::make_pair(Obj.getOffset(), Obj.getSize());
+    }
+  }
+
+  return make_error<StringError>(Twine("Universal binary ") + UB.getFileName() +
+                                     " does not contain a slice for " +
+                                     TT.str(),
+                                 inconvertibleErrorCode());
+}
+
 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
+    std::unique_ptr<object::Archive> Archive,
     GetObjectFileInterface GetObjFileInterface, Error &Err)
     : L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
-      ArchiveBuffer(std::move(ArchiveBuffer)),
-      Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {
+      ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) {
   ErrorAsOutParameter _(&Err);
   if (!this->GetObjFileInterface)
     this->GetObjFileInterface = getObjectFileInterface;


        


More information about the llvm-commits mailing list