[lld] r254461 - [ELF] MIPS paired R_MIPS_HI16/LO16 relocations support
Hal Finkel via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 1 13:51:07 PST 2015
----- Original Message -----
> From: "Simon Atanasyan via llvm-commits" <llvm-commits at lists.llvm.org>
> To: llvm-commits at lists.llvm.org
> Sent: Tuesday, December 1, 2015 3:24:46 PM
> Subject: [lld] r254461 - [ELF] MIPS paired R_MIPS_HI16/LO16 relocations support
>
> Author: atanasyan
> Date: Tue Dec 1 15:24:45 2015
> New Revision: 254461
>
> URL: http://llvm.org/viewvc/llvm-project?rev=254461&view=rev
> Log:
> [ELF] MIPS paired R_MIPS_HI16/LO16 relocations support
>
> Some MIPS relocations including `R_MIPS_HI16/R_MIPS_LO16` use
> combined
> addends. Such addend is calculated using addends of both paired
> relocations.
> Each `R_MIPS_HI16` relocation is paired with the next `R_MIPS_LO16`
> relocation. ABI requires to compute such combined addend in case of
> REL
> relocation record format only.
>
> For details see p. 4-17 at
> ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
>
> This patch implements lookup of the next paired relocation suing new
> `InputSectionBase::findPairedRelocLocation` method. The primary
> disadvantage of this approach is that we put MIPS specific logic into
> the common code. The next disadvantage is that we lookup
> `R_MIPS_LO16`
> for each `R_MIPS_HI16` relocation, while in fact multiple
> `R_MIPS_HI16`
> might be paired with the single `R_MIPS_LO16`. From the other side
> this way allows us to keep `MipsTargetInfo` class stateless and
> implement
> later relocation handling in parallel.
>
> This patch does not support `R_MIPS_HI16/R_MIPS_LO16` relocations
> against
> `_gp_disp` symbol. In that case the relocations use a special formula
> for
> the calculation. That will be implemented later.
>
> Differential Revision: http://reviews.llvm.org/D15112
>
> Added:
> lld/trunk/test/ELF/mips-hilo-hi-only.s
> lld/trunk/test/ELF/mips-hilo.s
> Modified:
> lld/trunk/ELF/InputSection.cpp
> lld/trunk/ELF/InputSection.h
> lld/trunk/ELF/Target.cpp
> lld/trunk/ELF/Target.h
>
> Modified: lld/trunk/ELF/InputSection.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=254461&r1=254460&r2=254461&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputSection.cpp (original)
> +++ lld/trunk/ELF/InputSection.cpp Tue Dec 1 15:24:45 2015
> @@ -94,9 +94,38 @@ bool InputSection<ELFT>::classof(const I
>
> template <class ELFT>
> template <bool isRela>
> -void InputSectionBase<ELFT>::relocate(
> - uint8_t *Buf, uint8_t *BufEnd,
> - iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
> +uint8_t *
> +InputSectionBase<ELFT>::findMipsPairedReloc(uint8_t *Buf, uint32_t
> Type,
> + RelIteratorRange<isRela>
> Rels) {
> + // Some MIPS relocations use addend calculated from addend of the
> relocation
> + // itself and addend of paired relocation. ABI requires to compute
> such
> + // combined addend in case of REL relocation record format only.
> + // See p. 4-17 at
> ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
> + if (isRela || Config->EMachine != EM_MIPS)
> + return nullptr;
> + if (Type == R_MIPS_HI16)
> + Type = R_MIPS_LO16;
> + else if (Type == R_MIPS_PCHI16)
> + Type = R_MIPS_PCLO16;
> + else if (Type == R_MICROMIPS_HI16)
> + Type = R_MICROMIPS_LO16;
> + else
> + return nullptr;
> + for (const auto &RI : Rels) {
> + if (RI.getType(Config->Mips64EL) != Type)
> + continue;
> + uintX_t Offset = getOffset(RI.r_offset);
> + if (Offset == (uintX_t)-1)
> + return nullptr;
> + return Buf + Offset;
> + }
> + return nullptr;
> +}
> +
> +template <class ELFT>
> +template <bool isRela>
> +void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
> + RelIteratorRange<isRela> Rels)
> {
> typedef Elf_Rel_Impl<ELFT, isRela> RelType;
> size_t Num = Rels.end() - Rels.begin();
> for (size_t I = 0; I < Num; ++I) {
> @@ -109,6 +138,7 @@ void InputSectionBase<ELFT>::relocate(
>
> uint8_t *BufLoc = Buf + Offset;
> uintX_t AddrLoc = OutSec->getVA() + Offset;
> + auto NextRelocs = llvm::make_range(&RI, Rels.end());
If I'm reading this correctly, this search is O(N^2/2) in the worst case. Is there some reason you don't get that behavior in practice?
It seems like if we presorted a list by <type, offset>, we could easily make this O(N*ln(N)) instead.
-Hal
>
> if (Target->isTlsLocalDynamicReloc(Type) &&
> !Target->isTlsOptimized(Type, nullptr)) {
> @@ -123,7 +153,8 @@ void InputSectionBase<ELFT>::relocate(
> const Elf_Shdr *SymTab = File->getSymbolTable();
> if (SymIndex < SymTab->sh_info) {
> uintX_t SymVA = getLocalRelTarget(*File, RI);
> - Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA);
> + Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA,
> + findMipsPairedReloc(Buf, Type,
> NextRelocs));
> continue;
> }
>
> @@ -161,7 +192,8 @@ void InputSectionBase<ELFT>::relocate(
> continue;
> }
> Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
> - SymVA + getAddend<ELFT>(RI));
> + SymVA + getAddend<ELFT>(RI),
> + findMipsPairedReloc(Buf, Type, NextRelocs));
> }
> }
>
>
> Modified: lld/trunk/ELF/InputSection.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=254461&r1=254460&r2=254461&view=diff
> ==============================================================================
> --- lld/trunk/ELF/InputSection.h (original)
> +++ lld/trunk/ELF/InputSection.h Tue Dec 1 15:24:45 2015
> @@ -76,9 +76,16 @@ public:
> InputSectionBase<ELFT> *getRelocTarget(const Elf_Rela &Rel);
>
> template <bool isRela>
> - void relocate(uint8_t *Buf, uint8_t *BufEnd,
> - llvm::iterator_range<
> - const llvm::object::Elf_Rel_Impl<ELFT, isRela>
> *> Rels);
> + using RelIteratorRange =
> + llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT,
> isRela> *>;
> +
> + template <bool isRela>
> + void relocate(uint8_t *Buf, uint8_t *BufEnd,
> RelIteratorRange<isRela> Rels);
> +
> +private:
> + template <bool isRela>
> + uint8_t *findMipsPairedReloc(uint8_t *Buf, uint32_t Type,
> + RelIteratorRange<isRela> Rels);
> };
>
> template <class ELFT>
>
> Modified: lld/trunk/ELF/Target.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=254461&r1=254460&r2=254461&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Target.cpp (original)
> +++ lld/trunk/ELF/Target.cpp Tue Dec 1 15:24:45 2015
> @@ -87,7 +87,7 @@ public:
> bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const
> override;
> bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const
> override;
> void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
> uint64_t P,
> - uint64_t SA) const override;
> + uint64_t SA, uint8_t *PairedLoc = nullptr) const
> override;
> };
>
> class X86_64TargetInfo final : public TargetInfo {
> @@ -106,7 +106,7 @@ public:
> bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const
> override;
> bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const
> override;
> void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
> uint64_t P,
> - uint64_t SA) const override;
> + uint64_t SA, uint8_t *PairedLoc = nullptr) const
> override;
> bool isRelRelative(uint32_t Type) const override;
> bool isTlsOptimized(unsigned Type, const SymbolBody *S) const
> override;
> unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
> uint32_t Type,
> @@ -133,7 +133,7 @@ public:
> bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const
> override;
> bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const
> override;
> void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
> uint64_t P,
> - uint64_t SA) const override;
> + uint64_t SA, uint8_t *PairedLoc = nullptr) const
> override;
> bool isRelRelative(uint32_t Type) const override;
> };
>
> @@ -150,7 +150,7 @@ public:
> bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const
> override;
> bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const
> override;
> void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
> uint64_t P,
> - uint64_t SA) const override;
> + uint64_t SA, uint8_t *PairedLoc = nullptr) const
> override;
> };
>
> template <class ELFT> class MipsTargetInfo final : public TargetInfo
> {
> @@ -166,7 +166,7 @@ public:
> bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const
> override;
> bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const
> override;
> void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
> uint64_t P,
> - uint64_t SA) const override;
> + uint64_t SA, uint8_t *PairedLoc = nullptr) const
> override;
> };
> } // anonymous namespace
>
> @@ -308,7 +308,8 @@ bool X86TargetInfo::relocNeedsPlt(uint32
> }
>
> void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
> uint32_t Type,
> - uint64_t P, uint64_t SA) const {
> + uint64_t P, uint64_t SA,
> + uint8_t *PairedLoc) const {
> switch (Type) {
> case R_386_32:
> add32le(Loc, SA);
> @@ -581,7 +582,8 @@ unsigned X86_64TargetInfo::relocateTlsOp
> }
>
> void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
> uint32_t Type,
> - uint64_t P, uint64_t SA) const {
> + uint64_t P, uint64_t SA,
> + uint8_t *PairedLoc) const {
> switch (Type) {
> case R_X86_64_32:
> checkUInt<32>(SA, Type);
> @@ -728,7 +730,8 @@ bool PPC64TargetInfo::isRelRelative(uint
> }
>
> void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
> uint32_t Type,
> - uint64_t P, uint64_t SA) const {
> + uint64_t P, uint64_t SA,
> + uint8_t *PairedLoc) const {
> uint64_t TB = getPPC64TocBase();
>
> // For a TOC-relative relocation, adjust the addend and proceed in
> terms of
> @@ -933,8 +936,8 @@ static uint64_t getAArch64Page(uint64_t
> }
>
> void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
> - uint32_t Type, uint64_t P,
> - uint64_t SA) const {
> + uint32_t Type, uint64_t P,
> uint64_t SA,
> + uint8_t *PairedLoc) const {
> switch (Type) {
> case R_AARCH64_ABS16:
> checkIntUInt<16>(SA, Type);
> @@ -1046,13 +1049,31 @@ bool MipsTargetInfo<ELFT>::relocNeedsPlt
>
> template <class ELFT>
> void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t
> *BufEnd,
> - uint32_t Type, uint64_t P,
> - uint64_t SA) const {
> + uint32_t Type, uint64_t P,
> uint64_t SA,
> + uint8_t *PairedLoc) const {
> const endianness E = ELFT::TargetEndianness;
> switch (Type) {
> case R_MIPS_32:
> add32<E>(Loc, SA);
> break;
> + case R_MIPS_HI16: {
> + uint32_t Instr = read32<E>(Loc);
> + if (PairedLoc) {
> + uint64_t AHL = ((Instr & 0xffff) << 16) +
> + llvm::SignExtend64<16>(read32<E>(PairedLoc) &
> 0xffff);
> + write32<E>(Loc, (Instr & 0xffff0000) | (((SA + AHL) >> 16) &
> 0xffff));
> + } else {
> + warning("Can't find matching R_MIPS_LO16 relocation for
> R_MIPS_HI16");
> + write32<E>(Loc, (Instr & 0xffff0000) | ((SA >> 16) & 0xffff));
> + }
> + break;
> + }
> + case R_MIPS_LO16: {
> + uint32_t Instr = read32<E>(Loc);
> + int64_t AHL = llvm::SignExtend64<16>(Instr & 0xffff);
> + write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff));
> + break;
> + }
> case R_MIPS_CALL16:
> case R_MIPS_GOT16: {
> int64_t V = SA - getMipsGpAddr<ELFT>();
>
> Modified: lld/trunk/ELF/Target.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=254461&r1=254460&r2=254461&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Target.h (original)
> +++ lld/trunk/ELF/Target.h Tue Dec 1 15:24:45 2015
> @@ -57,7 +57,8 @@ public:
> virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S)
> const = 0;
> virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S)
> const = 0;
> virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t
> Type,
> - uint64_t P, uint64_t SA) const = 0;
> + uint64_t P, uint64_t SA,
> + uint8_t *PairedLoc = nullptr) const = 0;
> virtual bool isTlsOptimized(unsigned Type, const SymbolBody *S)
> const;
> virtual unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t
> *BufEnd,
> uint32_t Type, uint64_t P,
>
> Added: lld/trunk/test/ELF/mips-hilo-hi-only.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-hilo-hi-only.s?rev=254461&view=auto
> ==============================================================================
> --- lld/trunk/test/ELF/mips-hilo-hi-only.s (added)
> +++ lld/trunk/test/ELF/mips-hilo-hi-only.s Tue Dec 1 15:24:45 2015
> @@ -0,0 +1,22 @@
> +# Check warning on orphaned R_MIPS_HI16 relocations.
> +
> +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
> +# RUN: ld.lld %t.o -o %t.exe 2>&1 | FileCheck -check-prefix=WARN %s
> +# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
> +
> +# REQUIRES: mips
> +
> + .text
> + .globl __start
> +__start:
> + lui $t0,%hi(__start+0x10000)
> +
> +# WARN: Can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16
> +
> +# CHECK: Disassembly of section .text:
> +# CHECK-NEXT: __start:
> +# CHECK-NEXT: 20000: 3c 08 00 02 lui $8, 2
> +# ^-- %hi(__start)
> w/o addend
> +
> +# CHECK: SYMBOL TABLE:
> +# CHECK: 0020000 .text 00000000 __start
>
> Added: lld/trunk/test/ELF/mips-hilo.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-hilo.s?rev=254461&view=auto
> ==============================================================================
> --- lld/trunk/test/ELF/mips-hilo.s (added)
> +++ lld/trunk/test/ELF/mips-hilo.s Tue Dec 1 15:24:45 2015
> @@ -0,0 +1,53 @@
> +# Check R_MIPS_HI16 / LO16 relocations calculation.
> +
> +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
> +# RUN: ld.lld %t.o -o %t.exe
> +# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
> +
> +# REQUIRES: mips
> +
> + .text
> + .globl __start
> +__start:
> + lui $t0,%hi(__start)
> + lui $t1,%hi(g1)
> + addi $t0,$t0,%lo(__start+4)
> + addi $t0,$t0,%lo(g1+8)
> +
> + lui $t0,%hi(l1+0x10000)
> + lui $t1,%hi(l1+0x20000)
> + addi $t0,$t0,%lo(l1+(-4))
> +
> + .data
> + .type l1, at object
> + .size l1,4
> +l1:
> + .word 0
> +
> + .globl g1
> + .type g1, at object
> + .size g1,4
> +g1:
> + .word 0
> +
> +# CHECK: Disassembly of section .text:
> +# CHECK-NEXT: __start:
> +# CHECK-NEXT: 20000: 3c 08 00 02 lui $8, 2
> +# ^-- %hi(__start+4)
> +# CHECK-NEXT: 20004: 3c 09 00 03 lui $9, 3
> +# ^-- %hi(g1+8)
> +# CHECK-NEXT: 20008: 21 08 00 04 addi $8, $8, 4
> +# ^--
> %lo(__start+4)
> +# CHECK-NEXT: 2000c: 21 08 00 0c addi $8, $8, 12
> +# ^-- %lo(g1+8)
> +# CHECK-NEXT: 20010: 3c 08 00 03 lui $8, 3
> +# ^--
> %hi(l1+0x10000-4)
> +# CHECK-NEXT: 20014: 3c 09 00 04 lui $9, 4
> +# ^--
> %hi(l1+0x20000-4)
> +# CHECK-NEXT: 20018: 21 08 ff fc addi $8, $8, -4
> +# ^-- %lo(l1-4)
> +
> +# CHECK: SYMBOL TABLE:
> +# CHECK: 0030000 l .data 00000004 l1
> +# CHECK: 0020000 .text 00000000 __start
> +# CHECK: 0030004 g .data 00000004 g1
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
--
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory
More information about the llvm-commits
mailing list