mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[mips] Adds support for R_MIPS_26, HIGHER, HIGHEST relocations in RuntimeDyld
After the N64 static relocation model support was added to llvm it is required to add its support in RuntimeDyld also because lldb uses ExecutionEngine for evaluating expressions. Reviewed by sdardis Differential: D31649 llvm-svn: 305997
This commit is contained in:
parent
9efb4e04c7
commit
74e536eb62
@ -861,7 +861,7 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
|
|||||||
// and stubs for branches Thumb - ARM and ARM - Thumb.
|
// and stubs for branches Thumb - ARM and ARM - Thumb.
|
||||||
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,<label>
|
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,<label>
|
||||||
return Addr + 4;
|
return Addr + 4;
|
||||||
} else if (IsMipsO32ABI) {
|
} else if (IsMipsO32ABI || IsMipsN32ABI) {
|
||||||
// 0: 3c190000 lui t9,%hi(addr).
|
// 0: 3c190000 lui t9,%hi(addr).
|
||||||
// 4: 27390000 addiu t9,t9,%lo(addr).
|
// 4: 27390000 addiu t9,t9,%lo(addr).
|
||||||
// 8: 03200008 jr t9.
|
// 8: 03200008 jr t9.
|
||||||
@ -869,13 +869,39 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
|
|||||||
const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
|
const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
|
||||||
const unsigned NopInstr = 0x0;
|
const unsigned NopInstr = 0x0;
|
||||||
unsigned JrT9Instr = 0x03200008;
|
unsigned JrT9Instr = 0x03200008;
|
||||||
if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_32R6)
|
if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_32R6 ||
|
||||||
JrT9Instr = 0x03200009;
|
(AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_64R6)
|
||||||
|
JrT9Instr = 0x03200009;
|
||||||
|
|
||||||
writeBytesUnaligned(LuiT9Instr, Addr, 4);
|
writeBytesUnaligned(LuiT9Instr, Addr, 4);
|
||||||
writeBytesUnaligned(AdduiT9Instr, Addr+4, 4);
|
writeBytesUnaligned(AdduiT9Instr, Addr + 4, 4);
|
||||||
writeBytesUnaligned(JrT9Instr, Addr+8, 4);
|
writeBytesUnaligned(JrT9Instr, Addr + 8, 4);
|
||||||
writeBytesUnaligned(NopInstr, Addr+12, 4);
|
writeBytesUnaligned(NopInstr, Addr + 12, 4);
|
||||||
|
return Addr;
|
||||||
|
} else if (IsMipsN64ABI) {
|
||||||
|
// 0: 3c190000 lui t9,%highest(addr).
|
||||||
|
// 4: 67390000 daddiu t9,t9,%higher(addr).
|
||||||
|
// 8: 0019CC38 dsll t9,t9,16.
|
||||||
|
// c: 67390000 daddiu t9,t9,%hi(addr).
|
||||||
|
// 10: 0019CC38 dsll t9,t9,16.
|
||||||
|
// 14: 67390000 daddiu t9,t9,%lo(addr).
|
||||||
|
// 18: 03200008 jr t9.
|
||||||
|
// 1c: 00000000 nop.
|
||||||
|
const unsigned LuiT9Instr = 0x3c190000, DaddiuT9Instr = 0x67390000,
|
||||||
|
DsllT9Instr = 0x19CC38;
|
||||||
|
const unsigned NopInstr = 0x0;
|
||||||
|
unsigned JrT9Instr = 0x03200008;
|
||||||
|
if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_64R6)
|
||||||
|
JrT9Instr = 0x03200009;
|
||||||
|
|
||||||
|
writeBytesUnaligned(LuiT9Instr, Addr, 4);
|
||||||
|
writeBytesUnaligned(DaddiuT9Instr, Addr + 4, 4);
|
||||||
|
writeBytesUnaligned(DsllT9Instr, Addr + 8, 4);
|
||||||
|
writeBytesUnaligned(DaddiuT9Instr, Addr + 12, 4);
|
||||||
|
writeBytesUnaligned(DsllT9Instr, Addr + 16, 4);
|
||||||
|
writeBytesUnaligned(DaddiuT9Instr, Addr + 20, 4);
|
||||||
|
writeBytesUnaligned(JrT9Instr, Addr + 24, 4);
|
||||||
|
writeBytesUnaligned(NopInstr, Addr + 28, 4);
|
||||||
return Addr;
|
return Addr;
|
||||||
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
|
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
|
||||||
// Depending on which version of the ELF ABI is in use, we need to
|
// Depending on which version of the ELF ABI is in use, we need to
|
||||||
|
@ -1251,8 +1251,7 @@ RuntimeDyldELF::processRelocationRef(
|
|||||||
if (Value.SymbolName) {
|
if (Value.SymbolName) {
|
||||||
addRelocationForSymbol(REHi, Value.SymbolName);
|
addRelocationForSymbol(REHi, Value.SymbolName);
|
||||||
addRelocationForSymbol(RELo, Value.SymbolName);
|
addRelocationForSymbol(RELo, Value.SymbolName);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
addRelocationForSection(REHi, Value.SectionID);
|
addRelocationForSection(REHi, Value.SectionID);
|
||||||
addRelocationForSection(RELo, Value.SectionID);
|
addRelocationForSection(RELo, Value.SectionID);
|
||||||
}
|
}
|
||||||
@ -1301,10 +1300,14 @@ RuntimeDyldELF::processRelocationRef(
|
|||||||
processSimpleRelocation(SectionID, Offset, RelType, Value);
|
processSimpleRelocation(SectionID, Offset, RelType, Value);
|
||||||
}
|
}
|
||||||
} else if (IsMipsN32ABI || IsMipsN64ABI) {
|
} else if (IsMipsN32ABI || IsMipsN64ABI) {
|
||||||
|
uint8_t *Placeholder = reinterpret_cast<uint8_t *>(
|
||||||
|
computePlaceholderAddress(SectionID, Offset));
|
||||||
|
uint32_t Opcode = readBytesUnaligned(Placeholder, 4);
|
||||||
|
|
||||||
uint32_t r_type = RelType & 0xff;
|
uint32_t r_type = RelType & 0xff;
|
||||||
RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
|
RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
|
||||||
if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE
|
if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE ||
|
||||||
|| r_type == ELF::R_MIPS_GOT_DISP) {
|
r_type == ELF::R_MIPS_GOT_DISP) {
|
||||||
StringMap<uint64_t>::iterator i = GOTSymbolOffsets.find(TargetName);
|
StringMap<uint64_t>::iterator i = GOTSymbolOffsets.find(TargetName);
|
||||||
if (i != GOTSymbolOffsets.end())
|
if (i != GOTSymbolOffsets.end())
|
||||||
RE.SymOffset = i->second;
|
RE.SymOffset = i->second;
|
||||||
@ -1312,11 +1315,83 @@ RuntimeDyldELF::processRelocationRef(
|
|||||||
RE.SymOffset = allocateGOTEntries(1);
|
RE.SymOffset = allocateGOTEntries(1);
|
||||||
GOTSymbolOffsets[TargetName] = RE.SymOffset;
|
GOTSymbolOffsets[TargetName] = RE.SymOffset;
|
||||||
}
|
}
|
||||||
|
if (Value.SymbolName)
|
||||||
|
addRelocationForSymbol(RE, Value.SymbolName);
|
||||||
|
else
|
||||||
|
addRelocationForSection(RE, Value.SectionID);
|
||||||
|
} else if (RelType == ELF::R_MIPS_26) {
|
||||||
|
// This is an Mips branch relocation, need to use a stub function.
|
||||||
|
DEBUG(dbgs() << "\t\tThis is a Mips branch relocation.");
|
||||||
|
SectionEntry &Section = Sections[SectionID];
|
||||||
|
|
||||||
|
// Look up for existing stub.
|
||||||
|
StubMap::const_iterator i = Stubs.find(Value);
|
||||||
|
if (i != Stubs.end()) {
|
||||||
|
RelocationEntry RE(SectionID, Offset, RelType, i->second);
|
||||||
|
addRelocationForSection(RE, SectionID);
|
||||||
|
DEBUG(dbgs() << " Stub function found\n");
|
||||||
|
} else {
|
||||||
|
// Create a new stub function.
|
||||||
|
DEBUG(dbgs() << " Create a new stub function\n");
|
||||||
|
Stubs[Value] = Section.getStubOffset();
|
||||||
|
|
||||||
|
unsigned AbiVariant;
|
||||||
|
O.getPlatformFlags(AbiVariant);
|
||||||
|
|
||||||
|
uint8_t *StubTargetAddr = createStubFunction(
|
||||||
|
Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant);
|
||||||
|
|
||||||
|
if (IsMipsN32ABI) {
|
||||||
|
// Creating Hi and Lo relocations for the filled stub instructions.
|
||||||
|
RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(),
|
||||||
|
ELF::R_MIPS_HI16, Value.Addend);
|
||||||
|
RelocationEntry RELo(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress() + 4,
|
||||||
|
ELF::R_MIPS_LO16, Value.Addend);
|
||||||
|
if (Value.SymbolName) {
|
||||||
|
addRelocationForSymbol(REHi, Value.SymbolName);
|
||||||
|
addRelocationForSymbol(RELo, Value.SymbolName);
|
||||||
|
} else {
|
||||||
|
addRelocationForSection(REHi, Value.SectionID);
|
||||||
|
addRelocationForSection(RELo, Value.SectionID);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Creating Highest, Higher, Hi and Lo relocations for the filled stub
|
||||||
|
// instructions.
|
||||||
|
RelocationEntry REHighest(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress(),
|
||||||
|
ELF::R_MIPS_HIGHEST, Value.Addend);
|
||||||
|
RelocationEntry REHigher(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress() + 4,
|
||||||
|
ELF::R_MIPS_HIGHER, Value.Addend);
|
||||||
|
RelocationEntry REHi(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress() + 12,
|
||||||
|
ELF::R_MIPS_HI16, Value.Addend);
|
||||||
|
RelocationEntry RELo(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress() + 20,
|
||||||
|
ELF::R_MIPS_LO16, Value.Addend);
|
||||||
|
if (Value.SymbolName) {
|
||||||
|
addRelocationForSymbol(REHighest, Value.SymbolName);
|
||||||
|
addRelocationForSymbol(REHigher, Value.SymbolName);
|
||||||
|
addRelocationForSymbol(REHi, Value.SymbolName);
|
||||||
|
addRelocationForSymbol(RELo, Value.SymbolName);
|
||||||
|
} else {
|
||||||
|
addRelocationForSection(REHighest, Value.SectionID);
|
||||||
|
addRelocationForSection(REHigher, Value.SectionID);
|
||||||
|
addRelocationForSection(REHi, Value.SectionID);
|
||||||
|
addRelocationForSection(RELo, Value.SectionID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset());
|
||||||
|
addRelocationForSection(RE, SectionID);
|
||||||
|
Section.advanceStubOffset(getMaxStubSize());
|
||||||
|
}
|
||||||
|
} else if (RelType == ELF::R_MIPS_HI16 || RelType == ELF::R_MIPS_PCHI16 ||
|
||||||
|
RelType == ELF::R_MIPS_HIGHEST ||
|
||||||
|
RelType == ELF::R_MIPS_HIGHER || RelType == ELF::R_MIPS_LO16 ||
|
||||||
|
RelType == ELF::R_MIPS_PCLO16) {
|
||||||
|
processSimpleRelocation(SectionID, Offset, RelType, Value);
|
||||||
}
|
}
|
||||||
if (Value.SymbolName)
|
|
||||||
addRelocationForSymbol(RE, Value.SymbolName);
|
|
||||||
else
|
|
||||||
addRelocationForSection(RE, Value.SectionID);
|
|
||||||
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
|
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
|
||||||
if (RelType == ELF::R_PPC64_REL24) {
|
if (RelType == ELF::R_PPC64_REL24) {
|
||||||
// Determine ABI variant in use for this object.
|
// Determine ABI variant in use for this object.
|
||||||
|
@ -66,8 +66,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
|||||||
return 20; // movz; movk; movk; movk; br
|
return 20; // movz; movk; movk; movk; br
|
||||||
if (Arch == Triple::arm || Arch == Triple::thumb)
|
if (Arch == Triple::arm || Arch == Triple::thumb)
|
||||||
return 8; // 32-bit instruction and 32-bit address
|
return 8; // 32-bit instruction and 32-bit address
|
||||||
else if (IsMipsO32ABI)
|
else if (IsMipsO32ABI || IsMipsN32ABI)
|
||||||
return 16;
|
return 16;
|
||||||
|
else if (IsMipsN64ABI)
|
||||||
|
return 32;
|
||||||
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
|
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
|
||||||
return 44;
|
return 44;
|
||||||
else if (Arch == Triple::x86_64)
|
else if (Arch == Triple::x86_64)
|
||||||
|
@ -141,6 +141,10 @@ int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
|
|||||||
return ((Value + Addend + 0x8000) >> 16) & 0xffff;
|
return ((Value + Addend + 0x8000) >> 16) & 0xffff;
|
||||||
case ELF::R_MIPS_LO16:
|
case ELF::R_MIPS_LO16:
|
||||||
return (Value + Addend) & 0xffff;
|
return (Value + Addend) & 0xffff;
|
||||||
|
case ELF::R_MIPS_HIGHER:
|
||||||
|
return ((Value + Addend + 0x80008000) >> 32) & 0xffff;
|
||||||
|
case ELF::R_MIPS_HIGHEST:
|
||||||
|
return ((Value + Addend + 0x800080008000) >> 48) & 0xffff;
|
||||||
case ELF::R_MIPS_CALL16:
|
case ELF::R_MIPS_CALL16:
|
||||||
case ELF::R_MIPS_GOT_DISP:
|
case ELF::R_MIPS_GOT_DISP:
|
||||||
case ELF::R_MIPS_GOT_PAGE: {
|
case ELF::R_MIPS_GOT_PAGE: {
|
||||||
@ -215,6 +219,8 @@ void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
|
|||||||
case ELF::R_MIPS_GPREL16:
|
case ELF::R_MIPS_GPREL16:
|
||||||
case ELF::R_MIPS_HI16:
|
case ELF::R_MIPS_HI16:
|
||||||
case ELF::R_MIPS_LO16:
|
case ELF::R_MIPS_LO16:
|
||||||
|
case ELF::R_MIPS_HIGHER:
|
||||||
|
case ELF::R_MIPS_HIGHEST:
|
||||||
case ELF::R_MIPS_PC16:
|
case ELF::R_MIPS_PC16:
|
||||||
case ELF::R_MIPS_PCHI16:
|
case ELF::R_MIPS_PCHI16:
|
||||||
case ELF::R_MIPS_PCLO16:
|
case ELF::R_MIPS_PCLO16:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user