[ELF][MIPS] Create PLT entry specific for MIPS ABI version R6
authorSimon Atanasyan <simon@atanasyan.com>
Wed, 20 Jul 2016 20:15:33 +0000 (20:15 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Wed, 20 Jul 2016 20:15:33 +0000 (20:15 +0000)
llvm-svn: 276173

lld/ELF/Target.cpp
lld/test/ELF/mips-plt-r6.s [new file with mode: 0644]

index 4bdde13..1d75bf3 100644 (file)
@@ -1957,6 +1957,12 @@ static void writeMipsLo16(uint8_t *Loc, uint64_t V) {
   write32<E>(Loc, (Instr & 0xffff0000) | (V & 0xffff));
 }
 
+template <class ELFT> static bool isMipsR6() {
+  const auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
+  uint32_t Arch = FirstObj.getObj().getHeader()->e_flags & EF_MIPS_ARCH;
+  return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6;
+}
+
 template <class ELFT>
 void MipsTargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const {
   const endianness E = ELFT::TargetEndianness;
@@ -1981,7 +1987,8 @@ void MipsTargetInfo<ELFT>::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
   const endianness E = ELFT::TargetEndianness;
   write32<E>(Buf, 0x3c0f0000);      // lui   $15, %hi(.got.plt entry)
   write32<E>(Buf + 4, 0x8df90000);  // l[wd] $25, %lo(.got.plt entry)($15)
-  write32<E>(Buf + 8, 0x03200008);  // jr    $25
+                                    // jr    $25
+  write32<E>(Buf + 8, isMipsR6<ELFT>() ? 0x03200009 : 0x03200008);
   write32<E>(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry)
   writeMipsHi16<E>(Buf, GotEntryAddr);
   writeMipsLo16<E>(Buf + 4, GotEntryAddr);
diff --git a/lld/test/ELF/mips-plt-r6.s b/lld/test/ELF/mips-plt-r6.s
new file mode 100644 (file)
index 0000000..8685d61
--- /dev/null
@@ -0,0 +1,38 @@
+# Check PLT entries generation in case of R6 ABI version.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:         -mcpu=mips32r6 %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:         -mcpu=mips32r6 %S/Inputs/mips-dynamic.s -o %t2.o
+# RUN: ld.lld %t2.o -shared -o %t.so
+# RUN: ld.lld %t1.o %t.so -o %t.exe
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK:      Disassembly of section .text:
+# CHECK-NEXT: __start:
+# CHECK-NEXT:   20000:       0c 00 80 0c     jal     131120
+#                                                    ^-- 0x20030 gotplt[foo0]
+# CHECK-NEXT:   20004:       00 00 00 00     nop
+#
+# CHECK-NEXT: Disassembly of section .plt:
+# CHECK-NEXT: .plt:
+# CHECK-NEXT:   20010:       3c 1c 00 04     aui     $zero, $gp, 4
+# CHECK-NEXT:   20014:       8f 99 00 04     lw      $25, 4($gp)
+# CHECK-NEXT:   20018:       27 9c 00 04     addiu   $gp, $gp, 4
+# CHECK-NEXT:   2001c:       03 1c c0 23     subu    $24, $24, $gp
+# CHECK-NEXT:   20020:       03 e0 78 25     move    $15, $ra
+# CHECK-NEXT:   20024:       00 18 c0 82     srl     $24, $24, 2
+# CHECK-NEXT:   20028:       03 20 f8 09     jalr    $25
+# CHECK-NEXT:   2002c:       27 18 ff fe     addiu   $24, $24, -2
+
+# CHECK-NEXT:   20030:       3c 0f 00 04     aui     $zero, $15, 4
+# CHECK-NEXT:   20034:       8d f9 00 0c     lw      $25, 12($15)
+# CHECK-NEXT:   20038:       03 20 00 09     jr      $25
+# CHECK-NEXT:   2003c:       25 f8 00 0c     addiu   $24, $15, 12
+
+  .text
+  .global __start
+__start:
+  jal foo0        # R_MIPS_26 against 'foo0' from DSO