[lld] r347736 - [ELF] Use more specific method to calculate DT_PLTRELSZ

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 28 02:04:55 PST 2018


Author: psmith
Date: Wed Nov 28 02:04:55 2018
New Revision: 347736

URL: http://llvm.org/viewvc/llvm-project?rev=347736&view=rev
Log:
[ELF] Use more specific method to calculate DT_PLTRELSZ

The DT_PLTRELSZ dynamic tag is calculated using the size of the
OutputSection containing the In.RelaPlt InputSection. This will work for the
default no linker script case and the majority of linker scripts.
Unfortunately it doesn't work for some 'almost' sensible linker scripts. It
is permitted by ELF to have a single OutputSection containing both
In.RelaDyn, In.RelaPlt and In.RelaIPlt. It is also permissible for the range
of memory [DT_RELA, DT_RELA + DT_RELASZ) and the range
[DT_JMPREL, DT_JMPREL + DT_JMPRELSZ) to overlap as long as the the latter
range is at the end.

To support this type of linker script use the specific InputSection sizes.

Fixes pr39678

Differential Revision: https://reviews.llvm.org/D54759


Added:
    lld/trunk/test/ELF/aarch64-combined-dynrel-ifunc.s
    lld/trunk/test/ELF/aarch64-combined-dynrel.s
    lld/trunk/test/ELF/arm-combined-dynrel-ifunc.s
    lld/trunk/test/ELF/x86-64-combined-dynrel.s
Modified:
    lld/trunk/ELF/SyntheticSections.cpp

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=347736&r1=347735&r2=347736&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Nov 28 02:04:55 2018
@@ -1255,6 +1255,18 @@ void DynamicSection<ELFT>::addSym(int32_
   Entries.push_back({Tag, [=] { return Sym->getVA(); }});
 }
 
+// A Linker script may assign the RELA relocation sections to the same
+// output section. When this occurs we cannot just use the OutputSection
+// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to
+// overlap with the [DT_RELA, DT_RELA + DT_RELASZ).
+static uint64_t addPltRelSz() {
+  size_t Size = In.RelaPlt->getSize();
+  if (In.RelaIplt->getParent() == In.RelaPlt->getParent() &&
+      In.RelaIplt->Name == In.RelaPlt->Name)
+    Size += In.RelaIplt->getSize();
+  return Size;
+}
+
 // Add remaining entries to complete .dynamic contents.
 template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
   // Set DT_FLAGS and DT_FLAGS_1.
@@ -1335,7 +1347,7 @@ template <class ELFT> void DynamicSectio
   // .rel[a].plt section.
   if (In.RelaPlt->getParent()->Live) {
     addInSec(DT_JMPREL, In.RelaPlt);
-    addSize(DT_PLTRELSZ, In.RelaPlt->getParent());
+    Entries.push_back({DT_PLTRELSZ, addPltRelSz});
     switch (Config->EMachine) {
     case EM_MIPS:
       addInSec(DT_MIPS_PLTGOT, In.GotPlt);

Added: lld/trunk/test/ELF/aarch64-combined-dynrel-ifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-combined-dynrel-ifunc.s?rev=347736&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-combined-dynrel-ifunc.s (added)
+++ lld/trunk/test/ELF/aarch64-combined-dynrel-ifunc.s Wed Nov 28 02:04:55 2018
@@ -0,0 +1,51 @@
+// REQUIRES: AArch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/shared.s -o %t-lib.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
+// RUN: ld.lld %t-lib.o --shared -o %t.so
+// RUN: echo "SECTIONS { \
+// RUN:         .text : { *(.text) } \
+// RUN:         .rela.dyn : { *(.rela.dyn) *(.rela.plt) } \
+// RUN: } " > %t.script
+// RUN: ld.lld %t.o -o %t.axf %t.so --script %t.script
+// RUN: llvm-readobj --section-headers --dynamic-table %t.axf | FileCheck %s
+
+// The linker script above combines the .rela.dyn and .rela.plt into a single
+// table. ELF is clear that the DT_PLTRELSZ should match the subset of
+// relocations that is associated with the PLT. It is less clear about what
+// the value of DT_RELASZ should be. ELF implies that it should be the size
+// of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in
+// glibc permits this as long as .rela.plt comes after .rela.dyn in the
+// combined table. In the ARM case irelative relocations do not count as PLT
+// relocs. In the AArch64 case irelative relocations count as PLT relocs.
+
+.text
+.globl indirect
+.type indirect, at gnu_indirect_function
+indirect:
+ ret
+
+.globl bar // from Inputs/shared.s
+
+.text
+.globl _start
+.type _start, at function
+main:
+ bl indirect
+ bl bar
+ adrp x8, :got:indirect
+ ldr  x8, [x8, :got_lo12:indirect]
+ adrp    x8, :got:bar
+ ldr     x8, [x8, :got_lo12:bar]
+ ret
+
+// CHECK:     Name: .rela.dyn
+// CHECK-NEXT:     Type: SHT_RELA
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address:
+// CHECK-NEXT:     Offset:
+// CHECK-NEXT:     Size: 72
+
+// CHECK:      0x0000000000000008 RELASZ               72
+// CHECK:      0x0000000000000002 PLTRELSZ             48

Added: lld/trunk/test/ELF/aarch64-combined-dynrel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-combined-dynrel.s?rev=347736&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-combined-dynrel.s (added)
+++ lld/trunk/test/ELF/aarch64-combined-dynrel.s Wed Nov 28 02:04:55 2018
@@ -0,0 +1,41 @@
+// REQUIRES: AArch64
+// RUN: llvm-mc --triple=aarch64-linux-gnu -filetype=obj -o %t.o %s
+// RUN: echo "SECTIONS { \
+// RUN:         .text : { *(.text) } \
+// RUN:         .rela.dyn : { *(.rela.dyn) *(.rela.plt) } \
+// RUN: } " > %t.script
+// RUN: ld.lld %t.o -o %t.so --shared --script %t.script
+// RUN: llvm-readobj --section-headers --dynamic-table %t.so | FileCheck %s
+
+// The linker script above combines the .rela.dyn and .rela.plt into a single
+// table. ELF is clear that the DT_PLTRELSZ should match the subset of
+// relocations that is associated with the PLT. It is less clear about what
+// the value of DT_RELASZ should be. ELF implies that it should be the size
+// of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in
+// glibc permits this as long as .rela.plt comes after .rela.dyn in the
+// combined table.
+ .text
+ .globl func
+ .type func, %function
+ .globl foo
+ .type foo, %object
+
+ .globl _start
+ .type _start, %function
+_start:
+ bl func
+ adrp    x8, :got:foo
+ ldr     x8, [x8, :got_lo12:foo]
+ ret
+
+// CHECK:     Name: .rela.dyn
+// CHECK-NEXT:         Type: SHT_RELA
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address:
+// CHECK-NEXT:     Offset:
+// CHECK-NEXT:     Size: 48
+
+// CHECK:  0x0000000000000008 RELASZ               48
+// CHECK:  0x0000000000000002 PLTRELSZ             24

Added: lld/trunk/test/ELF/arm-combined-dynrel-ifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-combined-dynrel-ifunc.s?rev=347736&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-combined-dynrel-ifunc.s (added)
+++ lld/trunk/test/ELF/arm-combined-dynrel-ifunc.s Wed Nov 28 02:04:55 2018
@@ -0,0 +1,49 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj  -arm-add-build-attributes -triple=armv7a-linux-gnueabihf %p/Inputs/arm-shared.s -o %t-lib.o
+// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-linux-gnueabihf %s -o %t.o
+// RUN: ld.lld %t-lib.o --shared -o %t.so
+// RUN: echo "SECTIONS { \
+// RUN:         .text : { *(.text) } \
+// RUN:         .rela.dyn : { *(.rel.dyn) *(.rel.plt) } \
+// RUN: } " > %t.script
+// RUN: ld.lld %t.o -o %t.axf %t.so --script %t.script
+// RUN: llvm-readobj --section-headers --dynamic-table %t.axf | FileCheck %s
+
+// The linker script above combines the .rela.dyn and .rela.plt into a single
+// table. ELF is clear that the DT_PLTRELSZ should match the subset of
+// relocations that is associated with the PLT. It is less clear about what
+// the value of DT_RELASZ should be. ELF implies that it should be the size
+// of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in
+// glibc permits this as long as .rela.plt comes after .rela.dyn in the
+// combined table. In the ARM case irelative relocations do not count as PLT
+// relocs.
+
+.text
+.globl indirect
+.type indirect,%gnu_indirect_function
+indirect:
+ bx lr
+
+.globl bar2 // from Inputs/arm-shared.s
+
+.text
+.globl _start
+.type _start,%function
+main:
+ bl indirect
+ bl bar2
+ .word indirect(got)
+ .word bar2(got)
+ bx lr
+
+// CHECK:     Name: .rela.dyn
+// CHECK-NEXT:     Type: SHT_REL
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address:
+// CHECK-NEXT:     Offset:
+// CHECK-NEXT:     Size: 24
+
+// CHECK: 0x00000012 RELSZ                24 (bytes)
+// CHECK: 0x00000002 PLTRELSZ             8 (bytes)

Added: lld/trunk/test/ELF/x86-64-combined-dynrel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-combined-dynrel.s?rev=347736&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-combined-dynrel.s (added)
+++ lld/trunk/test/ELF/x86-64-combined-dynrel.s Wed Nov 28 02:04:55 2018
@@ -0,0 +1,40 @@
+# REQUIRES: x86
+# RUN: llvm-mc --triple=x86_64-pc-linux -filetype=obj -o %t.o %s
+# RUN: echo "SECTIONS { \
+# RUN:         .text : { *(.text) } \
+# RUN:         .rela.dyn : { *(.rela.dyn) *(.rela.plt) } \
+# RUN: } " > %t.script
+# RUN: ld.lld %t.o -o %t.so --shared --script %t.script
+# RUN: llvm-readobj --section-headers --dynamic-table %t.so | FileCheck %s
+
+// The linker script above combines the .rela.dyn and .rela.plt into a single
+// table. ELF is clear that the DT_PLTRELSZ should match the subset of
+// relocations that is associated with the PLT. It is less clear about what
+// the value of DT_RELASZ should be. ELF implies that it should be the size
+// of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in
+// glibc permits this as long as .rela.plt comes after .rela.dyn in the
+// combined table.
+
+ .text
+ .globl func
+ .type func, %function
+ .globl foo
+ .type foo, %object
+
+ .globl _start
+ .type _start, %function
+_start:
+ call func at plt
+ movq func at GOTPCREL (%rip), %rax
+
+# CHECK:     Name: .rela.dyn
+# CHECK-NEXT:         Type: SHT_RELA
+# CHECK-NEXT:     Flags [
+# CHECK-NEXT:       SHF_ALLOC
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address:
+# CHECK-NEXT:     Offset:
+# CHECK-NEXT:     Size: 48
+
+# CHECK:  0x0000000000000008 RELASZ               48
+# CHECK:  0x0000000000000002 PLTRELSZ             24




More information about the llvm-commits mailing list