[ELF] Do not produce DT_JMPREL and DT_PLTGOT if .rela.plt is empty.

If .rela.plt is mentioned in a linker script, it might be preserved
even if it is empty. In that case, LLD created DT_JMPREL and DT_PLTGOT
dynamic tags. When the tags exist, a dynamic loader writes values into
reserved slots in .got.plt to support lazy symbol resolution.
The problem is that, in fact, the linker has not reserved that space,
and the writing may occur into the memory allocated for something else.

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

llvm-svn: 364639
This commit is contained in:
Igor Kudrin 2019-06-28 10:14:14 +00:00
parent 02e743586e
commit fd0ad4b24d
2 changed files with 45 additions and 1 deletions

View File

@ -1339,7 +1339,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
// as RelaIplt have. And we still want to emit proper dynamic tags for that
// case, so here we always use RelaPlt as marker for the begining of
// .rel[a].plt section.
if (IsMain && In.RelaPlt->getParent()->isLive()) {
if (IsMain && (In.RelaPlt->isNeeded() || In.RelaIplt->isNeeded())) {
addInSec(DT_JMPREL, In.RelaPlt);
Entries.push_back({DT_PLTRELSZ, addPltRelSz});
switch (Config->EMachine) {

View File

@ -0,0 +1,44 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
# RUN: ld.lld -shared %t.o -T %s -o %t
# RUN: llvm-readobj --dynamic-table --sections %t | FileCheck %s
## In spite of .rela.plt is empty, it might have been preserved because it is
## mentioned in the linker script. However, even in that case, we should not
## produce DT_JMPREL and DT_PLTGOT tags because this can cause a dynamic loader
## to write into slots in .got.plt it considers reserved to support lazy symbol
## resolution. In fact, as .got.plt is also empty, that memory might be
## allocated for something else.
# CHECK: Sections [
# CHECK: Name: .rela.plt
# CHECK-NEXT: Type: SHT_RELA
# CHECK-NEXT: Flags [
# CHECK-NEXT: SHF_ALLOC
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 0
# CHECK: Name: .got.plt
# CHECK-NEXT: Type: SHT_PROGBITS
# CHECK-NEXT: Flags [
# CHECK-NEXT: SHF_ALLOC
# CHECK-NEXT: SHF_WRITE
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 0
# CHECK: DynamicSection [
# CHECK-NOT: JMPREL
# CHECK-NOT: PLTGOT
PHDRS {
all PT_LOAD;
dyn PT_DYNAMIC;
}
SECTIONS {
.rela.plt : { *(.rela.plt) }: all
.dynamic : { *(.dynamic) }: all : dyn
.got.plt : {*(.got.plt)}: all
}