[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