[lld] r268876 - [ELF][MIPS] Handling 'packed' N64 ABI relocations
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Sun May 8 07:08:42 PDT 2016
Author: atanasyan
Date: Sun May 8 09:08:40 2016
New Revision: 268876
URL: http://llvm.org/viewvc/llvm-project?rev=268876&view=rev
Log:
[ELF][MIPS] Handling 'packed' N64 ABI relocations
MIPS N64 ABI packs multiple relocations into the single relocation
record. In general, all up to three relocations can have arbitrary types.
In fact, Clang and GCC uses only a few combinations. For now, we support
two of them. That is allow to pass at least all LLVM test suite cases.
<any relocation> / R_MIPS_SUB / R_MIPS_HI16 | R_MIPS_LO16
<any relocation> / R_MIPS_64 / R_MIPS_NONE
The first relocation is a 'real' relocation which is calculated using
the corresponding symbol's value. The second and the third relocations
used to modify result of the first one: extend it to 64-bit, extract
high or low part etc. For details, see part 2.9 'Relocation' at
https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf
Added:
lld/trunk/test/ELF/mips-64-rels.s
Modified:
lld/trunk/ELF/Target.cpp
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=268876&r1=268875&r2=268876&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Sun May 8 09:08:40 2016
@@ -1244,6 +1244,9 @@ template <class ELFT> MipsTargetInfo<ELF
template <class ELFT>
RelExpr MipsTargetInfo<ELFT>::getRelExpr(uint32_t Type,
const SymbolBody &S) const {
+ if (ELFT::Is64Bits)
+ // See comment in the calculateMips64RelChain.
+ Type &= 0xff;
switch (Type) {
default:
return R_ABS;
@@ -1443,14 +1446,44 @@ uint64_t MipsTargetInfo<ELFT>::getImplic
}
}
+static std::pair<uint32_t, uint64_t> calculateMips64RelChain(uint32_t Type,
+ uint64_t Val) {
+ // MIPS N64 ABI packs multiple relocations into the single relocation
+ // record. In general, all up to three relocations can have arbitrary
+ // types. In fact, Clang and GCC uses only a few combinations. For now,
+ // we support two of them. That is allow to pass at least all LLVM
+ // test suite cases.
+ // <any relocation> / R_MIPS_SUB / R_MIPS_HI16 | R_MIPS_LO16
+ // <any relocation> / R_MIPS_64 / R_MIPS_NONE
+ // The first relocation is a 'real' relocation which is calculated
+ // using the corresponding symbol's value. The second and the third
+ // relocations used to modify result of the first one: extend it to
+ // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation
+ // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf
+ uint32_t Type2 = (Type >> 8) & 0xff;
+ uint32_t Type3 = (Type >> 16) & 0xff;
+ if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE)
+ return std::make_pair(Type, Val);
+ if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE)
+ return std::make_pair(Type2, Val);
+ if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16))
+ return std::make_pair(Type3, -Val);
+ error("unsupported relocations combination " + Twine(Type));
+ return std::make_pair(Type & 0xff, Val);
+}
+
template <class ELFT>
void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
uint64_t Val) const {
const endianness E = ELFT::TargetEndianness;
// Thread pointer and DRP offsets from the start of TLS data area.
// https://www.linux-mips.org/wiki/NPTL
- const uint32_t TPOffset = 0x7000;
- const uint32_t DTPOffset = 0x8000;
+ if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16)
+ Val -= 0x8000;
+ else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16)
+ Val -= 0x7000;
+ if (ELFT::Is64Bits)
+ std::tie(Type, Val) = calculateMips64RelChain(Type, Val);
switch (Type) {
case R_MIPS_32:
case R_MIPS_GPREL32:
@@ -1472,10 +1505,14 @@ void MipsTargetInfo<ELFT>::relocateOne(u
case R_MIPS_GOT_OFST:
case R_MIPS_LO16:
case R_MIPS_PCLO16:
+ case R_MIPS_TLS_DTPREL_LO16:
+ case R_MIPS_TLS_TPREL_LO16:
writeMipsLo16<E>(Loc, Val);
break;
case R_MIPS_HI16:
case R_MIPS_PCHI16:
+ case R_MIPS_TLS_DTPREL_HI16:
+ case R_MIPS_TLS_TPREL_HI16:
writeMipsHi16<E>(Loc, Val);
break;
case R_MIPS_JALR:
@@ -1496,18 +1533,6 @@ void MipsTargetInfo<ELFT>::relocateOne(u
case R_MIPS_PC32:
applyMipsPcReloc<E, 32, 0>(Loc, Type, Val);
break;
- case R_MIPS_TLS_DTPREL_HI16:
- writeMipsHi16<E>(Loc, Val - DTPOffset);
- break;
- case R_MIPS_TLS_DTPREL_LO16:
- writeMipsLo16<E>(Loc, Val - DTPOffset);
- break;
- case R_MIPS_TLS_TPREL_HI16:
- writeMipsHi16<E>(Loc, Val - TPOffset);
- break;
- case R_MIPS_TLS_TPREL_LO16:
- writeMipsLo16<E>(Loc, Val - TPOffset);
- break;
default:
fatal("unrecognized reloc " + Twine(Type));
}
Added: lld/trunk/test/ELF/mips-64-rels.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-64-rels.s?rev=268876&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-64-rels.s (added)
+++ lld/trunk/test/ELF/mips-64-rels.s Sun May 8 09:08:40 2016
@@ -0,0 +1,46 @@
+# Check handling multiple MIPS N64 ABI relocations packed
+# into the single relocation record.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t.exe
+# RUN: llvm-objdump -d -s -t %t.exe | FileCheck %s
+# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
+
+# REQUIRES: mips
+
+# CHECK: __start:
+# CHECK-NEXT: 20000: 3c 1c 00 01 lui $gp, 1
+# ^-- 0x20000 - 0x37ff0
+# ^-- 0 - 0xfffffffffffe8010
+# ^-- %hi(0x17ff0)
+# CHECK: loc:
+# CHECK-NEXT: 20004: 67 9c 7f f0 daddiu $gp, $gp, 32752
+# ^-- 0x20000 - 0x37ff0
+# ^-- 0 - 0xfffffffffffe8010
+# ^-- %lo(0x17ff0)
+
+# CHECK: Contents of section .rodata:
+# CHECK-NEXT: 10190 ffffffff fffe8014
+# ^-- 0x20004 - 0x37ff0 = 0xfffffffffffe8014
+
+# CHECK: 0000000000020004 .text 00000000 loc
+# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
+# CHECK: 0000000000020000 .text 00000000 __start
+
+# REL: Relocations [
+# REL-NEXT: ]
+
+ .text
+ .global __start
+__start:
+ lui $gp,%hi(%neg(%gp_rel(__start))) # R_MIPS_GPREL16
+ # R_MIPS_SUB
+ # R_MIPS_HI16
+loc:
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(__start))) # R_MIPS_GPREL16
+ # R_MIPS_SUB
+ # R_MIPS_LO16
+
+ .section .rodata,"a", at progbits
+ .gpdword(loc) # R_MIPS_GPREL32
+ # R_MIPS_64
More information about the llvm-commits
mailing list