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.
Reviewers: sdardis Subscribers: jaydeep, bhushan, llvm-commits Differential Revision: https://reviews.llvm.org/D38314 llvm-svn: 316287
This commit is contained in:
parent
297749d93e
commit
755be3706a
@ -878,7 +878,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, [pc, #-4]
|
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc, [pc, #-4]
|
||||||
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.
|
||||||
@ -886,13 +886,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
|
||||||
|
@ -1276,8 +1276,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);
|
||||||
}
|
}
|
||||||
@ -1337,11 +1336,81 @@ 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 {
|
||||||
|
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)
|
||||||
|
@ -116,6 +116,8 @@ int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
|
|||||||
<< format("%llx", Section.getLoadAddressWithOffset(Offset))
|
<< format("%llx", Section.getLoadAddressWithOffset(Offset))
|
||||||
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
|
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
|
||||||
<< format("%x", Type) << " Addend: 0x" << format("%llx", Addend)
|
<< format("%x", Type) << " Addend: 0x" << format("%llx", Addend)
|
||||||
|
<< " Offset: " << format("%llx" PRIx64, Offset)
|
||||||
|
<< " SID: " << format("%d", SectionID)
|
||||||
<< " SymOffset: " << format("%x", SymOffset) << "\n");
|
<< " SymOffset: " << format("%x", SymOffset) << "\n");
|
||||||
|
|
||||||
switch (Type) {
|
switch (Type) {
|
||||||
@ -141,6 +143,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 +221,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:
|
||||||
@ -304,7 +312,8 @@ void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,
|
|||||||
<< format("%p", Section.getLoadAddressWithOffset(Offset))
|
<< format("%p", Section.getLoadAddressWithOffset(Offset))
|
||||||
<< " Value: " << format("%x", Value)
|
<< " Value: " << format("%x", Value)
|
||||||
<< " Type: " << format("%x", Type)
|
<< " Type: " << format("%x", Type)
|
||||||
<< " Addend: " << format("%x", Addend) << "\n");
|
<< " Addend: " << format("%x", Addend)
|
||||||
|
<< " SymOffset: " << format("%x", Offset) << "\n");
|
||||||
|
|
||||||
Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
|
Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ bar:
|
|||||||
sd $4, 8($fp)
|
sd $4, 8($fp)
|
||||||
|
|
||||||
# Test R_MIPS_26 relocation.
|
# Test R_MIPS_26 relocation.
|
||||||
# rtdyld-check: decode_operand(insn1, 0)[27:0] = foo[27:0]
|
# rtdyld-check: decode_operand(insn1, 0)[27:0] = stub_addr(test_ELF_Mips64N64.o, .text, foo)[27:0]
|
||||||
insn1:
|
insn1:
|
||||||
.option pic0
|
.option pic0
|
||||||
jal foo
|
jal foo
|
||||||
|
@ -44,7 +44,7 @@ bar:
|
|||||||
sd $4, 8($fp)
|
sd $4, 8($fp)
|
||||||
|
|
||||||
# Test R_MIPS_26 relocation.
|
# Test R_MIPS_26 relocation.
|
||||||
# rtdyld-check: decode_operand(insn1, 0)[27:0] = foo[27:0]
|
# rtdyld-check: decode_operand(insn1, 0)[27:0] = stub_addr(test_ELF_N32.o, .text, foo)[27:0]
|
||||||
insn1:
|
insn1:
|
||||||
.option pic0
|
.option pic0
|
||||||
jal foo
|
jal foo
|
||||||
|
Loading…
x
Reference in New Issue
Block a user