[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 &params,
+                          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 &params,
+                       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