mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
Split out relocation resolution into target-specific bits.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128173 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
741ad15e26
commit
a8287e322f
@ -31,6 +31,9 @@ using namespace llvm::object;
|
||||
|
||||
namespace llvm {
|
||||
class RuntimeDyldImpl {
|
||||
unsigned CPUType;
|
||||
unsigned CPUSubtype;
|
||||
|
||||
// Master symbol table. As modules are loaded and external symbols are
|
||||
// resolved, their addresses are stored here.
|
||||
StringMap<void*> SymbolTable;
|
||||
@ -52,6 +55,10 @@ class RuntimeDyldImpl {
|
||||
bool resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE,
|
||||
SmallVectorImpl<void *> &SectionBases,
|
||||
SmallVectorImpl<StringRef> &SymbolNames);
|
||||
bool resolveX86_64Relocation(intptr_t Address, intptr_t Value, bool isPCRel,
|
||||
unsigned Type, unsigned Size);
|
||||
bool resolveARMRelocation(intptr_t Address, intptr_t Value, bool isPCRel,
|
||||
unsigned Type, unsigned Size);
|
||||
|
||||
bool loadSegment32(const MachOObject *Obj,
|
||||
const MachOObject::LoadCommandInfo *SegmentLCI,
|
||||
@ -128,6 +135,20 @@ resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE,
|
||||
Value = (intptr_t)SectionBases[SymbolNum - 1];
|
||||
}
|
||||
|
||||
unsigned Size = 1 << Log2Size;
|
||||
switch (CPUType) {
|
||||
default: assert(0 && "Unsupported CPU type!");
|
||||
case mach::CTM_x86_64:
|
||||
return resolveX86_64Relocation(Address, Value, isPCRel, Type, Size);
|
||||
case mach::CTM_ARM:
|
||||
return resolveARMRelocation(Address, Value, isPCRel, Type, Size);
|
||||
}
|
||||
llvm_unreachable("");
|
||||
}
|
||||
|
||||
bool RuntimeDyldImpl::resolveX86_64Relocation(intptr_t Address, intptr_t Value,
|
||||
bool isPCRel, unsigned Type,
|
||||
unsigned Size) {
|
||||
// If the relocation is PC-relative, the value to be encoded is the
|
||||
// pointer difference.
|
||||
if (isPCRel)
|
||||
@ -142,9 +163,8 @@ resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE,
|
||||
case macho::RIT_X86_64_Branch: {
|
||||
// Mask in the target value a byte at a time (we don't have an alignment
|
||||
// guarantee for the target address, so this is safest).
|
||||
unsigned Len = 1 << Log2Size;
|
||||
uint8_t *p = (uint8_t*)Address;
|
||||
for (unsigned i = 0; i < Len; ++i) {
|
||||
for (unsigned i = 0; i < Size; ++i) {
|
||||
*p++ = (uint8_t)Value;
|
||||
Value >>= 8;
|
||||
}
|
||||
@ -163,6 +183,46 @@ resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RuntimeDyldImpl::resolveARMRelocation(intptr_t Address, intptr_t Value,
|
||||
bool isPCRel, unsigned Type,
|
||||
unsigned Size) {
|
||||
// If the relocation is PC-relative, the value to be encoded is the
|
||||
// pointer difference.
|
||||
if (isPCRel) {
|
||||
Value -= Address;
|
||||
// ARM PCRel relocations have an effective-PC offset of two instructions
|
||||
// (four bytes in Thumb mode, 8 bytes in ARM mode).
|
||||
// FIXME: For now, assume ARM mode.
|
||||
Value -= 8;
|
||||
}
|
||||
|
||||
switch(Type) {
|
||||
default:
|
||||
case macho::RIT_Vanilla: {
|
||||
llvm_unreachable("Invalid relocation type!");
|
||||
// Mask in the target value a byte at a time (we don't have an alignment
|
||||
// guarantee for the target address, so this is safest).
|
||||
uint8_t *p = (uint8_t*)Address;
|
||||
for (unsigned i = 0; i < Size; ++i) {
|
||||
*p++ = (uint8_t)Value;
|
||||
Value >>= 8;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case macho::RIT_Pair:
|
||||
case macho::RIT_Difference:
|
||||
case macho::RIT_ARM_LocalDifference:
|
||||
case macho::RIT_ARM_PreboundLazyPointer:
|
||||
case macho::RIT_ARM_Branch24Bit:
|
||||
case macho::RIT_ARM_ThumbBranch22Bit:
|
||||
case macho::RIT_ARM_ThumbBranch32Bit:
|
||||
case macho::RIT_ARM_Half:
|
||||
case macho::RIT_ARM_HalfDifference:
|
||||
return Error("Relocation type not implemented yet!");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RuntimeDyldImpl::
|
||||
loadSegment32(const MachOObject *Obj,
|
||||
const MachOObject::LoadCommandInfo *SegmentLCI,
|
||||
@ -352,10 +412,18 @@ bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) {
|
||||
if (!Obj)
|
||||
return Error("unable to load object: '" + ErrorStr + "'");
|
||||
|
||||
// Get the CPU type information from the header.
|
||||
const macho::Header &Header = Obj->getHeader();
|
||||
|
||||
// FIXME: Error checking that the loaded object is compatible with
|
||||
// the system we're running on.
|
||||
CPUType = Header.CPUType;
|
||||
CPUSubtype = Header.CPUSubtype;
|
||||
|
||||
// Validate that the load commands match what we expect.
|
||||
const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0,
|
||||
*DysymtabLCI = 0;
|
||||
for (unsigned i = 0; i != Obj->getHeader().NumLoadCommands; ++i) {
|
||||
for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
|
||||
const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i);
|
||||
switch (LCI.Command.Type) {
|
||||
case macho::LCT_Segment:
|
||||
|
Loading…
x
Reference in New Issue
Block a user