mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-01 17:28:21 +00:00
Improved support in RuntimeDyldMachO for generating
code that will be relocated into another memory space. Now when relocations are resolved, the address of the relocation in the host memory (where the JIT is) is passed separately from the address that the relocation will be at in the target memory (where the code will run). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152264 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7afcda0c58
commit
61dfa77fce
@ -22,29 +22,49 @@ using namespace llvm::object;
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
bool RuntimeDyldMachO::
|
bool RuntimeDyldMachO::
|
||||||
resolveRelocation(uint8_t *Address, uint64_t Value, bool isPCRel,
|
resolveRelocation(uint8_t *LocalAddress,
|
||||||
unsigned Type, unsigned Size, int64_t Addend) {
|
uint64_t FinalAddress,
|
||||||
|
uint64_t Value,
|
||||||
|
bool isPCRel,
|
||||||
|
unsigned Type,
|
||||||
|
unsigned Size,
|
||||||
|
int64_t Addend) {
|
||||||
// This just dispatches to the proper target specific routine.
|
// This just dispatches to the proper target specific routine.
|
||||||
switch (CPUType) {
|
switch (CPUType) {
|
||||||
default: llvm_unreachable("Unsupported CPU type!");
|
default: llvm_unreachable("Unsupported CPU type!");
|
||||||
case mach::CTM_x86_64:
|
case mach::CTM_x86_64:
|
||||||
return resolveX86_64Relocation((uintptr_t)Address, (uintptr_t)Value,
|
return resolveX86_64Relocation(LocalAddress,
|
||||||
isPCRel, Type, Size, Addend);
|
FinalAddress,
|
||||||
|
(uintptr_t)Value,
|
||||||
|
isPCRel,
|
||||||
|
Type,
|
||||||
|
Size,
|
||||||
|
Addend);
|
||||||
case mach::CTM_ARM:
|
case mach::CTM_ARM:
|
||||||
return resolveARMRelocation((uintptr_t)Address, (uintptr_t)Value,
|
return resolveARMRelocation(LocalAddress,
|
||||||
isPCRel, Type, Size, Addend);
|
FinalAddress,
|
||||||
|
(uintptr_t)Value,
|
||||||
|
isPCRel,
|
||||||
|
Type,
|
||||||
|
Size,
|
||||||
|
Addend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuntimeDyldMachO::
|
bool RuntimeDyldMachO::
|
||||||
resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||||
unsigned Type, unsigned Size, int64_t Addend) {
|
uint64_t FinalAddress,
|
||||||
|
uint64_t Value,
|
||||||
|
bool isPCRel,
|
||||||
|
unsigned Type,
|
||||||
|
unsigned Size,
|
||||||
|
int64_t Addend) {
|
||||||
// If the relocation is PC-relative, the value to be encoded is the
|
// If the relocation is PC-relative, the value to be encoded is the
|
||||||
// pointer difference.
|
// pointer difference.
|
||||||
if (isPCRel)
|
if (isPCRel)
|
||||||
// FIXME: It seems this value needs to be adjusted by 4 for an effective PC
|
// FIXME: It seems this value needs to be adjusted by 4 for an effective PC
|
||||||
// address. Is that expected? Only for branches, perhaps?
|
// address. Is that expected? Only for branches, perhaps?
|
||||||
Value -= Address + 4;
|
Value -= FinalAddress + 4;
|
||||||
|
|
||||||
switch(Type) {
|
switch(Type) {
|
||||||
default:
|
default:
|
||||||
@ -58,7 +78,7 @@ resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
|||||||
Value += Addend;
|
Value += Addend;
|
||||||
// Mask in the target value a byte at a time (we don't have an alignment
|
// 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).
|
// guarantee for the target address, so this is safest).
|
||||||
uint8_t *p = (uint8_t*)Address;
|
uint8_t *p = (uint8_t*)LocalAddress;
|
||||||
for (unsigned i = 0; i < Size; ++i) {
|
for (unsigned i = 0; i < Size; ++i) {
|
||||||
*p++ = (uint8_t)Value;
|
*p++ = (uint8_t)Value;
|
||||||
Value >>= 8;
|
Value >>= 8;
|
||||||
@ -74,12 +94,17 @@ resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RuntimeDyldMachO::
|
bool RuntimeDyldMachO::
|
||||||
resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
resolveARMRelocation(uint8_t *LocalAddress,
|
||||||
unsigned Type, unsigned Size, int64_t Addend) {
|
uint64_t FinalAddress,
|
||||||
|
uint64_t Value,
|
||||||
|
bool isPCRel,
|
||||||
|
unsigned Type,
|
||||||
|
unsigned Size,
|
||||||
|
int64_t Addend) {
|
||||||
// If the relocation is PC-relative, the value to be encoded is the
|
// If the relocation is PC-relative, the value to be encoded is the
|
||||||
// pointer difference.
|
// pointer difference.
|
||||||
if (isPCRel) {
|
if (isPCRel) {
|
||||||
Value -= Address;
|
Value -= FinalAddress;
|
||||||
// ARM PCRel relocations have an effective-PC offset of two instructions
|
// ARM PCRel relocations have an effective-PC offset of two instructions
|
||||||
// (four bytes in Thumb mode, 8 bytes in ARM mode).
|
// (four bytes in Thumb mode, 8 bytes in ARM mode).
|
||||||
// FIXME: For now, assume ARM mode.
|
// FIXME: For now, assume ARM mode.
|
||||||
@ -92,7 +117,7 @@ resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
|||||||
case macho::RIT_Vanilla: {
|
case macho::RIT_Vanilla: {
|
||||||
// Mask in the target value a byte at a time (we don't have an alignment
|
// 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).
|
// guarantee for the target address, so this is safest).
|
||||||
uint8_t *p = (uint8_t*)Address;
|
uint8_t *p = (uint8_t*)LocalAddress;
|
||||||
for (unsigned i = 0; i < Size; ++i) {
|
for (unsigned i = 0; i < Size; ++i) {
|
||||||
*p++ = (uint8_t)Value;
|
*p++ = (uint8_t)Value;
|
||||||
Value >>= 8;
|
Value >>= 8;
|
||||||
@ -102,7 +127,7 @@ resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
|||||||
case macho::RIT_ARM_Branch24Bit: {
|
case macho::RIT_ARM_Branch24Bit: {
|
||||||
// Mask the value into the target address. We know instructions are
|
// Mask the value into the target address. We know instructions are
|
||||||
// 32-bit aligned, so we can do it all at once.
|
// 32-bit aligned, so we can do it all at once.
|
||||||
uint32_t *p = (uint32_t*)Address;
|
uint32_t *p = (uint32_t*)LocalAddress;
|
||||||
// The low two bits of the value are not encoded.
|
// The low two bits of the value are not encoded.
|
||||||
Value >>= 2;
|
Value >>= 2;
|
||||||
// Mask the value to 24 bits.
|
// Mask the value to 24 bits.
|
||||||
@ -569,6 +594,7 @@ void RuntimeDyldMachO::reassignSectionAddress(unsigned SectionID,
|
|||||||
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
|
||||||
RelocationEntry &RE = Relocs[i];
|
RelocationEntry &RE = Relocs[i];
|
||||||
uint8_t *Target = (uint8_t*)Sections[RE.SectionID].base() + RE.Offset;
|
uint8_t *Target = (uint8_t*)Sections[RE.SectionID].base() + RE.Offset;
|
||||||
|
uint64_t FinalTarget = (uint64_t)SectionLoadAddress[RE.SectionID] + RE.Offset;
|
||||||
bool isPCRel = (RE.Data >> 24) & 1;
|
bool isPCRel = (RE.Data >> 24) & 1;
|
||||||
unsigned Type = (RE.Data >> 28) & 0xf;
|
unsigned Type = (RE.Data >> 28) & 0xf;
|
||||||
unsigned Size = 1 << ((RE.Data >> 25) & 3);
|
unsigned Size = 1 << ((RE.Data >> 25) & 3);
|
||||||
@ -580,7 +606,13 @@ void RuntimeDyldMachO::reassignSectionAddress(unsigned SectionID,
|
|||||||
<< ", type: " << Type << ", Size: " << Size << ", Addend: "
|
<< ", type: " << Type << ", Size: " << Size << ", Addend: "
|
||||||
<< RE.Addend << ").\n");
|
<< RE.Addend << ").\n");
|
||||||
|
|
||||||
resolveRelocation(Target, Addr, isPCRel, Type, Size, RE.Addend);
|
resolveRelocation(Target,
|
||||||
|
FinalTarget,
|
||||||
|
Addr,
|
||||||
|
isPCRel,
|
||||||
|
Type,
|
||||||
|
Size,
|
||||||
|
RE.Addend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,12 +51,27 @@ class RuntimeDyldMachO : public RuntimeDyldImpl {
|
|||||||
// relocations by definition. Indexed by symbol name.
|
// relocations by definition. Indexed by symbol name.
|
||||||
StringMap<RelocationList> UnresolvedRelocations;
|
StringMap<RelocationList> UnresolvedRelocations;
|
||||||
|
|
||||||
bool resolveRelocation(uint8_t *Address, uint64_t Value, bool isPCRel,
|
bool resolveRelocation(uint8_t *LocalAddress,
|
||||||
unsigned Type, unsigned Size, int64_t Addend);
|
uint64_t FinalAddress,
|
||||||
bool resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
uint64_t Value,
|
||||||
unsigned Type, unsigned Size, int64_t Addend);
|
bool isPCRel,
|
||||||
bool resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel,
|
unsigned Type,
|
||||||
unsigned Type, unsigned Size, int64_t Addend);
|
unsigned Size,
|
||||||
|
int64_t Addend);
|
||||||
|
bool resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||||
|
uint64_t FinalAddress,
|
||||||
|
uint64_t Value,
|
||||||
|
bool isPCRel,
|
||||||
|
unsigned Type,
|
||||||
|
unsigned Size,
|
||||||
|
int64_t Addend);
|
||||||
|
bool resolveARMRelocation(uint8_t *LocalAddress,
|
||||||
|
uint64_t FinalAddress,
|
||||||
|
uint64_t Value,
|
||||||
|
bool isPCRel,
|
||||||
|
unsigned Type,
|
||||||
|
unsigned Size,
|
||||||
|
int64_t Addend);
|
||||||
|
|
||||||
bool loadSegment32(const MachOObject *Obj,
|
bool loadSegment32(const MachOObject *Obj,
|
||||||
const MachOObject::LoadCommandInfo *SegmentLCI,
|
const MachOObject::LoadCommandInfo *SegmentLCI,
|
||||||
|
Loading…
Reference in New Issue
Block a user