mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
[MCJIT] Add support for ARM HALF_DIFF relocations to MCJIT.
Fixes <rdar://problem/18297804>. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217620 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
11e375565a
commit
67868b5791
@ -108,6 +108,64 @@ void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE,
|
||||
<< " Size: " << (1 << RE.Size) << "\n";
|
||||
}
|
||||
|
||||
section_iterator
|
||||
RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
|
||||
uint64_t Addr) {
|
||||
section_iterator SI = Obj.section_begin();
|
||||
section_iterator SE = Obj.section_end();
|
||||
|
||||
for (; SI != SE; ++SI) {
|
||||
uint64_t SAddr, SSize;
|
||||
SI->getAddress(SAddr);
|
||||
SI->getSize(SSize);
|
||||
if ((Addr >= SAddr) && (Addr < SAddr + SSize))
|
||||
return SI;
|
||||
}
|
||||
|
||||
return SE;
|
||||
}
|
||||
|
||||
|
||||
// Populate __pointers section.
|
||||
void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
||||
MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID) {
|
||||
assert(!Obj.is64Bit() &&
|
||||
"Pointer table section not supported in 64-bit MachO.");
|
||||
|
||||
MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
|
||||
MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
|
||||
uint32_t PTSectionSize = Sec32.size;
|
||||
unsigned FirstIndirectSymbol = Sec32.reserved1;
|
||||
const unsigned PTEntrySize = 4;
|
||||
unsigned NumPTEntries = PTSectionSize / PTEntrySize;
|
||||
unsigned PTEntryOffset = 0;
|
||||
|
||||
assert((PTSectionSize % PTEntrySize) == 0 &&
|
||||
"Pointers section does not contain a whole number of stubs?");
|
||||
|
||||
DEBUG(dbgs() << "Populating pointer table section "
|
||||
<< Sections[PTSectionID].Name
|
||||
<< ", Section ID " << PTSectionID << ", "
|
||||
<< NumPTEntries << " entries, " << PTEntrySize
|
||||
<< " bytes each:\n");
|
||||
|
||||
for (unsigned i = 0; i < NumPTEntries; ++i) {
|
||||
unsigned SymbolIndex =
|
||||
Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
|
||||
symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
|
||||
StringRef IndirectSymbolName;
|
||||
SI->getName(IndirectSymbolName);
|
||||
DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex
|
||||
<< ", PT offset: " << PTEntryOffset << "\n");
|
||||
RelocationEntry RE(PTSectionID, PTEntryOffset,
|
||||
MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
|
||||
addRelocationForSymbol(RE, IndirectSymbolName);
|
||||
PTEntryOffset += PTEntrySize;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const {
|
||||
if (InputBuffer->getBufferSize() < 4)
|
||||
|
@ -101,6 +101,16 @@ protected:
|
||||
/// Dump information about the relocation entry (RE) and resolved value.
|
||||
void dumpRelocationToResolve(const RelocationEntry &RE, uint64_t Value) const;
|
||||
|
||||
// Return a section iterator for the section containing the given address.
|
||||
static section_iterator getSectionByAddress(const MachOObjectFile &Obj,
|
||||
uint64_t Addr);
|
||||
|
||||
|
||||
// Populate __pointers section.
|
||||
void populateIndirectSymbolPointersSection(MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID);
|
||||
|
||||
public:
|
||||
/// Create an ObjectImage from the given ObjectBuffer.
|
||||
static std::unique_ptr<ObjectImage>
|
||||
|
@ -56,9 +56,15 @@ public:
|
||||
static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
|
||||
MachO::any_relocation_info RelInfo =
|
||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||
uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
|
||||
|
||||
if (Obj.isRelocationScattered(RelInfo))
|
||||
return ++++RelI;
|
||||
if (Obj.isRelocationScattered(RelInfo)) {
|
||||
if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF)
|
||||
return processHALFSECTDIFFRelocation(SectionID, RelI, ObjImg,
|
||||
ObjSectionToID);
|
||||
else
|
||||
return ++++RelI;
|
||||
}
|
||||
|
||||
RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI));
|
||||
RE.Addend = decodeAddend(RE);
|
||||
@ -120,10 +126,26 @@ public:
|
||||
*p = (*p & ~0xffffff) | FinalValue;
|
||||
break;
|
||||
}
|
||||
case MachO::ARM_RELOC_HALF_SECTDIFF: {
|
||||
uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress;
|
||||
uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress;
|
||||
assert((Value == SectionABase || Value == SectionBBase) &&
|
||||
"Unexpected HALFSECTDIFF relocation value.");
|
||||
Value = SectionABase - SectionBBase + RE.Addend;
|
||||
if (RE.Size & 0x1) // :upper16:
|
||||
Value = (Value >> 16);
|
||||
Value &= 0xffff;
|
||||
|
||||
uint32_t Insn;
|
||||
memcpy(&Insn, LocalAddress, 4);
|
||||
Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff);
|
||||
memcpy(LocalAddress, &Insn, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case MachO::ARM_THUMB_RELOC_BR22:
|
||||
case MachO::ARM_THUMB_32BIT_BRANCH:
|
||||
case MachO::ARM_RELOC_HALF:
|
||||
case MachO::ARM_RELOC_HALF_SECTDIFF:
|
||||
case MachO::ARM_RELOC_PAIR:
|
||||
case MachO::ARM_RELOC_SECTDIFF:
|
||||
case MachO::ARM_RELOC_LOCAL_SECTDIFF:
|
||||
@ -134,9 +156,18 @@ public:
|
||||
}
|
||||
|
||||
void finalizeSection(ObjectImage &ObjImg, unsigned SectionID,
|
||||
const SectionRef &Section) {}
|
||||
const SectionRef &Section) {
|
||||
StringRef Name;
|
||||
Section.getName(Name);
|
||||
|
||||
if (Name == "__nl_symbol_ptr")
|
||||
populateIndirectSymbolPointersSection(
|
||||
cast<MachOObjectFile>(*ObjImg.getObjectFile()),
|
||||
Section, SectionID);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void processBranchRelocation(const RelocationEntry &RE,
|
||||
const RelocationValueRef &Value,
|
||||
StubMap &Stubs) {
|
||||
@ -166,6 +197,83 @@ private:
|
||||
RE.IsPCRel, RE.Size);
|
||||
resolveRelocation(TargetRE, (uint64_t)Addr);
|
||||
}
|
||||
|
||||
relocation_iterator
|
||||
processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
|
||||
ObjectImage &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID) {
|
||||
const MachOObjectFile *MachO =
|
||||
static_cast<const MachOObjectFile *>(Obj.getObjectFile());
|
||||
MachO::any_relocation_info RE =
|
||||
MachO->getRelocation(RelI->getRawDataRefImpl());
|
||||
|
||||
|
||||
// For a half-diff relocation the length bits actually record whether this
|
||||
// is a movw/movt, and whether this is arm or thumb.
|
||||
// Bit 0 indicates movw (b0 == 0) or movt (b0 == 1).
|
||||
// Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1).
|
||||
unsigned HalfDiffKindBits = MachO->getAnyRelocationLength(RE);
|
||||
if (HalfDiffKindBits & 0x2)
|
||||
llvm_unreachable("Thumb not yet supported.");
|
||||
|
||||
SectionEntry &Section = Sections[SectionID];
|
||||
uint32_t RelocType = MachO->getAnyRelocationType(RE);
|
||||
bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
|
||||
uint64_t Offset;
|
||||
RelI->getOffset(Offset);
|
||||
uint8_t *LocalAddress = Section.Address + Offset;
|
||||
int64_t Immediate = 0;
|
||||
memcpy(&Immediate, LocalAddress, 4); // Copy the whole instruction out.
|
||||
Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff);
|
||||
|
||||
++RelI;
|
||||
MachO::any_relocation_info RE2 =
|
||||
MachO->getRelocation(RelI->getRawDataRefImpl());
|
||||
uint32_t AddrA = MachO->getScatteredRelocationValue(RE);
|
||||
section_iterator SAI = getSectionByAddress(*MachO, AddrA);
|
||||
assert(SAI != MachO->section_end() && "Can't find section for address A");
|
||||
uint64_t SectionABase;
|
||||
SAI->getAddress(SectionABase);
|
||||
uint64_t SectionAOffset = AddrA - SectionABase;
|
||||
SectionRef SectionA = *SAI;
|
||||
bool IsCode;
|
||||
SectionA.isText(IsCode);
|
||||
uint32_t SectionAID =
|
||||
findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID);
|
||||
|
||||
uint32_t AddrB = MachO->getScatteredRelocationValue(RE2);
|
||||
section_iterator SBI = getSectionByAddress(*MachO, AddrB);
|
||||
assert(SBI != MachO->section_end() && "Can't find section for address B");
|
||||
uint64_t SectionBBase;
|
||||
SBI->getAddress(SectionBBase);
|
||||
uint64_t SectionBOffset = AddrB - SectionBBase;
|
||||
SectionRef SectionB = *SBI;
|
||||
uint32_t SectionBID =
|
||||
findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID);
|
||||
|
||||
uint32_t OtherHalf = MachO->getAnyRelocationAddress(RE2) & 0xffff;
|
||||
unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0;
|
||||
uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift));
|
||||
int64_t Addend = FullImmVal - (AddrA - AddrB);
|
||||
|
||||
// addend = Encoded - Expected
|
||||
// = Encoded - (AddrA - AddrB)
|
||||
|
||||
DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB
|
||||
<< ", Addend: " << Addend << ", SectionA ID: " << SectionAID
|
||||
<< ", SectionAOffset: " << SectionAOffset
|
||||
<< ", SectionB ID: " << SectionBID
|
||||
<< ", SectionBOffset: " << SectionBOffset << "\n");
|
||||
RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID,
|
||||
SectionAOffset, SectionBID, SectionBOffset, IsPCRel,
|
||||
HalfDiffKindBits);
|
||||
|
||||
addRelocationForSection(R, SectionAID);
|
||||
addRelocationForSection(R, SectionBID);
|
||||
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -119,8 +119,9 @@ public:
|
||||
populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section,
|
||||
SectionID);
|
||||
else if (Name == "__pointers")
|
||||
populatePointersSection(cast<MachOObjectFile>(*ObjImg.getObjectFile()),
|
||||
Section, SectionID);
|
||||
populateIndirectSymbolPointersSection(
|
||||
cast<MachOObjectFile>(*ObjImg.getObjectFile()),
|
||||
Section, SectionID);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -259,58 +260,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Populate __pointers section.
|
||||
void populatePointersSection(MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID) {
|
||||
assert(!Obj.is64Bit() &&
|
||||
"__pointers section not supported in 64-bit MachO.");
|
||||
|
||||
MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
|
||||
MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
|
||||
uint32_t PTSectionSize = Sec32.size;
|
||||
unsigned FirstIndirectSymbol = Sec32.reserved1;
|
||||
const unsigned PTEntrySize = 4;
|
||||
unsigned NumPTEntries = PTSectionSize / PTEntrySize;
|
||||
unsigned PTEntryOffset = 0;
|
||||
|
||||
assert((PTSectionSize % PTEntrySize) == 0 &&
|
||||
"Pointers section does not contain a whole number of stubs?");
|
||||
|
||||
DEBUG(dbgs() << "Populating __pointers, Section ID " << PTSectionID << ", "
|
||||
<< NumPTEntries << " entries, " << PTEntrySize
|
||||
<< " bytes each:\n");
|
||||
|
||||
for (unsigned i = 0; i < NumPTEntries; ++i) {
|
||||
unsigned SymbolIndex =
|
||||
Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
|
||||
symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
|
||||
StringRef IndirectSymbolName;
|
||||
SI->getName(IndirectSymbolName);
|
||||
DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex
|
||||
<< ", PT offset: " << PTEntryOffset << "\n");
|
||||
RelocationEntry RE(PTSectionID, PTEntryOffset,
|
||||
MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
|
||||
addRelocationForSymbol(RE, IndirectSymbolName);
|
||||
PTEntryOffset += PTEntrySize;
|
||||
}
|
||||
}
|
||||
|
||||
static section_iterator getSectionByAddress(const MachOObjectFile &Obj,
|
||||
uint64_t Addr) {
|
||||
section_iterator SI = Obj.section_begin();
|
||||
section_iterator SE = Obj.section_end();
|
||||
|
||||
for (; SI != SE; ++SI) {
|
||||
uint64_t SAddr, SSize;
|
||||
SI->getAddress(SAddr);
|
||||
SI->getSize(SSize);
|
||||
if ((Addr >= SAddr) && (Addr < SAddr + SSize))
|
||||
return SI;
|
||||
}
|
||||
|
||||
return SE;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
# 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
|
||||
.globl bar
|
||||
.align 2
|
||||
.syntax unified
|
||||
.section __TEXT,__text,regular,pure_instructions
|
||||
.globl bar
|
||||
.align 2
|
||||
bar:
|
||||
# Check lower 16-bits of section difference relocation
|
||||
# rtdyld-check: decode_operand(insn1, 1) = (foo-(nextPC+8))[15:0]
|
||||
# rtdyld-check: decode_operand(insn1, 1) = (foo$non_lazy_ptr-(nextPC+8))[15:0]
|
||||
insn1:
|
||||
movw r0, :lower16:(foo-(nextPC+8))
|
||||
movw r0, :lower16:(foo$non_lazy_ptr-(nextPC+8))
|
||||
# Check upper 16-bits of section difference relocation
|
||||
# rtdyld-check: decode_operand(insn2, 2) = (foo-(nextPC+8))[31:16]
|
||||
# rtdyld-check: decode_operand(insn2, 2) = (foo$non_lazy_ptr-(nextPC+8))[31:16]
|
||||
insn2:
|
||||
movt r0, :upper16:(foo-(nextPC+8))
|
||||
movt r0, :upper16:(foo$non_lazy_ptr-(nextPC+8))
|
||||
nextPC:
|
||||
add r0, pc, r0
|
||||
add r1, r0, r0
|
||||
|
||||
# Check stub generation by referencing a common symbol, 'baz'. Check both the
|
||||
# Content of the stub, and the reference to the stub.
|
||||
@ -27,16 +27,20 @@ nextPC:
|
||||
# rtdyld-check: decode_operand(insn3, 0) = stub_addr(foo.o, __text, baz) - (insn3 + 8)
|
||||
insn3:
|
||||
bl baz
|
||||
bx lr
|
||||
|
||||
.globl foo
|
||||
.align 2
|
||||
foo:
|
||||
bx lr
|
||||
bx lr
|
||||
|
||||
# Add 'aaa' to the common symbols to make sure 'baz' isn't at the start of the
|
||||
# section. This ensures that we test VANILLA relocation addends correctly.
|
||||
.comm aaa, 4, 2
|
||||
.comm baz, 4, 2
|
||||
.comm foo, 4, 2
|
||||
|
||||
# Check that the symbol pointer section entries are fixed up properly:
|
||||
# rtdyld-check: *{4}foo$non_lazy_ptr = foo
|
||||
.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
|
||||
.align 2
|
||||
foo$non_lazy_ptr:
|
||||
.indirect_symbol foo
|
||||
.long 0
|
||||
|
||||
.subsections_via_symbols
|
||||
|
Loading…
Reference in New Issue
Block a user