[lld] r250297 - [ELF2][mips] Support both big and little endian MIPS 32-bit targets

Hal Finkel via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 14 11:29:34 PDT 2015


----- Original Message -----
> From: "Simon Atanasyan via llvm-commits" <llvm-commits at lists.llvm.org>
> To: llvm-commits at lists.llvm.org
> Sent: Wednesday, October 14, 2015 9:24:46 AM
> Subject: [lld] r250297 - [ELF2][mips] Support both big and little endian MIPS 32-bit targets
> 
> Author: atanasyan
> Date: Wed Oct 14 09:24:46 2015
> New Revision: 250297
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=250297&view=rev
> Log:
> [ELF2][mips] Support both big and little endian MIPS 32-bit targets
> 
> - Make the `MipsTargetInfo` template class with `ELFType` argument.
> Use
>   the argument to select an appropriate relocation type and
>   read/write
>   routines.
> - Add template function `add32` to add-and-write relocation value in
>   both big and little endian cases. Keep the `add32le` to reduce code
>   changes.
> 
> Differential Revision: http://reviews.llvm.org/D13723
> 
> Modified:
>     lld/trunk/ELF/Target.cpp
>     lld/trunk/ELF/Target.h
>     lld/trunk/test/elf2/mips-relocs.s
> 
> Modified: lld/trunk/ELF/Target.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=250297&r1=250296&r2=250297&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Target.cpp (original)
> +++ lld/trunk/ELF/Target.cpp Wed Oct 14 09:24:46 2015
> @@ -39,7 +39,14 @@ TargetInfo *createTarget() {
>    case EM_AARCH64:
>      return new AArch64TargetInfo();
>    case EM_MIPS:
> -    return new MipsTargetInfo();
> +    switch (Config->EKind) {
> +    case ELF32LEKind:
> +      return new MipsTargetInfo<ELF32LE>();
> +    case ELF32BEKind:
> +      return new MipsTargetInfo<ELF32BE>();
> +    default:
> +      error("Unsupported MIPS target");
> +    }
>    case EM_PPC:
>      return new PPCTargetInfo();
>    case EM_PPC64:
> @@ -84,8 +91,13 @@ bool X86TargetInfo::relocNeedsPlt(uint32
>  }
>  
>  static void add32le(uint8_t *L, int32_t V) { write32le(L,
>  read32le(L) + V); }
> +static void add32be(uint8_t *L, int32_t V) { write32be(L,
> read32be(L) + V); }
>  static void or32le(uint8_t *L, int32_t V) { write32le(L, read32le(L)
>  | V); }
>  
> +template <bool IsLE> static void add32(uint8_t *L, int32_t V);
> +template <> void add32<true>(uint8_t *L, int32_t V) { add32le(L, V);
> }
> +template <> void add32<false>(uint8_t *L, int32_t V) { add32be(L,
> V); }

I think that we should be able to find a cleaner way to do this. add32le and add32be are implemented in terms of write32le and write32be, and these are defined like this (in include/llvm/Support/Endian.h):

inline uint32_t read32le(const void *p) { return *(const ulittle32_t *)p; }
inline uint32_t read32be(const void *p) { return *(const ubig32_t *)p; }
inline void write32le(void *p, uint32_t v) { *(ulittle32_t *)p = v; }
inline void write32be(void *p, uint32_t v) { *(ubig32_t *)p = v; }

and those types are:

typedef detail::packed_endian_specific_integral
                  <uint32_t, little, unaligned> ulittle32_t;
typedef detail::packed_endian_specific_integral
                  <uint32_t, big, unaligned>    ubig32_t;

so all of these things are implemented using the same operations on values of the same templated type (just with a difference in the second template parameter: big or little endian).

One solution would be to define:

template <endianness endian>
inline uint32_t read32(const void *p) { return *(const detail::packed_endian_specific_integral<uint32_t, endian, unaligned> *) p; }

and similar for write32, and implement Endian-independent things in terms of those.

 -Hal

> +
>  void X86TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, const
>  void *RelP,
>                                  uint32_t Type, uint64_t BaseAddr,
>                                  uint64_t SymVA) const {
> @@ -542,32 +554,40 @@ void AArch64TargetInfo::relocateOne(uint
>    }
>  }
>  
> -MipsTargetInfo::MipsTargetInfo() {
> +template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
>    // PCRelReloc = FIXME
>    // GotReloc = FIXME
>    PageSize = 65536;
>  }
>  
> -void MipsTargetInfo::writePltEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> -                                   uint64_t PltEntryAddr) const {}
> -
> -bool MipsTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody
> &S) const {
> +template <class ELFT>
> +void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> +                                         uint64_t PltEntryAddr)
> const {}
> +
> +template <class ELFT>
> +bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
> +                                         const SymbolBody &S) const
> {
>    return false;
>  }
>  
> -bool MipsTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody
> &S) const {
> +template <class ELFT>
> +bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type,
> +                                         const SymbolBody &S) const
> {
>    return false;
>  }
>  
> -void MipsTargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
> -                                 const void *RelP, uint32_t Type,
> -                                 uint64_t BaseAddr, uint64_t SymVA)
> const {
> -  typedef ELFFile<ELF32LE>::Elf_Rel Elf_Rel;
> +template <class ELFT>
> +void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Buf, uint8_t
> *BufEnd,
> +                                       const void *RelP, uint32_t
> Type,
> +                                       uint64_t BaseAddr,
> +                                       uint64_t SymVA) const {
> +  const bool IsLE = ELFT::TargetEndianness == support::little;
> +  typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
>    auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP);
>  
>    switch (Type) {
>    case R_MIPS_32:
> -    add32le(Buf + Rel.r_offset, SymVA);
> +    add32<IsLE>(Buf + Rel.r_offset, SymVA);
>      break;
>    default:
>      error("unrecognized reloc " + Twine(Type));
> 
> Modified: lld/trunk/ELF/Target.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=250297&r1=250296&r2=250297&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Target.h (original)
> +++ lld/trunk/ELF/Target.h Wed Oct 14 09:24:46 2015
> @@ -110,7 +110,7 @@ public:
>                     uint64_t SymVA) const override;
>  };
>  
> -class MipsTargetInfo final : public TargetInfo {
> +template <class ELFT> class MipsTargetInfo final : public TargetInfo
> {
>  public:
>    MipsTargetInfo();
>    void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> 
> Modified: lld/trunk/test/elf2/mips-relocs.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/mips-relocs.s?rev=250297&r1=250296&r2=250297&view=diff
> ==============================================================================
> --- lld/trunk/test/elf2/mips-relocs.s (original)
> +++ lld/trunk/test/elf2/mips-relocs.s Wed Oct 14 09:24:46 2015
> @@ -1,7 +1,14 @@
>  # Check R_MIPS_32 relocation calculation.
> -# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t.o
> -# RUN: ld.lld2 %t.o -o %t.exe
> -# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
> +
> +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o
> %t-be.o
> +# RUN: ld.lld2 %t-be.o -o %t-be.exe
> +# RUN: llvm-objdump -t %t-be.exe | FileCheck %s
> +# RUN: llvm-objdump -s %t-be.exe | FileCheck -check-prefix=BE %s
> +
> +# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o
> %t-el.o
> +# RUN: ld.lld2 %t-el.o -o %t-el.exe
> +# RUN: llvm-objdump -t %t-el.exe | FileCheck %s
> +# RUN: llvm-objdump -s %t-el.exe | FileCheck -check-prefix=EL %s
>  
>  # REQUIRES: mips
>  
> @@ -22,10 +29,14 @@ v2:
>    .word v2+4 # R_MIPS_32 target v2 addend 4
>    .word v1   # R_MIPS_32 target v1 addend 0
>  
> -# CHECK: Contents of section .data:
> -# CHECK-NEXT: 30000 00000000 08000300 00000300
> -#                            ^-- v2+4 ^-- v1
> -
>  # CHECK: SYMBOL TABLE:
>  # CHECK: 00030000 l       .data           00000004 v1
>  # CHECK: 00030004 g       .data           00000008 v2
> +
> +# BE: Contents of section .data:
> +# BE-NEXT: 30000 00000000 00030008 00030000
> +#                         ^-- v2+4 ^-- v1
> +
> +# EL: Contents of section .data:
> +# EL-NEXT: 30000 00000000 08000300 00000300
> +#                         ^-- v2+4 ^-- v1
> 
> 
> _______________________________________________
> 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