Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1339,7 +1339,7 @@ // 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) { Index: test/ELF/empty-relaplt-dyntags.s =================================================================== --- /dev/null +++ test/ELF/empty-relaplt-dyntags.s @@ -0,0 +1,24 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "PHDRS { \ +# RUN: all PT_LOAD; \ +# RUN: dyn PT_DYNAMIC; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .rela.plt : { *(.rela.plt) }: all \ +# RUN: .dynamic : { *(.dynamic) }: all : dyn \ +# RUN: }" > %t.script + +# RUN: ld.lld -shared %t.o -T %t.script -o %t +# RUN: llvm-readobj --dynamic-table %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 memory it considers reserved. In fact, as .got.plt is also +## empty, that memory might be allocated for something else. + +# CHECK: DynamicSection [ +# CHECK-NOT: JMPREL +# CHECK-NOT: PLTGOT