Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -67,6 +67,9 @@ // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN. bool Provide = false; bool Hidden = false; + + // Whether the "." is available. + bool DotAvailable = true; }; // Linker scripts allow additional constraints to be put on ouput sections. Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -370,11 +370,11 @@ for (const std::unique_ptr &Base : Opt.Commands) { if (auto *Cmd = dyn_cast(Base.get())) { - if (Cmd->Name == ".") { + if (Cmd->Name == "." && Cmd->DotAvailable) Dot = Cmd->Expression(Dot); - } else if (Cmd->Sym) { - cast>(Cmd->Sym)->Value = Cmd->Expression(Dot); - } + else if (Cmd->Sym) + cast>(Cmd->Sym)->Value = Cmd->Expression( + Cmd->DotAvailable ? Dot : 0); continue; } @@ -653,10 +653,14 @@ void ScriptParser::run() { while (!atEOF()) { StringRef Tok = next(); - if (Handler Fn = Cmd.lookup(Tok)) + if (Handler Fn = Cmd.lookup(Tok)) { (this->*Fn)(); - else + } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) { + Cmd->DotAvailable = false; + Opt.Commands.emplace_back(Cmd); + } else { setError("unknown directive: " + Tok); + } } } Index: test/ELF/invalid-linkerscript.test =================================================================== --- test/ELF/invalid-linkerscript.test +++ test/ELF/invalid-linkerscript.test @@ -15,7 +15,7 @@ # RUN: echo foobar > %t1 # RUN: not ld.lld %t1 no-such-file 2>&1 | FileCheck -check-prefix=ERR1 %s -# ERR1: unknown directive: foobar +# ERR1: unexpected EOF # ERR1: cannot open no-such-file: # RUN: echo "foo \"bar" > %t2 Index: test/ELF/linkerscript/linkerscript-symbols.s =================================================================== --- test/ELF/linkerscript/linkerscript-symbols.s +++ test/ELF/linkerscript/linkerscript-symbols.s @@ -41,6 +41,41 @@ # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN3 %s # HIDDEN3: 0000000000000001 *ABS* 00000000 .hidden newsym +# The symbol is not referenced. Don't provide it. +# RUN: echo "PROVIDE(newsym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE4 %s +# PROVIDE4-NOT: 0000000000000001 *ABS* 00000000 newsym + +# The symbol is not referenced. Don't provide it. +# RUN: echo "PROVIDE_HIDDEN(newsym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN4 %s +# HIDDEN4-NOT: 0000000000000001 *ABS* 00000000 .hidden newsym + +# Provide existing symbol. The value should be 0, even though we +# have value of 1 in PROVIDE() +# RUN: echo "PROVIDE(somesym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE5 %s +# PROVIDE5: 0000000000000000 *ABS* 00000000 somesym + +# Provide existing symbol. The value should be 0, even though we +# have value of 1 in PROVIDE_HIDDEN(). Visibility should not change +# RUN: echo "PROVIDE_HIDDEN(somesym = 1);" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN5 %s +# HIDDEN5: 0000000000000000 *ABS* 00000000 somesym + +# Provide existing symbol. The value should be 0, even though we +# have value of 1 in PROVIDE_HIDDEN(). Visibility should not change +# RUN: echo ". = 0x1000; globalsym = .; SECTIONS { localsym = .; }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=DOT %s +# DOT: 0000000000000000 *ABS* 00000000 somesym +# DOT: 0000000000000000 *ABS* 00000000 globalsym +# DOT: 0000000000000120 *ABS* 00000000 localsym + .global _start _start: nop