[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.

<rdar://problem/17750739>



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214285 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Lang Hames 2014-07-30 03:35:05 +00:00
parent e54c557b01
commit 1febfa28a4
7 changed files with 46 additions and 15 deletions

View File

@ -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<const MachOObjectFile &>(*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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -18,6 +18,9 @@ namespace llvm {
class RuntimeDyldMachOARM
: public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> {
private:
typedef RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> 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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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