diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h @@ -36,9 +36,22 @@ protected: RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr, - JITSymbolResolver &Resolver) - : RuntimeDyldImpl(MemMgr, Resolver) {} + JITSymbolResolver &Resolver, unsigned PointerSize, + uint32_t PointerReloc) + : RuntimeDyldImpl(MemMgr, Resolver), PointerSize(PointerSize), + PointerReloc(PointerReloc) { + assert((PointerSize == 4 || PointerSize == 8) && "Unexpected pointer size"); + } + uint64_t getSymbolOffset(const SymbolRef &Sym); + uint64_t getDLLImportOffset(unsigned SectionID, StubMap &Stubs, + StringRef Name); + + static constexpr StringRef getImportSymbolPrefix() { return "__imp_"; } + +private: + unsigned PointerSize; + uint32_t PointerReloc; }; } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -78,6 +78,27 @@ return Sym.getValue(); } +uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID, StubMap &Stubs, + StringRef Name) { + assert(Name.startswith(getImportSymbolPrefix()) && "Not a DLLImport symbol?"); + RelocationValueRef Reloc; + Reloc.SymbolName = Name.data(); + auto I = Stubs.find(Reloc); + if (I != Stubs.end()) + return I->second; + + assert(SectionID < Sections.size() && "SectionID out of range"); + auto &Sec = Sections[SectionID]; + auto EntryOffset = alignTo(Sec.getStubOffset(), PointerSize); + Sec.advanceStubOffset(EntryOffset + PointerSize - Sec.getStubOffset()); + Stubs[Reloc] = EntryOffset; + + RelocationEntry RE(SectionID, Sec.getStubOffset(), PointerReloc, 0, false, + Log2_64(PointerSize)); + addRelocationForSymbol(RE, Name.drop_front(getImportSymbolPrefix().size())); + return EntryOffset; +} + bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const { return Obj.isCOFF(); } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -191,13 +191,11 @@ class RelocationValueRef { public: - unsigned SectionID; - uint64_t Offset; - int64_t Addend; - const char *SymbolName; + unsigned SectionID = 0; + uint64_t Offset = 0; + int64_t Addend = 0; + const char *SymbolName = nullptr; bool IsStubThumb = false; - RelocationValueRef() : SectionID(0), Offset(0), Addend(0), - SymbolName(nullptr) {} inline bool operator==(const RelocationValueRef &Other) const { return SectionID == Other.SectionID && Offset == Other.Offset && diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h @@ -89,7 +89,8 @@ public: RuntimeDyldCOFFAArch64(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {} + : RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_ARM64_ADDR64), + ImageBase(0) {} unsigned getStubAlignment() override { return 8; } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h @@ -25,7 +25,7 @@ public: RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver) {} + : RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_I386_DIR32) {} unsigned getMaxStubSize() const override { return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad @@ -53,10 +53,28 @@ if (!SectionOrErr) return SectionOrErr.takeError(); auto Section = *SectionOrErr; + bool IsExtern = Section == Obj.section_end(); uint64_t RelType = RelI->getType(); uint64_t Offset = RelI->getOffset(); + unsigned TargetSectionID = -1; + uint64_t TargetOffset = -1; + if (!IsExtern) { + if (auto TargetSectionIDOrErr = findOrEmitSection( + Obj, *Section, Section->isText(), ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); + if (RelType != COFF::IMAGE_REL_I386_SECTION) + TargetOffset = getSymbolOffset(*Symbol); + } else if (TargetName.startswith(getImportSymbolPrefix())) { + TargetSectionID = SectionID; + TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName); + TargetName = StringRef(); + IsExtern = false; + } + // Determine the Addend used to adjust the relocation value. uint64_t Addend = 0; SectionEntry &AddendSection = Sections[SectionID]; @@ -83,16 +101,10 @@ << " RelType: " << RelTypeName << " TargetName: " << TargetName << " Addend " << Addend << "\n"); - unsigned TargetSectionID = -1; if (Section == Obj.section_end()) { RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); addRelocationForSymbol(RE, TargetName); } else { - if (auto TargetSectionIDOrErr = - findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID)) - TargetSectionID = *TargetSectionIDOrErr; - else - return TargetSectionIDOrErr.takeError(); switch (RelType) { case COFF::IMAGE_REL_I386_ABSOLUTE: @@ -103,7 +115,7 @@ case COFF::IMAGE_REL_I386_REL32: { RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, - getSymbolOffset(*Symbol), 0, 0, false, 0); + TargetOffset, 0, 0, false, 0); addRelocationForSection(RE, TargetSectionID); break; } @@ -114,8 +126,8 @@ break; } case COFF::IMAGE_REL_I386_SECREL: { - RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, - getSymbolOffset(*Symbol) + Addend); + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend); addRelocationForSection(RE, TargetSectionID); break; } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h @@ -48,7 +48,7 @@ public: RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver) {} + : RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_ARM_ADDR32) {} unsigned getMaxStubSize() const override { return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -56,7 +56,8 @@ public: RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {} + : RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_AMD64_ADDR64), + ImageBase(0) {} unsigned getStubAlignment() override { return 1; } @@ -202,7 +203,7 @@ return SectionOrError.takeError(); object::section_iterator SecI = *SectionOrError; // If there is no section, this must be an external reference. - const bool IsExtern = SecI == Obj.section_end(); + bool IsExtern = SecI == Obj.section_end(); // Determine the Addend used to adjust the relocation value. uint64_t RelType = RelI->getType(); @@ -214,7 +215,26 @@ Expected TargetNameOrErr = Symbol->getName(); if (!TargetNameOrErr) return TargetNameOrErr.takeError(); + StringRef TargetName = *TargetNameOrErr; + unsigned TargetSectionID = 0; + uint64_t TargetOffset = 0; + bool IsCode = SecI->isText(); + + if (TargetName.startswith(getImportSymbolPrefix())) { + assert(IsExtern && "DLLImport not marked extern?"); + TargetSectionID = SectionID; + TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName); + TargetName = StringRef(); + IsExtern = false; + } else if (!IsExtern) { + if (auto TargetSectionIDOrErr = + findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); + TargetOffset = getSymbolOffset(*Symbol); + } switch (RelType) { @@ -253,14 +273,6 @@ RelocationEntry RE(SectionID, Offset, RelType, Addend); addRelocationForSymbol(RE, TargetName); } else { - bool IsCode = SecI->isText(); - unsigned TargetSectionID; - if (auto TargetSectionIDOrErr = - findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID)) - TargetSectionID = *TargetSectionIDOrErr; - else - return TargetSectionIDOrErr.takeError(); - uint64_t TargetOffset = getSymbolOffset(*Symbol); RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); addRelocationForSection(RE, TargetSectionID); }