[lld] r231642 - [Mips] Implement R_MIPS_64 relocation handling
Simon Atanasyan
simon at atanasyan.com
Mon Mar 9 03:53:42 PDT 2015
Author: atanasyan
Date: Mon Mar 9 05:53:41 2015
New Revision: 231642
URL: http://llvm.org/viewvc/llvm-project?rev=231642&view=rev
Log:
[Mips] Implement R_MIPS_64 relocation handling
Added:
lld/trunk/test/elf/Mips/dt-textrel-64.test
lld/trunk/test/elf/Mips/rel-64.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp?rev=231642&r1=231641&r2=231642&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Mon Mar 9 05:53:41 2015
@@ -25,6 +25,7 @@ enum class CrossJumpMode {
};
struct MipsRelocationParams {
+ uint8_t _size; // Relocations's size in bytes
uint64_t _mask; // Read/write mask of relocation
uint8_t _shift; // Relocation's addendum left shift size
bool _shuffle; // Relocation's addendum/result needs to be shuffled
@@ -34,15 +35,17 @@ struct MipsRelocationParams {
static MipsRelocationParams getRelocationParams(uint32_t rType) {
switch (rType) {
case llvm::ELF::R_MIPS_NONE:
- return {0x0, 0, false};
+ return {4, 0x0, 0, false};
+ case llvm::ELF::R_MIPS_64:
+ return {8, 0xffffffffffffffffull, 0, false};
case llvm::ELF::R_MIPS_32:
case llvm::ELF::R_MIPS_GPREL32:
case llvm::ELF::R_MIPS_PC32:
case LLD_R_MIPS_32_HI16:
- return {0xffffffff, 0, false};
+ return {4, 0xffffffff, 0, false};
case llvm::ELF::R_MIPS_26:
case LLD_R_MIPS_GLOBAL_26:
- return {0x3ffffff, 2, false};
+ return {4, 0x3ffffff, 2, false};
case llvm::ELF::R_MIPS_HI16:
case llvm::ELF::R_MIPS_LO16:
case llvm::ELF::R_MIPS_GPREL16:
@@ -53,41 +56,41 @@ static MipsRelocationParams getRelocatio
case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
case LLD_R_MIPS_HI16:
case LLD_R_MIPS_LO16:
- return {0xffff, 0, false};
+ return {4, 0xffff, 0, false};
case llvm::ELF::R_MICROMIPS_TLS_DTPREL_HI16:
case llvm::ELF::R_MICROMIPS_TLS_DTPREL_LO16:
case llvm::ELF::R_MICROMIPS_TLS_TPREL_HI16:
case llvm::ELF::R_MICROMIPS_TLS_TPREL_LO16:
- return {0xffff, 0, true};
+ return {4, 0xffff, 0, true};
case llvm::ELF::R_MICROMIPS_26_S1:
case LLD_R_MICROMIPS_GLOBAL_26_S1:
- return {0x3ffffff, 1, true};
+ return {4, 0x3ffffff, 1, true};
case llvm::ELF::R_MICROMIPS_HI16:
case llvm::ELF::R_MICROMIPS_LO16:
case llvm::ELF::R_MICROMIPS_GOT16:
- return {0xffff, 0, true};
+ return {4, 0xffff, 0, true};
case llvm::ELF::R_MICROMIPS_PC16_S1:
- return {0xffff, 1, true};
+ return {4, 0xffff, 1, true};
case llvm::ELF::R_MICROMIPS_PC7_S1:
- return {0x7f, 1, false};
+ return {4, 0x7f, 1, false};
case llvm::ELF::R_MICROMIPS_PC10_S1:
- return {0x3ff, 1, false};
+ return {4, 0x3ff, 1, false};
case llvm::ELF::R_MICROMIPS_PC23_S2:
- return {0x7fffff, 2, true};
+ return {4, 0x7fffff, 2, true};
case llvm::ELF::R_MIPS_CALL16:
case llvm::ELF::R_MIPS_TLS_GD:
case llvm::ELF::R_MIPS_TLS_LDM:
case llvm::ELF::R_MIPS_TLS_GOTTPREL:
- return {0xffff, 0, false};
+ return {4, 0xffff, 0, false};
case llvm::ELF::R_MICROMIPS_CALL16:
case llvm::ELF::R_MICROMIPS_TLS_GD:
case llvm::ELF::R_MICROMIPS_TLS_LDM:
case llvm::ELF::R_MICROMIPS_TLS_GOTTPREL:
- return {0xffff, 0, true};
+ return {4, 0xffff, 0, true};
case R_MIPS_JALR:
- return {0x0, 0, false};
+ return {4, 0x0, 0, false};
case R_MICROMIPS_JALR:
- return {0x0, 0, true};
+ return {4, 0x0, 0, true};
case R_MIPS_REL32:
case R_MIPS_JUMP_SLOT:
case R_MIPS_COPY:
@@ -95,11 +98,11 @@ static MipsRelocationParams getRelocatio
case R_MIPS_TLS_DTPREL32:
case R_MIPS_TLS_TPREL32:
// Ignore runtime relocations.
- return {0x0, 0, false};
+ return {4, 0x0, 0, false};
case LLD_R_MIPS_GLOBAL_GOT:
case LLD_R_MIPS_STO_PLT:
// Do nothing.
- return {0x0, 0, false};
+ return {4, 0x0, 0, false};
default:
llvm_unreachable("Unknown relocation");
}
@@ -115,6 +118,10 @@ template <size_t BITS, class T> inline T
/// local/external: word32 S + A (truncate)
static uint32_t reloc32(uint64_t S, int64_t A) { return S + A; }
+/// \brief R_MIPS_64
+/// local/external: word64 S + A (truncate)
+static uint64_t reloc64(uint64_t S, int64_t A) { return S + A; }
+
/// \brief R_MIPS_PC32
/// local/external: word32 S + A i- P (truncate)
static uint32_t relocpc32(uint64_t P, uint64_t S, int64_t A) {
@@ -219,7 +226,7 @@ static uint32_t reloc32hi16(uint64_t S,
return (S + A + 0x8000) & 0xffff0000;
}
-static std::error_code adjustJumpOpCode(uint32_t &ins, uint64_t tgt,
+static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt,
CrossJumpMode mode) {
if (mode == CrossJumpMode::None)
return std::error_code();
@@ -273,7 +280,7 @@ static uint32_t microShuffle(uint32_t in
return ((ins & 0xffff) << 16) | ((ins & 0xffff0000) >> 16);
}
-static ErrorOr<uint32_t> calculateRelocation(const Reference &ref,
+static ErrorOr<uint64_t> calculateRelocation(const Reference &ref,
uint64_t tgtAddr, uint64_t relAddr,
uint64_t gpAddr, bool isGP) {
bool isCrossJump = getCrossJumpMode(ref) != CrossJumpMode::None;
@@ -282,6 +289,8 @@ static ErrorOr<uint32_t> calculateReloca
return 0;
case R_MIPS_32:
return reloc32(tgtAddr, ref.addend());
+ case R_MIPS_64:
+ return reloc64(tgtAddr, ref.addend());
case R_MIPS_26:
return reloc26loc(relAddr, tgtAddr, ref.addend(), 2);
case R_MICROMIPS_26_S1:
@@ -365,6 +374,42 @@ static ErrorOr<uint32_t> calculateReloca
}
template <class ELFT>
+static uint64_t relocRead(const MipsRelocationParams ¶ms,
+ const uint8_t *loc) {
+ uint64_t data;
+ switch (params._size) {
+ case 4:
+ data = endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(loc);
+ break;
+ case 8:
+ data = endian::read<uint64_t, ELFT::TargetEndianness, unaligned>(loc);
+ break;
+ default:
+ llvm_unreachable("Unexpected size");
+ }
+ if (params._shuffle)
+ data = microShuffle(data);
+ return data;
+}
+
+template <class ELFT>
+static void relocWrite(uint64_t data, const MipsRelocationParams ¶ms,
+ uint8_t *loc) {
+ if (params._shuffle)
+ data = microShuffle(data);
+ switch (params._size) {
+ case 4:
+ endian::write<uint32_t, ELFT::TargetEndianness, unaligned>(loc, data);
+ break;
+ case 8:
+ endian::write<uint64_t, ELFT::TargetEndianness, unaligned>(loc, data);
+ break;
+ default:
+ llvm_unreachable("Unexpected size");
+ }
+}
+
+template <class ELFT>
std::error_code MipsRelocationHandler<ELFT>::applyRelocation(
ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
const Reference &ref) const {
@@ -394,22 +439,15 @@ std::error_code MipsRelocationHandler<EL
if (auto ec = res.getError())
return ec;
- uint32_t ins =
- endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(location);
-
auto params = getRelocationParams(ref.kindValue());
- if (params._shuffle)
- ins = microShuffle(ins);
+ uint64_t ins = relocRead<ELFT>(params, location);
if (auto ec = adjustJumpOpCode(ins, targetVAddress, getCrossJumpMode(ref)))
return ec;
ins = (ins & ~params._mask) | (*res & params._mask);
+ relocWrite<ELFT>(ins, params, location);
- if (params._shuffle)
- ins = microShuffle(ins);
-
- endian::write<uint32_t, ELFT::TargetEndianness, unaligned>(location, ins);
return std::error_code();
}
@@ -417,10 +455,8 @@ template <class ELFT>
Reference::Addend
MipsRelocationHandler<ELFT>::readAddend(Reference::KindValue kind,
const uint8_t *content) {
- auto ins = endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(content);
auto params = getRelocationParams(kind);
- if (params._shuffle)
- ins = microShuffle(ins);
+ uint64_t ins = relocRead<ELFT>(params, content);
return (ins & params._mask) << params._shift;
}
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp?rev=231642&r1=231641&r2=231642&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Mon Mar 9 05:53:41 2015
@@ -587,7 +587,7 @@ bool RelocationPass<ELFT>::mightBeDynami
refKind == R_MICROMIPS_CALL16 || refKind == R_MICROMIPS_GOT16)
return true;
- if (refKind != R_MIPS_32)
+ if (refKind != R_MIPS_32 && refKind != R_MIPS_64)
return false;
if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
return false;
Added: lld/trunk/test/elf/Mips/dt-textrel-64.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/dt-textrel-64.test?rev=231642&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/dt-textrel-64.test (added)
+++ lld/trunk/test/elf/Mips/dt-textrel-64.test Mon Mar 9 05:53:41 2015
@@ -0,0 +1,74 @@
+# Check that if a dynamic relocation R_MIPS_64 modify a read-only section,
+# .dynamic section contains the DT_TEXTREL tag.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
+# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t-so.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
+# RUN: lld -flavor gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so
+# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck %s
+
+# CHECK: 0x{{[0-9A-F]+}} TEXTREL
+
+# so.o
+---
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
+
+Sections:
+- Name: .text
+ Type: SHT_PROGBITS
+ Size: 0x4
+ AddressAlign: 16
+ Flags: [SHF_EXECINSTR, SHF_ALLOC]
+
+Symbols:
+ Global:
+ - Name: T1
+ Section: .text
+ Type: STT_FUNC
+ Value: 0x0
+ Size: 0x08
+
+# o.o
+---
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x4
+ Size: 0x8
+
+ - Name: .rel.text
+ Type: SHT_RELA
+ Link: .symtab
+ Info: .text
+ AddressAlign: 0x04
+ Relocations:
+ - Offset: 0
+ Symbol: T1
+ Type: R_MIPS_64
+
+Symbols:
+ Local:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+
+ Global:
+ - Name: T0
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x8
+ - Name: T1
+...
Added: lld/trunk/test/elf/Mips/rel-64.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/rel-64.test?rev=231642&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/rel-64.test (added)
+++ lld/trunk/test/elf/Mips/rel-64.test Mon Mar 9 05:53:41 2015
@@ -0,0 +1,61 @@
+# Check handling of R_MIPS_64 relocation.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mips64el -o %t.exe %t.o
+# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
+
+# CHECK: Contents of section .data:
+# CHECK-NEXT: 120002000 d1010020 01000000 d0010020 01000100 ... ....... ....
+# ^^ __start + 1 = 0x1200001d1
+# ^^ __start + 0x1000000000000
+# = 0x10001200001d0
+# CHECK: SYMBOL TABLE:
+# CHECK: 00000001200001d0 g .rodata 00000008 __start
+
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
+
+Sections:
+- Name: .text
+ Type: SHT_PROGBITS
+ Size: 0x08
+ AddressAlign: 16
+ Flags: [SHF_ALLOC]
+- Name: .data
+ Type: SHT_PROGBITS
+ Size: 0x10
+ AddressAlign: 16
+ Flags: [SHF_ALLOC, SHF_WRITE]
+
+- Name: .rela.data
+ Type: SHT_RELA
+ Info: .data
+ AddressAlign: 4
+ Relocations:
+ - Offset: 0x0
+ Symbol: __start
+ Type: R_MIPS_64
+ Addend: 1
+ - Offset: 0x8
+ Symbol: __start
+ Type: R_MIPS_64
+ Addend: 0x1000000000000
+
+Symbols:
+ Global:
+ - Name: __start
+ Section: .text
+ Value: 0x0
+ Size: 8
+ - Name: data1
+ Section: .data
+ Value: 0x0
+ Size: 8
+ - Name: data2
+ Section: .data
+ Value: 0x8
+ Size: 8
More information about the llvm-commits
mailing list