diff options
| author | Fangrui Song <maskray@google.com> | 2019-12-22 14:50:14 -0800 |
|---|---|---|
| committer | Fangrui Song <maskray@google.com> | 2019-12-26 09:54:22 -0800 |
| commit | 1edd9651307112447f83a0cd402ee23125f0fdb3 (patch) | |
| tree | 531aa8f7ca5d105140deb7490740141f6e2814e4 | |
| parent | cb5eb13eafdcf2d6ad8dc3a2c7b25eea3948839d (diff) | |
| download | bcm5719-llvm-1edd9651307112447f83a0cd402ee23125f0fdb3.tar.gz bcm5719-llvm-1edd9651307112447f83a0cd402ee23125f0fdb3.zip | |
[ELF] Support input section description .gnu.version* in /DISCARD/
Linux powerpc discards `*(.gnu.version*)` (arch/powerpc/kernel/vmlinux.lds.S)
to suppress --orphan-handling=warn warnings in the -pie output `.tmp_vmlinux1`
The support is simple. Just add isLive() to:
1) Fix an assertion in SectionBase::getPartition() called by VersionTableSection::isNeeded().
2) Suppress DT_VERSYM, DT_VERDEF, DT_VERNEED and DT_VERNEEDNUM, if the relevant section is discarded.
Reviewed By: grimar
Differential Revision: https://reviews.llvm.org/D71819
| -rw-r--r-- | lld/ELF/SyntheticSections.cpp | 12 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/discard-gnu-version.s | 47 |
2 files changed, 53 insertions, 6 deletions
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 347ffc3d507..2c66f54a6e1 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1437,14 +1437,13 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { addSym(DT_FINI, b); } - bool hasVerNeed = SharedFile::vernauxNum != 0; - if (hasVerNeed || part.verDef) + if (part.verSym && part.verSym->isNeeded()) addInSec(DT_VERSYM, part.verSym); - if (part.verDef) { + if (part.verDef && part.verDef->isLive()) { addInSec(DT_VERDEF, part.verDef); addInt(DT_VERDEFNUM, getVerDefNum()); } - if (hasVerNeed) { + if (part.verNeed && part.verNeed->isNeeded()) { addInSec(DT_VERNEED, part.verNeed); unsigned needNum = 0; for (SharedFile *f : sharedFiles) @@ -2963,7 +2962,8 @@ void VersionTableSection::writeTo(uint8_t *buf) { } bool VersionTableSection::isNeeded() const { - return getPartition().verDef || getPartition().verNeed->isNeeded(); + return isLive() && + (getPartition().verDef || getPartition().verNeed->isNeeded()); } void addVerneed(Symbol *ss) { @@ -3051,7 +3051,7 @@ template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const { } template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const { - return SharedFile::vernauxNum != 0; + return isLive() && SharedFile::vernauxNum != 0; } void MergeSyntheticSection::addSection(MergeInputSection *ms) { diff --git a/lld/test/ELF/linkerscript/discard-gnu-version.s b/lld/test/ELF/linkerscript/discard-gnu-version.s new file mode 100644 index 00000000000..7a40236feaa --- /dev/null +++ b/lld/test/ELF/linkerscript/discard-gnu-version.s @@ -0,0 +1,47 @@ +# REQUIRES: x86 +# RUN: echo '.globl f; f:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o +# RUN: echo 'v1 { f; };' > %t1.ver +# RUN: ld.lld -shared --version-script %t1.ver %t1.o -o %t1.so + +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: echo 'v1 { foo; };' > %t.ver +# RUN: ld.lld -shared --version-script %t.ver %t.o %t1.so -o %t.so +# RUN: llvm-readelf -S -d %t.so | FileCheck --check-prefixes=SYM,DEF,NEED %s + +# SYM: .gnu.version +# DEF: .gnu.version_d +# NEED: .gnu.version_r + +# SYM: (VERSYM) +# DEF: (VERDEF) +# DEF: (VERDEFNUM) +# NEED: (VERNEED) +# NEED: (VERNEEDNUM) + +## Discard all of .gnu.version* +# RUN: echo 'SECTIONS { /DISCARD/ : { *(.gnu.version*) } }' > %t.script +# RUN: ld.lld -shared --version-script %t.ver -T %t.script %t.o %t1.so -o %t.so +# RUN: llvm-readelf -S -d %t.so | FileCheck /dev/null \ +# RUN: --implicit-check-not='(VER' --implicit-check-not=.gnu.version + +## Discard .gnu.version +# RUN: echo 'SECTIONS { /DISCARD/ : { *(.gnu.version) } }' > %t.noversym.script +# RUN: ld.lld -shared --version-script %t.ver -T %t.noversym.script %t.o %t1.so -o %t.noversym.so +# RUN: llvm-readelf -S -d %t.noversym.so | FileCheck --check-prefixes=DEF,NEED %s \ +# RUN: --implicit-check-not='(VER' --implicit-check-not=.gnu.version + +## Discard .gnu.version_d +# RUN: echo 'SECTIONS { /DISCARD/ : { *(.gnu.version_d) } }' > %t.noverdef.script +# RUN: ld.lld -shared --version-script %t.ver -T %t.noverdef.script %t.o %t1.so -o %t.noverdef.so +# RUN: llvm-readelf -S -d %t.noverdef.so | FileCheck --check-prefixes=SYM,NEED %s \ +# RUN: --implicit-check-not='(VER' --implicit-check-not=.gnu.version + +## Discard .gnu.version_r +# RUN: echo 'SECTIONS { /DISCARD/ : { *(.gnu.version_r) } }' > %t.noverneed.script +# RUN: ld.lld -shared --version-script %t.ver -T %t.noverneed.script %t.o %t1.so -o %t.noverneed.so +# RUN: llvm-readelf -S -d %t.noverneed.so | FileCheck --check-prefixes=SYM,DEF %s \ +# RUN: --implicit-check-not='(VER' --implicit-check-not=.gnu.version + +.globl foo +foo: + call f@plt |

