1
0
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:
Nitesh Jain 2017-10-22 09:47:41 +00:00
parent 297749d93e
commit 755be3706a
6 changed files with 122 additions and 16 deletions

View File

@ -878,7 +878,7 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
// and stubs for branches Thumb - ARM and ARM - Thumb.
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc, [pc, #-4]
return Addr + 4;
} else if (IsMipsO32ABI) {
} else if (IsMipsO32ABI || IsMipsN32ABI) {
// 0: 3c190000 lui t9,%hi(addr).
// 4: 27390000 addiu t9,t9,%lo(addr).
// 8: 03200008 jr t9.
@ -886,7 +886,8 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
const unsigned NopInstr = 0x0;
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 ||
(AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_64R6)
JrT9Instr = 0x03200009;
writeBytesUnaligned(LuiT9Instr, Addr, 4);
@ -894,6 +895,31 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
writeBytesUnaligned(JrT9Instr, Addr + 8, 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;
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
// Depending on which version of the ELF ABI is in use, we need to
// generate one of two variants of the stub. They both start with

View File

@ -1276,8 +1276,7 @@ RuntimeDyldELF::processRelocationRef(
if (Value.SymbolName) {
addRelocationForSymbol(REHi, Value.SymbolName);
addRelocationForSymbol(RELo, Value.SymbolName);
}
else {
} else {
addRelocationForSection(REHi, Value.SectionID);
addRelocationForSection(RELo, Value.SectionID);
}
@ -1337,11 +1336,81 @@ RuntimeDyldELF::processRelocationRef(
RE.SymOffset = allocateGOTEntries(1);
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);
}
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
if (RelType == ELF::R_PPC64_REL24) {
// Determine ABI variant in use for this object.

View File

@ -66,8 +66,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
return 20; // movz; movk; movk; movk; br
if (Arch == Triple::arm || Arch == Triple::thumb)
return 8; // 32-bit instruction and 32-bit address
else if (IsMipsO32ABI)
else if (IsMipsO32ABI || IsMipsN32ABI)
return 16;
else if (IsMipsN64ABI)
return 32;
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
return 44;
else if (Arch == Triple::x86_64)

View File

@ -116,6 +116,8 @@ int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
<< format("%llx", Section.getLoadAddressWithOffset(Offset))
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
<< format("%x", Type) << " Addend: 0x" << format("%llx", Addend)
<< " Offset: " << format("%llx" PRIx64, Offset)
<< " SID: " << format("%d", SectionID)
<< " SymOffset: " << format("%x", SymOffset) << "\n");
switch (Type) {
@ -141,6 +143,10 @@ int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
return ((Value + Addend + 0x8000) >> 16) & 0xffff;
case ELF::R_MIPS_LO16:
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_GOT_DISP:
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_HI16:
case ELF::R_MIPS_LO16:
case ELF::R_MIPS_HIGHER:
case ELF::R_MIPS_HIGHEST:
case ELF::R_MIPS_PC16:
case ELF::R_MIPS_PCHI16:
case ELF::R_MIPS_PCLO16:
@ -304,7 +312,8 @@ void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,
<< format("%p", Section.getLoadAddressWithOffset(Offset))
<< " Value: " << format("%x", Value)
<< " Type: " << format("%x", Type)
<< " Addend: " << format("%x", Addend) << "\n");
<< " Addend: " << format("%x", Addend)
<< " SymOffset: " << format("%x", Offset) << "\n");
Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);

View File

@ -44,7 +44,7 @@ bar:
sd $4, 8($fp)
# 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:
.option pic0
jal foo

View File

@ -44,7 +44,7 @@ bar:
sd $4, 8($fp)
# 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:
.option pic0
jal foo