From 373a533a0a65cc64f923297111b06a83da1d606d Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Mon, 25 Jul 2016 00:25:18 +0000 Subject: [PATCH] [ELF] Fix the semantic of PROVIDE in linker scripts. PROVIDE request us to define a symbol only if it is referenced and is not defined by any object included in the link. We created the symbol in the symbol table no matter what. Differential Revision: https://reviews.llvm.org/D22739 llvm-svn: 276592 --- lld/ELF/LinkerScript.cpp | 4 +++- .../linkerscript-symbolreferenced.s | 22 +++++++++++++++++++ .../ELF/linkerscript/linkerscript-symbols.s | 8 +++---- 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 lld/test/ELF/linkerscript/linkerscript-symbolreferenced.s diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index aacb5d8d7fa3e..efb3c4afc789b 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -350,7 +350,9 @@ template void LinkerScript::addScriptedSymbols() { continue; SymbolBody *B = Symtab::X->find(Cmd->Name); - if (!B || B->isUndefined()) + // The semantic of PROVIDE is that of introducing a symbol only if + // it's not defined and there's at least a reference to it. + if ((!B && !Cmd->Provide) || (B && B->isUndefined())) Symtab::X->addAbsolute(Cmd->Name, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT); else diff --git a/lld/test/ELF/linkerscript/linkerscript-symbolreferenced.s b/lld/test/ELF/linkerscript/linkerscript-symbolreferenced.s new file mode 100644 index 0000000000000..c2925b179ad50 --- /dev/null +++ b/lld/test/ELF/linkerscript/linkerscript-symbolreferenced.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Provide new symbol. The value should be 1, like set in PROVIDE() +# RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE1 %s +# PROVIDE1: 0000000000000001 *ABS* 00000000 newsym + +# Provide new symbol (hidden). The value should be 1 +# RUN: echo "SECTIONS { PROVIDE_HIDDEN(newsym = 1);}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN1 %s +# HIDDEN1: 0000000000000001 *ABS* 00000000 .hidden newsym + +.global _start +_start: + nop + +.globl patatino +patatino: + movl newsym, %eax diff --git a/lld/test/ELF/linkerscript/linkerscript-symbols.s b/lld/test/ELF/linkerscript/linkerscript-symbols.s index 5e2fc2d183673..036ce9bb0514b 100644 --- a/lld/test/ELF/linkerscript/linkerscript-symbols.s +++ b/lld/test/ELF/linkerscript/linkerscript-symbols.s @@ -9,17 +9,17 @@ # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s # SIMPLE: 0000000000000121 *ABS* 00000000 text_end -# Provide new symbol. The value should be 1, like set in PROVIDE() +# The symbol is not referenced. Don't provide it. # RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE1 %s -# PROVIDE1: 0000000000000001 *ABS* 00000000 newsym +# PROVIDE1-NOT: 0000000000000001 *ABS* 00000000 newsym -# Provide new symbol (hidden). The value should be 1 +# The symbol is not referenced. Don't provide it. # RUN: echo "SECTIONS { PROVIDE_HIDDEN(newsym = 1);}" > %t.script # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN1 %s -# HIDDEN1: 0000000000000001 *ABS* 00000000 .hidden newsym +# HIDDEN1-NOT: 0000000000000001 *ABS* 00000000 .hidden newsym # Provide existing symbol. The value should be 0, even though we # have value of 1 in PROVIDE()