[lld] r276398 - [ELF] Support PROVIDE and PROVIDE_HIDDEN inside SECTIONS
Eugene Leviant via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 22 00:38:41 PDT 2016
Author: evgeny777
Date: Fri Jul 22 02:38:40 2016
New Revision: 276398
URL: http://llvm.org/viewvc/llvm-project?rev=276398&view=rev
Log:
[ELF] Support PROVIDE and PROVIDE_HIDDEN inside SECTIONS
Modified:
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/LinkerScript.h
lld/trunk/test/ELF/linkerscript-locationcounter.s
lld/trunk/test/ELF/linkerscript-symbols.s
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=276398&r1=276397&r2=276398&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Jul 22 02:38:40 2016
@@ -338,7 +338,7 @@ void LinkerScript<ELFT>::dispatchAssignm
uint64_t Val = evalExpr(Cmd->Expr, Dot);
if (Cmd->Name == ".") {
Dot = Val;
- } else {
+ } else if (!Cmd->Ignore) {
auto *D = cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd->Name));
D->Value = Val;
}
@@ -528,10 +528,19 @@ int LinkerScript<ELFT>::compareSections(
}
template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() {
- for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands)
- if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get()))
- if (Cmd->Name != "." && Symtab<ELFT>::X->find(Cmd->Name) == nullptr)
- Symtab<ELFT>::X->addAbsolute(Cmd->Name, STV_DEFAULT);
+ for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
+ auto *Cmd = dyn_cast<SymbolAssignment>(Base.get());
+ if (!Cmd || Cmd->Name == ".")
+ continue;
+
+ if (Symtab<ELFT>::X->find(Cmd->Name) == nullptr)
+ Symtab<ELFT>::X->addAbsolute(Cmd->Name,
+ Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
+ else
+ // Symbol already exists in symbol table. If it is provided
+ // then we can't override its value.
+ Cmd->Ignore = Cmd->Provide;
+ }
}
template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() {
@@ -592,7 +601,8 @@ private:
void readOutputSectionDescription(StringRef OutSec);
std::vector<StringRef> readOutputSectionPhdrs();
unsigned readPhdrType();
- void readSymbolAssignment(StringRef Name);
+ void readProvide(bool Hidden);
+ SymbolAssignment *readSymbolAssignment(StringRef Name);
std::vector<StringRef> readSectionsCommandExpr();
const static StringMap<Handler> Cmd;
@@ -789,7 +799,11 @@ void ScriptParser::readSections() {
continue;
}
next();
- if (peek() == "=")
+ if (Tok == "PROVIDE")
+ readProvide(false);
+ else if (Tok == "PROVIDE_HIDDEN")
+ readProvide(true);
+ else if (peek() == "=")
readSymbolAssignment(Tok);
else
readOutputSectionDescription(Tok);
@@ -855,19 +869,42 @@ void ScriptParser::readOutputSectionDesc
}
}
-void ScriptParser::readSymbolAssignment(StringRef Name) {
+void ScriptParser::readProvide(bool Hidden) {
+ expect("(");
+ if (SymbolAssignment *Assignment = readSymbolAssignment(next())) {
+ Assignment->Provide = true;
+ Assignment->Hidden = Hidden;
+ }
+ expect(")");
+ expect(";");
+}
+
+SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) {
expect("=");
std::vector<StringRef> Expr = readSectionsCommandExpr();
- if (Expr.empty())
+ if (Expr.empty()) {
error("error in symbol assignment expression");
- else
+ } else {
Opt.Commands.push_back(llvm::make_unique<SymbolAssignment>(Name, Expr));
+ return static_cast<SymbolAssignment *>(Opt.Commands.back().get());
+ }
+ return nullptr;
}
+// This function reads balanced expression until semicolon is seen.
std::vector<StringRef> ScriptParser::readSectionsCommandExpr() {
+ int Braces = 0;
std::vector<StringRef> Expr;
while (!Error) {
- StringRef Tok = next();
+ StringRef Tok = peek();
+
+ if (Tok == "(")
+ Braces++;
+ else if (Tok == ")")
+ if (--Braces < 0)
+ break;
+
+ next();
if (Tok == ";")
break;
Expr.push_back(Tok);
Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=276398&r1=276397&r2=276398&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Fri Jul 22 02:38:40 2016
@@ -51,6 +51,10 @@ struct SymbolAssignment : BaseCommand {
static bool classof(const BaseCommand *C);
StringRef Name;
std::vector<StringRef> Expr;
+ bool Provide = false;
+ // Hidden and Ignore can be true, only if Provide is true
+ bool Hidden = false;
+ bool Ignore = false;
};
// Linker scripts allow additional constraints to be put on ouput sections.
Modified: lld/trunk/test/ELF/linkerscript-locationcounter.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-locationcounter.s?rev=276398&r1=276397&r2=276398&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript-locationcounter.s (original)
+++ lld/trunk/test/ELF/linkerscript-locationcounter.s Fri Jul 22 02:38:40 2016
@@ -319,7 +319,7 @@
# RUN: }" > %t.script
# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=BRACKETERR2 %s
-# BRACKETERR2: stray token: )
+# BRACKETERR2: expected, but got *
## Empty expression.
# RUN: echo "SECTIONS { \
Modified: lld/trunk/test/ELF/linkerscript-symbols.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-symbols.s?rev=276398&r1=276397&r2=276398&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript-symbols.s (original)
+++ lld/trunk/test/ELF/linkerscript-symbols.s Fri Jul 22 02:38:40 2016
@@ -1,11 +1,43 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# Simple symbol assignment. Should raise conflict in case we
+# have duplicates in any input section, but currently simply
+# replaces the value.
# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
# RUN: ld.lld -o %t1 --script %t.script %t
-# RUN: llvm-objdump -t %t1 | FileCheck %s
-# CHECK: 0000000000000121 *ABS* 00000000 text_end
+# 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()
+# 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
+
+# Provide existing symbol. The value should be 0, even though we
+# have value of 1 in PROVIDE()
+# RUN: echo "SECTIONS { PROVIDE(somesym = 1);}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE2 %s
+# PROVIDE2: 0000000000000000 *ABS* 00000000 somesym
+
+# Provide existing symbol. The value should be 0, even though we
+# have value of 1 in PROVIDE(). Visibility should not change
+# RUN: echo "SECTIONS { PROVIDE(somesym = 1);}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN2 %s
+# HIDDEN2: 0000000000000000 *ABS* 00000000 somesym
.global _start
_start:
nop
+
+.global somesym
+somesym = 0
More information about the llvm-commits
mailing list