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

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:
Sagar Thakur 2017-06-22 11:49:19 +00:00
parent 9efb4e04c7
commit 74e536eb62
4 changed files with 124 additions and 15 deletions

View File

@ -861,7 +861,7 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
// and stubs for branches Thumb - ARM and ARM - Thumb.
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,<label>
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.
@ -869,13 +869,39 @@ 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)
JrT9Instr = 0x03200009;
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);
writeBytesUnaligned(AdduiT9Instr, Addr+4, 4);
writeBytesUnaligned(JrT9Instr, Addr+8, 4);
writeBytesUnaligned(NopInstr, Addr+12, 4);
writeBytesUnaligned(AdduiT9Instr, Addr + 4, 4);
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

View File

@ -1251,8 +1251,7 @@ RuntimeDyldELF::processRelocationRef(
if (Value.SymbolName) {
addRelocationForSymbol(REHi, Value.SymbolName);
addRelocationForSymbol(RELo, Value.SymbolName);
}
else {
} else {
addRelocationForSection(REHi, Value.SectionID);
addRelocationForSection(RELo, Value.SectionID);
}
@ -1301,10 +1300,14 @@ RuntimeDyldELF::processRelocationRef(
processSimpleRelocation(SectionID, Offset, RelType, Value);
}
} 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;
RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE
|| r_type == ELF::R_MIPS_GOT_DISP) {
if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE ||
r_type == ELF::R_MIPS_GOT_DISP) {
StringMap<uint64_t>::iterator i = GOTSymbolOffsets.find(TargetName);
if (i != GOTSymbolOffsets.end())
RE.SymOffset = i->second;
@ -1312,11 +1315,83 @@ 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 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) {
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

@ -141,6 +141,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 +219,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: