[lld] 1edd965 - [ELF] Support input section description .gnu.version* in /DISCARD/

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 26 09:54:28 PST 2019


Author: Fangrui Song
Date: 2019-12-26T09:54:22-08:00
New Revision: 1edd9651307112447f83a0cd402ee23125f0fdb3

URL: https://github.com/llvm/llvm-project/commit/1edd9651307112447f83a0cd402ee23125f0fdb3
DIFF: https://github.com/llvm/llvm-project/commit/1edd9651307112447f83a0cd402ee23125f0fdb3.diff

LOG: [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

Added: 
    lld/test/ELF/linkerscript/discard-gnu-version.s

Modified: 
    lld/ELF/SyntheticSections.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 347ffc3d5070..2c66f54a6e15 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 000000000000..7a40236feaaa
--- /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 at plt


        


More information about the llvm-commits mailing list