Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -104,6 +104,9 @@ bool Provide = false; bool Hidden = false; + // Flag shows if this command is -defsym assignment. + bool IsDefsym = false; + // Holds file name and line number for error reporting. std::string Location; }; @@ -206,6 +209,7 @@ llvm::DenseMap NameToOutputSection; + void addDefSymbol(SymbolAssignment *Cmd); void addSymbol(SymbolAssignment *Cmd); void assignSymbol(SymbolAssignment *Cmd, bool InSec); void setDot(Expr E, const Twine &Loc, bool InSec); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -153,6 +153,38 @@ Cmd->Sym = cast(Sym); } +void LinkerScript::addDefSymbol(SymbolAssignment *Cmd) { + ExprValue Value = Cmd->Expression(); + SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; + uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; + uint64_t SymValue = Value.Sec ? 0 : Value.getValue(); + + switch (Config->EKind) { + case ELF32LEKind: + Symtab->addRegular(Cmd->Name, Visibility, STT_NOTYPE, SymValue, + /*Size=*/0, STB_GLOBAL, Sec, + /*File=*/nullptr); + return; + case ELF32BEKind: + Symtab->addRegular(Cmd->Name, Visibility, STT_NOTYPE, SymValue, + /*Size=*/0, STB_GLOBAL, Sec, + /*File=*/nullptr); + return; + case ELF64LEKind: + Symtab->addRegular(Cmd->Name, Visibility, STT_NOTYPE, SymValue, + /*Size=*/0, STB_GLOBAL, Sec, + /*File=*/nullptr); + return; + case ELF64BEKind: + Symtab->addRegular(Cmd->Name, Visibility, STT_NOTYPE, SymValue, + /*Size=*/0, STB_GLOBAL, Sec, + /*File=*/nullptr); + return; + default: + llvm_unreachable("unknown Config->EKind"); + } +} + // This function is called from assignAddresses, while we are // fixing the output section addresses. This function is supposed // to set the final value for a given symbol assignment. @@ -364,7 +396,10 @@ for (BaseCommand *Base : SectionCommands) { // Handle symbol assignments outside of any output section. if (auto *Cmd = dyn_cast(Base)) { - addSymbol(Cmd); + if (Cmd->IsDefsym) + addDefSymbol(Cmd); + else + addSymbol(Cmd); continue; } Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -275,6 +275,7 @@ if (!atEOF()) setError("EOF expected, but got " + next()); SymbolAssignment *Cmd = make(Name, E, getCurrentLocation()); + Cmd->IsDefsym = true; Script->SectionCommands.push_back(Cmd); } Index: test/ELF/linkerscript/symbol-multiple-defs.s =================================================================== --- test/ELF/linkerscript/symbol-multiple-defs.s +++ test/ELF/linkerscript/symbol-multiple-defs.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "foo = 0x3;" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s --check-prefix=SCRIPT +# SCRIPT: 0000000000000003 *ABS* 00000000 foo + +# RUN: not ld.lld --defsym=foo=0x3 -o %t2 %t 2>&1 \ +# RUN: | FileCheck %s --check-prefix=ERR +# ERR: duplicate symbol: foo + +.global foo +foo: