Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -56,29 +56,20 @@ LinkerScriptBase *elf::ScriptBase; ScriptConfiguration *elf::ScriptConfig; -template static void addRegular(SymbolAssignment *Cmd) { +template static SymbolBody *addRegular(SymbolAssignment *Cmd) { uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; - Symbol *Sym = Symtab::X->addRegular(Cmd->Name, Visibility, STT_NOTYPE, - 0, 0, STB_GLOBAL, nullptr, nullptr); - Cmd->Sym = Sym->body(); - - // If we have no SECTIONS then we don't have '.' and don't call - // assignAddresses(). We calculate symbol value immediately in this case. - if (!ScriptConfig->HasSections) - cast>(Cmd->Sym)->Value = Cmd->Expression(0); + Symbol *Sym = + Symtab::X->addRegular(Cmd->Name, Visibility, STT_NOTYPE, 0, 0, + STB_GLOBAL, nullptr, nullptr, true); + return Sym->body(); } -template static void addSynthetic(SymbolAssignment *Cmd) { - // If we have SECTIONS block then output sections haven't been created yet. +template static SymbolBody *addSynthetic(SymbolAssignment *Cmd) { const OutputSectionBase *Sec = ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section(); Symbol *Sym = Symtab::X->addSynthetic( - Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT); - Cmd->Sym = Sym->body(); - - // If we already know section then we can calculate symbol value immediately. - if (Sec) - cast(Cmd->Sym)->Value = Cmd->Expression(0) - Sec->Addr; + Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT, true); + return Sym->body(); } static bool isUnderSysroot(StringRef Path) { @@ -90,21 +81,39 @@ return false; } -template static void addSymbol(SymbolAssignment *Cmd) { - if (Cmd->Expression.IsAbsolute()) - addRegular(Cmd); - else - addSynthetic(Cmd); +template static void assignSymbol(SymbolAssignment *Cmd) { + // If there are sections, then let the value be assigned later in + // `assignAddresses`. + if (ScriptConfig->HasSections) + return; + + uint64_t Value = Cmd->Expression(0); + if (Cmd->Expression.IsAbsolute()) { + cast>(Cmd->Sym)->Value = Value; + } else { + const OutputSectionBase *Sec = Cmd->Expression.Section(); + if (Sec) + cast(Cmd->Sym)->Value = Value - Sec->Addr; + } } -// If a symbol was in PROVIDE(), we need to define it only when -// it is an undefined symbol. -template static bool shouldDefine(SymbolAssignment *Cmd) { + +template static void addSymbol(SymbolAssignment *Cmd) { if (Cmd->Name == ".") - return false; - if (!Cmd->Provide) - return true; + return; + + // If a symbol was in PROVIDE(), we need to define it only when + // it is a referenced undefined symbol. SymbolBody *B = Symtab::X->find(Cmd->Name); - return B && B->isUndefined(); + if (Cmd->Provide && (!B || B->isDefined())) + return; + + // Otherwise, create a new symbol if one does not exist or an + // undefined one does exist. + if (Cmd->Expression.IsAbsolute()) + Cmd->Sym = addRegular(Cmd); + else + Cmd->Sym = addSynthetic(Cmd); + assignSymbol(Cmd); } bool SymbolAssignment::classof(const BaseCommand *C) { @@ -313,8 +322,7 @@ // Handle symbol assignments outside of any output section. if (auto *Cmd = dyn_cast(Base1.get())) { - if (shouldDefine(Cmd)) - addSymbol(Cmd); + addSymbol(Cmd); continue; } @@ -356,8 +364,7 @@ // ".foo : { ...; bar = .; }". Handle them. for (const std::unique_ptr &Base : Cmd->Commands) if (auto *OutCmd = dyn_cast(Base.get())) - if (shouldDefine(OutCmd)) - addSymbol(OutCmd); + addSymbol(OutCmd); // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign // is given, input sections are aligned to that value, whether the Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -60,10 +60,12 @@ Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, uintX_t Value, uintX_t Size, uint8_t Binding, - InputSectionBase *Section, InputFile *File); + InputSectionBase *Section, InputFile *File, + bool ForceReplace = false); Symbol *addSynthetic(StringRef N, const OutputSectionBase *Section, - uintX_t Value, uint8_t StOther); + uintX_t Value, uint8_t StOther, + bool ForceReplace = false); void addShared(SharedFile *F, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -382,14 +382,14 @@ uint8_t Type, uintX_t Value, uintX_t Size, uint8_t Binding, InputSectionBase *Section, - InputFile *File) { + InputFile *File, bool ForceReplace) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, Section == nullptr, Value); - if (Cmp > 0) + if (Cmp > 0 || ForceReplace) replaceBody>(S, Name, /*IsLocal=*/false, StOther, Type, Value, Size, Section, File); else if (Cmp == 0) @@ -400,14 +400,15 @@ template Symbol *SymbolTable::addSynthetic(StringRef N, const OutputSectionBase *Section, - uintX_t Value, uint8_t StOther) { + uintX_t Value, uint8_t StOther, + bool ForceReplace) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(N, STT_NOTYPE, getVisibility(StOther), /*CanOmitFromDynSym*/ false, nullptr); int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL, /*IsAbsolute*/ false, /*Value*/ 0); - if (Cmp > 0) + if (Cmp > 0 || ForceReplace) replaceBody(S, N, Value, Section); else if (Cmp == 0) reportDuplicate(S->body(), nullptr); Index: test/ELF/linkerscript/symbol-assignexpr.s =================================================================== --- test/ELF/linkerscript/symbol-assignexpr.s +++ test/ELF/linkerscript/symbol-assignexpr.s @@ -13,14 +13,20 @@ # RUN: symbol9 = - 4; \ # RUN: symbol10 = 0xfedcba9876543210; \ # RUN: symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \ +# RUN: symbol12 = 0x1234; \ +# RUN: symbol12 += 1; \ +# RUN: bar = 0x5678; \ +# RUN: baz = 0x9abc; \ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-objdump -t %t1 | FileCheck %s # CHECK: SYMBOL TABLE: # CHECK-NEXT: 0000000000000000 *UND* 00000000 -# CHECK-NEXT: .text 00000000 _start -# CHECK-NEXT: .text 00000000 foo +# CHECK-NEXT: 0000000000000000 .text 00000000 _start +# CHECK-NEXT: 0000000000005678 *ABS* 00000000 bar +# CHECK-NEXT: 0000000000009abc *ABS* 00000000 baz +# CHECK-NEXT: 0000000000000001 .text 00000000 foo # CHECK-NEXT: 0000000000001000 *ABS* 00000000 symbol # CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol2 # CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol3 @@ -32,6 +38,7 @@ # CHECK-NEXT: fffffffffffffffc *ABS* 00000000 symbol9 # CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10 # CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11 +# CHECK-NEXT: 0000000000001235 *ABS* 00000000 symbol12 # RUN: echo "SECTIONS { \ # RUN: symbol2 = symbol; \ @@ -46,3 +53,9 @@ .global foo foo: + nop + +.global bar +bar = 0x1234 + +.comm baz,8,8 Index: test/ELF/mips-gp-ext.s =================================================================== --- test/ELF/mips-gp-ext.s +++ test/ELF/mips-gp-ext.s @@ -1,10 +1,6 @@ # Check that the linker use a value of _gp symbol defined # in a linker script to calculate GOT relocations. -# FIXME: This test is xfailed because it depends on D27276 patch -# that enables absolute symbols redefinition by a linker's script. -# XFAIL: * - # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o # RUN: echo "SECTIONS { \