From: Simon Atanasyan Date: Mon, 21 Dec 2015 17:36:40 +0000 (+0000) Subject: [ELF][MIPS] Support some of R_MIPS_PCxxx relocations X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0fc0acf18028a17eba7dd0e1c230134a8c25879c;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index ef814a3..0456b44 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -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::relocNeedsPlt(uint32_t Type, static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; } +template +static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t P, + uint64_t SA) { + uint32_t Mask = ~(0xffffffff << BSIZE); + uint32_t Instr = read32(Loc); + int64_t A = SignExtend64((Instr & Mask) << 2); + checkAlignment<4>(SA + A, Type); + int64_t V = SA + A - P; + checkInt(V, Type); + write32(Loc, (Instr & ~Mask) | ((V >> 2) & Mask)); +} + template void MipsTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, @@ -1390,11 +1403,56 @@ void MipsTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, write32(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff)); break; } + case R_MIPS_PC16: + applyMipsPcReloc(Loc, Type, P, SA); + break; + case R_MIPS_PC19_S2: + applyMipsPcReloc(Loc, Type, P, SA); + break; + case R_MIPS_PC21_S2: + applyMipsPcReloc(Loc, Type, P, SA); + break; + case R_MIPS_PC26_S2: + applyMipsPcReloc(Loc, Type, P, SA); + break; + case R_MIPS_PCHI16: { + uint32_t Instr = read32(Loc); + if (PairedLoc) { + uint64_t AHL = ((Instr & 0xffff) << 16) + + SignExtend64<16>(read32(PairedLoc) & 0xffff); + write32(Loc, (Instr & 0xffff0000) | mipsHigh(SA + AHL - P)); + } else { + warning("Can't find matching R_MIPS_PCLO16 relocation for R_MIPS_PCHI16"); + write32(Loc, (Instr & 0xffff0000) | mipsHigh(SA - P)); + } + break; + } + case R_MIPS_PCLO16: { + uint32_t Instr = read32(Loc); + int64_t AHL = SignExtend64<16>(Instr & 0xffff); + write32(Loc, (Instr & 0xffff0000) | ((SA + AHL - P) & 0xffff)); + break; + } default: error("unrecognized reloc " + Twine(Type)); } } +template +bool MipsTargetInfo::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 typename ELFFile::uintX_t getMipsGpAddr() { const unsigned GPOffset = 0x7ff0; return Out::Got->getVA() ? (Out::Got->getVA() + GPOffset) : 0; diff --git a/lld/test/ELF/mips-pc-relocs.s b/lld/test/ELF/mips-pc-relocs.s new file mode 100644 index 0000000..631dd43 --- /dev/null +++ b/lld/test/ELF/mips-pc-relocs.s @@ -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