[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