#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"
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
//===----------------------------------------------------------------------===//
#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"
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)
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.