From: Lang Hames Date: Wed, 30 Jul 2014 03:35:05 +0000 (+0000) Subject: [MCJIT] Fix the ARM BR24 relocation in RuntimeDyldMachO. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=1febfa28a46094f27ce71578fd419d5ef43cfcad [MCJIT] Fix the ARM BR24 relocation in RuntimeDyldMachO. We now (1) correctly decode the branch immediate, (2) modify the immediate to corretly treat it as PC-rel, and (3) properly populate the stub entry. Previously we had been doing each of these wrong. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214285 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 920b999fa08..bae2471054d 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -79,7 +79,8 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, ObjectImage &ObjImg, - const relocation_iterator &RI) { + const relocation_iterator &RI, + unsigned OffsetToNextPC) { const MachOObjectFile &Obj = static_cast(*ObjImg.getObjectFile()); MachO::any_relocation_info RelInfo = @@ -89,8 +90,7 @@ void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, if (IsPCRel) { uint64_t RelocAddr = 0; RI->getAddress(RelocAddr); - unsigned RelocSize = Obj.getAnyRelocationLength(RelInfo); - Value.Addend += RelocAddr + (1ULL << RelocSize); + Value.Addend += RelocAddr + OffsetToNextPC; } } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 7450f1141e1..30f61e98e32 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -73,7 +73,8 @@ protected: /// Make the RelocationValueRef addend PC-relative. void makeValueAddendPCRel(RelocationValueRef &Value, ObjectImage &ObjImg, - const relocation_iterator &RI); + const relocation_iterator &RI, + unsigned OffsetToNextPC); /// Dump information about the relocation entry (RE) and resolved value. void dumpRelocationToResolve(const RelocationEntry &RE, uint64_t Value) const; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index 967b12ff440..ced85f3e55a 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -276,7 +276,7 @@ public: bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); RE.Addend = Value.Addend; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 1de99421982..dadde769656 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -18,6 +18,9 @@ namespace llvm { class RuntimeDyldMachOARM : public RuntimeDyldMachOCRTPBase { +private: + typedef RuntimeDyldMachOCRTPBase ParentT; + public: RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} @@ -25,6 +28,21 @@ public: unsigned getStubAlignment() override { return 4; } + int64_t decodeAddend(uint8_t *LocalAddress, unsigned NumBytes, + MachO::RelocationInfoType RelType) const { + switch (RelType) { + default: + return ParentT::decodeAddend(LocalAddress, NumBytes, RelType); + case MachO::ARM_RELOC_BR24: { + uint32_t Temp; + memcpy(&Temp, LocalAddress, 4); + Temp &= 0x00ffffff; // Mask out the opcode. + // Now we've got the shifted immediate, shift by 2, sign extend and ret. + return SignExtend32<26>(Temp << 2); + } + } + } + relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, @@ -41,9 +59,8 @@ public: RelocationValueRef Value( getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); - bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); - if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + if (RE.IsPCRel) + makeValueAddendPCRel(Value, ObjImg, RelI, 8); if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) processBranchRelocation(RE, Value, Stubs); @@ -134,7 +151,8 @@ private: uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry StubRE(RE.SectionID, StubTargetAddr - Section.Address, - MachO::GENERIC_RELOC_VANILLA, Value.Addend); + MachO::GENERIC_RELOC_VANILLA, Value.Addend, false, + 2); if (Value.SymbolName) addRelocationForSymbol(StubRE, Value.SymbolName); else @@ -142,7 +160,7 @@ private: Addr = Section.Address + Section.StubOffset; Section.StubOffset += getMaxStubSize(); } - RelocationEntry TargetRE(Value.SectionID, RE.Offset, RE.RelType, 0, + RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0, RE.IsPCRel, RE.Size); resolveRelocation(TargetRE, (uint64_t)Addr); } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 856c6ca3035..156287b3af1 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -62,7 +62,7 @@ public: // Value.Addend += RelocAddr + 4; // } if (RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); RE.Addend = Value.Addend; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 99efe9da448..9106f415422 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -44,7 +44,7 @@ public: bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); if (RE.RelType == MachO::X86_64_RELOC_GOT || RE.RelType == MachO::X86_64_RELOC_GOT_LOAD) diff --git a/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s b/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s index 86041835591..d0d30271f0d 100644 --- a/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s +++ b/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s @@ -1,6 +1,5 @@ -# RUN: llvm-mc -triple=armv7s-apple-ios7.0.0 -relocation-model=pic -filetype=obj -o %t.o %s -# RUN: llvm-rtdyld -triple=armv7s-apple-ios7.0.0 -verify -check=%s %t.o -# RUN: rm %t.o +# RUN: llvm-mc -triple=armv7s-apple-ios7.0.0 -relocation-model=pic -filetype=obj -o %T/foo.o %s +# RUN: llvm-rtdyld -triple=armv7s-apple-ios7.0.0 -verify -check=%s %/T/foo.o .syntax unified .section __TEXT,__text,regular,pure_instructions @@ -17,6 +16,17 @@ insn2: movt r0, :upper16:(foo-(nextPC+8)) nextPC: add r0, pc, r0 + +# Check stub generation by referencing a common symbol, 'baz'. Check both the +# Content of the stub, and the reference to the stub. +# Stub should contain '0xe51ff004' (ldr pc, [pc, #-4]), followed by the target. +# +# rtdyld-check: *{4}(stub_addr(foo.o, __text, baz)) = 0xe51ff004 +# rtdyld-check: *{4}(stub_addr(foo.o, __text, baz) + 4) = baz +# +# rtdyld-check: decode_operand(insn3, 0) = stub_addr(foo.o, __text, baz) - (insn3 + 8) +insn3: + bl baz bx lr .globl foo @@ -24,4 +34,6 @@ nextPC: foo: bx lr + .comm baz, 4, 2 + .subsections_via_symbols