forked from OSchip/llvm-project
[ELF][MIPS] Support some of R_MIPS_PCxxx relocations
The patch adds support for R_MIPS_PC16, R_MIPS_PC19_S2, R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PCHI16, R_MIPS_PCLO16 relocations handling. llvm-svn: 256172
This commit is contained in:
parent
4f04d85fa6
commit
0fc0acf180
|
@ -206,6 +206,7 @@ public:
|
|||
void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
|
||||
uint64_t SA, uint64_t ZA = 0,
|
||||
uint8_t *PairedLoc = nullptr) const override;
|
||||
bool isRelRelative(uint32_t Type) const override;
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -1352,6 +1353,18 @@ bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type,
|
|||
|
||||
static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; }
|
||||
|
||||
template <endianness E, uint8_t BSIZE>
|
||||
static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t P,
|
||||
uint64_t SA) {
|
||||
uint32_t Mask = ~(0xffffffff << BSIZE);
|
||||
uint32_t Instr = read32<E>(Loc);
|
||||
int64_t A = SignExtend64<BSIZE + 2>((Instr & Mask) << 2);
|
||||
checkAlignment<4>(SA + A, Type);
|
||||
int64_t V = SA + A - P;
|
||||
checkInt<BSIZE + 2>(V, Type);
|
||||
write32<E>(Loc, (Instr & ~Mask) | ((V >> 2) & Mask));
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
|
||||
uint32_t Type, uint64_t P, uint64_t SA,
|
||||
|
@ -1390,11 +1403,56 @@ void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
|
|||
write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff));
|
||||
break;
|
||||
}
|
||||
case R_MIPS_PC16:
|
||||
applyMipsPcReloc<E, 16>(Loc, Type, P, SA);
|
||||
break;
|
||||
case R_MIPS_PC19_S2:
|
||||
applyMipsPcReloc<E, 19>(Loc, Type, P, SA);
|
||||
break;
|
||||
case R_MIPS_PC21_S2:
|
||||
applyMipsPcReloc<E, 21>(Loc, Type, P, SA);
|
||||
break;
|
||||
case R_MIPS_PC26_S2:
|
||||
applyMipsPcReloc<E, 26>(Loc, Type, P, SA);
|
||||
break;
|
||||
case R_MIPS_PCHI16: {
|
||||
uint32_t Instr = read32<E>(Loc);
|
||||
if (PairedLoc) {
|
||||
uint64_t AHL = ((Instr & 0xffff) << 16) +
|
||||
SignExtend64<16>(read32<E>(PairedLoc) & 0xffff);
|
||||
write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA + AHL - P));
|
||||
} else {
|
||||
warning("Can't find matching R_MIPS_PCLO16 relocation for R_MIPS_PCHI16");
|
||||
write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA - P));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R_MIPS_PCLO16: {
|
||||
uint32_t Instr = read32<E>(Loc);
|
||||
int64_t AHL = SignExtend64<16>(Instr & 0xffff);
|
||||
write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL - P) & 0xffff));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error("unrecognized reloc " + Twine(Type));
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool MipsTargetInfo<ELFT>::isRelRelative(uint32_t Type) const {
|
||||
switch (Type) {
|
||||
default:
|
||||
return false;
|
||||
case R_MIPS_PC16:
|
||||
case R_MIPS_PC19_S2:
|
||||
case R_MIPS_PC21_S2:
|
||||
case R_MIPS_PC26_S2:
|
||||
case R_MIPS_PCHI16:
|
||||
case R_MIPS_PCLO16:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT> typename ELFFile<ELFT>::uintX_t getMipsGpAddr() {
|
||||
const unsigned GPOffset = 0x7ff0;
|
||||
return Out<ELFT>::Got->getVA() ? (Out<ELFT>::Got->getVA() + GPOffset) : 0;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Check R_MIPS_PCxxx relocations calculation.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
|
||||
# RUN: -mcpu=mips32r6 %s -o %t1.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
|
||||
# RUN: -mcpu=mips32r6 %S/Inputs/mips-dynamic.s -o %t2.o
|
||||
# RUN: ld.lld %t1.o %t2.o -o %t.exe
|
||||
# RUN: llvm-objdump -mcpu=mips32r6 -d -t %t.exe | FileCheck %s
|
||||
|
||||
# REQUIRES: mips
|
||||
|
||||
.text
|
||||
.globl __start
|
||||
__start:
|
||||
lwpc $6, _foo # R_MIPS_PC19_S2
|
||||
beqc $5, $6, _foo # R_MIPS_PC16
|
||||
beqzc $9, _foo # R_MIPS_PC21_S2
|
||||
bc _foo # R_MIPS_PC26_S2
|
||||
aluipc $2, %pcrel_hi(_foo) # R_MIPS_PCHI16
|
||||
addiu $2, $2, %pcrel_lo(_foo) # R_MIPS_PCLO16
|
||||
|
||||
# CHECK: Disassembly of section .text:
|
||||
# CHECK-NEXT: __start:
|
||||
# CHECK-NEXT: 20000: ec c8 00 08 lwpc $6, 32
|
||||
# ^-- (0x20020-0x20000)>>2
|
||||
# CHECK-NEXT: 20004: 20 a6 00 06 beqc $5, $6, 24
|
||||
# ^-- (0x20020-4-0x20004)>>2
|
||||
# CHECK-NEXT: 20008: d9 20 00 05 beqzc $9, 20
|
||||
# ^-- (0x20020-4-0x20008)>>2
|
||||
# CHECK-NEXT: 2000c: c8 00 00 04 bc 16
|
||||
# ^-- (0x20020-4-0x2000c)>>2
|
||||
# CHECK-NEXT: 20010: ec 5f 00 00 aluipc $2, 0
|
||||
# ^-- %hi(0x20020-0x20010)
|
||||
# CHECK-NEXT: 20014: 24 42 00 0c addiu $2, $2, 12
|
||||
# ^-- %lo(0x20020-0x20014)
|
||||
|
||||
# CHECK: 00020000 .text 00000000 __start
|
||||
# CHECK: 00020020 .text 00000000 _foo
|
Loading…
Reference in New Issue