From b427d4eced315ffa2b6f5bd0f7ee24c9c869126a Mon Sep 17 00:00:00 2001 From: James Henderson Date: Tue, 3 Jul 2018 09:23:25 +0000 Subject: [PATCH] [ELF] Don't create empty output section for unreferenced PROVIDEs LLD removes empty output sections otherwise specified in the linker script. Prior to this change however, if section descriptions included ANY kind of symbol assignment, then the consequent output section would not be removed, even if the assignment was marked with PROVIDE and not actually triggered (i.e. the symbol was never referenced). This change modifies the isDiscarable function to ignore such directives when determining whether a section should be discarded, in keeping with bfd's behaviour. Symbol assignments that do result in a symbol definition will continue to result in a kept section (this is not actually the same as bfd's behaviour, but it is simpler, and probably makes more sense). Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D48771 llvm-svn: 336184 --- lld/ELF/LinkerScript.cpp | 9 ++++++- lld/test/ELF/linkerscript/provide-empty-section.s | 30 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/linkerscript/provide-empty-section.s diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 9cc836b..3e3fe31 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -834,9 +834,16 @@ static bool isDiscardable(OutputSection &Sec) { if (Sec.ExpressionsUseSymbols) return false; - for (BaseCommand *Base : Sec.SectionCommands) + for (BaseCommand *Base : Sec.SectionCommands) { + if (auto Cmd = dyn_cast(Base)) + // Don't create empty output sections just for unreferenced PROVIDE + // symbols. + if (Cmd->Name != "." && !Cmd->Sym) + continue; + if (!isa(*Base)) return false; + } return true; } diff --git a/lld/test/ELF/linkerscript/provide-empty-section.s b/lld/test/ELF/linkerscript/provide-empty-section.s new file mode 100644 index 0000000..56cb6ac --- /dev/null +++ b/lld/test/ELF/linkerscript/provide-empty-section.s @@ -0,0 +1,30 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tundefined.o +# RUN: echo "foo=42" | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %tdefined.o +# RUN: echo "call foo" | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %treference.o + +# RUN: echo "SECTIONS { .bar : { PROVIDE(foo = .); } }" > %t.script + +# Case 1: Provided symbol is undefined and not referenced - empty section should be removed. +# RUN: ld.lld %tundefined.o -T %t.script -o %t1.elf +# RUN: llvm-readobj -sections %t1.elf | FileCheck %s --check-prefix=NOSECTION + +# Case 2: Provided symbol is undefined and referenced - empty section should not be removed. +# RUN: ld.lld %tundefined.o %treference.o -T %t.script -o %t2.elf +# RUN: llvm-readobj -sections %t2.elf | FileCheck %s --check-prefix=SECTION + +# Case 3: Provided symbol is defined and not referenced - empty section should be removed. +# RUN: ld.lld %tdefined.o -T %t.script -o %t3.elf +# RUN: llvm-readobj -sections %t3.elf | FileCheck %s --check-prefix=NOSECTION + +# Case 4: Provided symbol is defined and referenced - empty section should not be removed. +# RUN: ld.lld %tdefined.o %treference.o -T %t.script -o %t4.elf +# RUN: llvm-readobj -sections %t4.elf | FileCheck %s --check-prefix=SECTION + +.global _start +_start: + ret + +# SECTION: .bar +# NOSECTION-NOT: .bar -- 2.7.4