[llvm] 0c69f9f - [ORC][COFF] Introduce DLLImportDefinitionGenerator.

Sunho Kim via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 15 10:07:04 PDT 2022


Author: Sunho Kim
Date: 2022-08-16T02:06:57+09:00
New Revision: 0c69f9f32c83002006a91639a950d9fd70f1b1bb

URL: https://github.com/llvm/llvm-project/commit/0c69f9f32c83002006a91639a950d9fd70f1b1bb
DIFF: https://github.com/llvm/llvm-project/commit/0c69f9f32c83002006a91639a950d9fd70f1b1bb.diff

LOG: [ORC][COFF] Introduce DLLImportDefinitionGenerator.

This class will be used to properly solve the `__imp_` symbol and jump-thunk generation issues. It is assumed to be the last definition generator to be called, and as it's the last generator the only symbols remaining in the lookup set are the symbols that are supposed to be queried outside this jitdylib. Instead of just letting them through, we issue another lookup invocation and fetch the allocated addresses, and then create jitlink graph containing `__imp_` GOT symbols and jump-thunks targetting the fetched addresses.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D131833

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 b60c086a7d2e..812313b68c7e 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -18,6 +18,7 @@
 #include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/Mangling.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
 #include "llvm/Object/Archive.h"
@@ -314,6 +315,40 @@ class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
   DenseMap<SymbolStringPtr, MemoryBufferRef> ObjectFilesMap;
 };
 
+/// A utility class to create COFF dllimport GOT symbols (__imp_*) and PLT
+/// stubs.
+///
+/// If an instance of this class is attached to a JITDylib as a fallback
+/// definition generator, PLT stubs and dllimport __imp_ symbols will be
+/// generated for external symbols found outside the given jitdylib. Currently
+/// only supports x86_64 architecture.
+class DLLImportDefinitionGenerator : public DefinitionGenerator {
+public:
+  /// Creates a DLLImportDefinitionGenerator instance.
+  static std::unique_ptr<DLLImportDefinitionGenerator>
+  Create(ExecutionSession &ES, ObjectLinkingLayer &L);
+
+  Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+                      JITDylibLookupFlags JDLookupFlags,
+                      const SymbolLookupSet &Symbols) override;
+
+private:
+  DLLImportDefinitionGenerator(ExecutionSession &ES, ObjectLinkingLayer &L)
+      : ES(ES), L(L) {}
+
+  static Expected<unsigned> getTargetPointerSize(const Triple &TT);
+  static Expected<support::endianness> getTargetEndianness(const Triple &TT);
+  Expected<std::unique_ptr<jitlink::LinkGraph>>
+  createStubsGraph(const SymbolMap &Resolved);
+
+  static StringRef getImpPrefix() { return "__imp_"; }
+
+  static StringRef getSectionName() { return "$__DLLIMPORT_STUBS"; }
+
+  ExecutionSession &ES;
+  ObjectLinkingLayer &L;
+};
+
 } // end namespace orc
 } // end namespace llvm
 

diff  --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 090e90cb3cf1..da96a5910122 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/JITLink/x86_64.h"
 #include "llvm/ExecutionEngine/Orc/Layer.h"
 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
 #include "llvm/IR/Constants.h"
@@ -350,7 +351,6 @@ StaticLibraryDefinitionGenerator::Create(
 Error StaticLibraryDefinitionGenerator::tryToGenerate(
     LookupState &LS, LookupKind K, JITDylib &JD,
     JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
-
   // Don't materialize symbols from static archives unless this is a static
   // lookup.
   if (K != LookupKind::Static)
@@ -430,5 +430,121 @@ StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
     Err = buildObjectFilesMap();
 }
 
+std::unique_ptr<DLLImportDefinitionGenerator>
+DLLImportDefinitionGenerator::Create(ExecutionSession &ES,
+                                     ObjectLinkingLayer &L) {
+  return std::unique_ptr<DLLImportDefinitionGenerator>(
+      new DLLImportDefinitionGenerator(ES, L));
+}
+
+Error DLLImportDefinitionGenerator::tryToGenerate(
+    LookupState &LS, LookupKind K, JITDylib &JD,
+    JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
+  JITDylibSearchOrder LinkOrder;
+  JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) {
+    LinkOrder.reserve(LO.size());
+    for (auto &KV : LO) {
+      if (KV.first == &JD)
+        continue;
+      LinkOrder.push_back(KV);
+    }
+  });
+
+  // FIXME: if regular symbol name start with __imp_ we have to issue lookup of
+  // both __imp_ and stripped name and use the lookup information to resolve the
+  // real symbol name.
+  SymbolLookupSet LookupSet;
+  DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols;
+  for (auto &KV : Symbols) {
+    StringRef Deinterned = *KV.first;
+    if (Deinterned.startswith(getImpPrefix()))
+      Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size());
+    // Don't degrade the required state
+    if (ToLookUpSymbols.count(Deinterned) &&
+        ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol)
+      continue;
+    ToLookUpSymbols[Deinterned] = KV.second;
+  }
+
+  for (auto &KV : ToLookUpSymbols)
+    LookupSet.add(ES.intern(KV.first), KV.second);
+
+  auto Resolved =
+      ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved);
+  if (!Resolved)
+    return Resolved.takeError();
+
+  auto G = createStubsGraph(*Resolved);
+  if (!G)
+    return G.takeError();
+  return L.add(JD, std::move(*G));
+}
+
+Expected<unsigned>
+DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) {
+  switch (TT.getArch()) {
+  case Triple::x86_64:
+    return 8;
+  default:
+    return make_error<StringError>(
+        "architecture unsupported by DLLImportDefinitionGenerator",
+        inconvertibleErrorCode());
+  }
+}
+
+Expected<support::endianness>
+DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) {
+  switch (TT.getArch()) {
+  case Triple::x86_64:
+    return support::endianness::little;
+  default:
+    return make_error<StringError>(
+        "architecture unsupported by DLLImportDefinitionGenerator",
+        inconvertibleErrorCode());
+  }
+}
+
+Expected<std::unique_ptr<jitlink::LinkGraph>>
+DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) {
+  Triple TT = ES.getExecutorProcessControl().getTargetTriple();
+  auto PointerSize = getTargetEndianness(TT);
+  if (!PointerSize)
+    return std::move(PointerSize.takeError());
+  auto Endianness = getTargetEndianness(TT);
+  if (!Endianness)
+    return std::move(Endianness.takeError());
+
+  auto G = std::make_unique<jitlink::LinkGraph>(
+      "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness,
+      jitlink::getGenericEdgeKindName);
+  jitlink::Section &Sec = G->createSection(
+      getSectionName(), jitlink::MemProt::Read | jitlink::MemProt::Exec);
+
+  for (auto &KV : Resolved) {
+    jitlink::Symbol &Target = G->addAbsoluteSymbol(
+        *KV.first, ExecutorAddr(KV.second.getAddress()), *PointerSize,
+        jitlink::Linkage::Strong, jitlink::Scope::Local, false);
+
+    // Create __imp_ symbol
+    jitlink::Symbol &Ptr =
+        jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target);
+    auto NameCopy = G->allocateString(Twine(getImpPrefix()) + *KV.first);
+    StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size());
+    Ptr.setName(NameCopyRef);
+    Ptr.setLinkage(jitlink::Linkage::Strong);
+    Ptr.setScope(jitlink::Scope::Default);
+
+    // Create PLT stub
+    // FIXME: check PLT stub of data symbol is not accessed
+    jitlink::Block &StubBlock =
+        jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr);
+    G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(),
+                        jitlink::Linkage::Strong, jitlink::Scope::Default, true,
+                        false);
+  }
+
+  return std::move(G);
+}
+
 } // End namespace orc.
 } // End namespace llvm.


        


More information about the llvm-commits mailing list