diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -1102,11 +1102,11 @@ Symbol &addAbsoluteSymbol(StringRef Name, orc::ExecutorAddr Address, orc::ExecutorAddrDiff Size, Linkage L, Scope S, bool IsLive) { - assert(llvm::count_if(AbsoluteSymbols, - [&](const Symbol *Sym) { - return Sym->getName() == Name; - }) == 0 && - "Duplicate absolute symbol"); + assert(S == Scope::Local || llvm::count_if(AbsoluteSymbols, + [&](const Symbol *Sym) { + return Sym->getName() == Name; + }) == 0 && + "Duplicate absolute symbol"); auto &Sym = Symbol::constructAbsolute(Allocator.Allocate(), createAddressable(Address), Name, Size, L, S, IsLive); diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h @@ -53,6 +53,17 @@ /// the address space, otherwise an out-of-range error will be returned. Pointer32Signed, + /// A plain 16-bit pointer value relocation. + /// + /// Fixup expression: + /// Fixup <- Target + Addend : uint16 + /// + /// Errors: + /// - The target must reside in the low 16-bits of the address space, + /// otherwise an out-of-range error will be returned. + /// + Pointer16, + /// A 64-bit delta. /// /// Delta from the fixup to the target. @@ -415,6 +426,15 @@ break; } + case Pointer16: { + uint64_t Value = E.getTarget().getAddress().getValue() + E.getAddend(); + if (LLVM_LIKELY(isUInt<16>(Value))) + *(ulittle16_t *)FixupPtr = Value; + else + return makeTargetOutOfRangeError(G, B, E); + break; + } + case PCRel32: case BranchPCRel32: case BranchPCRel32ToPtrJumpStub: diff --git a/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp --- a/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp @@ -30,6 +30,8 @@ PCRel32 = x86_64::FirstPlatformRelocation, Pointer32NB, Pointer64, + SectionIdx16, + SecRel32, }; class COFFJITLinker_x86_64 : public JITLinker { @@ -144,6 +146,25 @@ Addend = *reinterpret_cast(FixupPtr); break; } + case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_SECTION: { + Kind = EdgeKind_coff_x86_64::SectionIdx16; + Addend = *reinterpret_cast(FixupPtr); + uint64_t SectionIdx = 0; + if (COFFSymbol.isAbsolute()) + SectionIdx = getObject().getNumberOfSections() + 1; + else + SectionIdx = COFFSymbol.getSectionNumber(); + auto *AbsSym = &getGraph().addAbsoluteSymbol( + "secidx", orc::ExecutorAddr(SectionIdx), 2, Linkage::Strong, + Scope::Local, false); + GraphSymbol = AbsSym; + break; + } + case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_SECREL: { + Kind = EdgeKind_coff_x86_64::SecRel32; + Addend = *reinterpret_cast(FixupPtr); + break; + } default: { return make_error("Unsupported x86_64 relocation:" + formatv("{0:d}", Rel.getType())); @@ -192,6 +213,17 @@ E.setKind(x86_64::Pointer64); break; } + case EdgeKind_coff_x86_64::SectionIdx16: { + E.setKind(x86_64::Pointer16); + break; + } + case EdgeKind_coff_x86_64::SecRel32: { + E.setAddend(E.getAddend() - + getSectionStart(E.getTarget().getBlock().getSection()) + .getValue()); + E.setKind(x86_64::Pointer32); + break; + } default: break; } @@ -202,6 +234,15 @@ private: static StringRef getImageBaseSymbolName() { return "__ImageBase"; } + + orc::ExecutorAddr getSectionStart(Section &Sec) { + if (!SectionStartCache.count(&Sec)) { + SectionRange Range(Sec); + SectionStartCache[&Sec] = Range.getStart(); + } + return SectionStartCache[&Sec]; + } + Expected getImageBaseAddress(LinkGraph &G, JITLinkContext &Ctx) { if (this->ImageBase) @@ -231,6 +272,8 @@ this->ImageBase = ImageBase; return ImageBase; } + + DenseMap
SectionStartCache; JITTargetAddress ImageBase = 0; }; @@ -257,6 +300,10 @@ return "Pointer32NB"; case Pointer64: return "Pointer64"; + case SectionIdx16: + return "SectionIdx16"; + case SecRel32: + return "SecRel32"; default: return x86_64::getEdgeKindName(R); } diff --git a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp --- a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp @@ -26,6 +26,8 @@ return "Pointer32"; case Pointer32Signed: return "Pointer32Signed"; + case Pointer16: + return "Pointer16"; case Delta64: return "Delta64"; case Delta32: diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp --- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -537,7 +537,8 @@ for (auto *B : G.blocks()) { auto &BI = BlockInfos[B]; for (auto &E : B->edges()) { - if (E.getTarget().getScope() == Scope::Local) { + if (E.getTarget().getScope() == Scope::Local && + !E.getTarget().isAbsolute()) { auto &TgtB = E.getTarget().getBlock(); if (&TgtB != B) { BI.Dependencies.insert(&TgtB); diff --git a/llvm/test/ExecutionEngine/JITLink/X86/COFF_section_relocs.test b/llvm/test/ExecutionEngine/JITLink/X86/COFF_section_relocs.test new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/X86/COFF_section_relocs.test @@ -0,0 +1,89 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-jitlink -noexec -abs __ImageBase=0xfff00000 \ +# RUN: -slab-allocate 100Kb -slab-address 0xfff00000 -slab-page-size 4096 \ +# RUN: -check %s %t +# +# Check IMAGE_REL_AMD64_SECTION and IMAGE_REL_AMD64_SECREL relocations +# are working correctly. +# +# jitlink-check: *{2}(sect) = 2 +# jitlink-check: *{4}(sect+2) = 4 +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: '0000000000000000' + - Name: .func + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: '0000000000000000' + - Name: .sect + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0000000000000000' + Relocations: + - VirtualAddress: 0 + SymbolTableIndex: 7 + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 2 + SymbolTableIndex: 7 + Type: IMAGE_REL_AMD64_SECREL +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + CheckSum: 0 + NumberOfLinenumbers: 0 + Number: 1 + - Name: .func + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + CheckSum: 0 + NumberOfLinenumbers: 0 + Number: 2 + - Name: .pdata + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 1 + CheckSum: 0 + NumberOfLinenumbers: 0 + Number: 3 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: func + Value: 4 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: sect + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL