Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -165,27 +165,46 @@ Cmd->Sym = cast(Sym); } +// This function is called from LinkerScript::declareSymbols. +// It creates a placeholder symbol if needed. +static void declareSymbol(SymbolAssignment *Cmd) { + if (!shouldDefineSym(Cmd)) + return; + + // We can't calculate final value right now. + Symbol *Sym; + uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; + std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, + /*CanOmitFromDynSym*/ false, + /*File*/ nullptr); + replaceSymbol(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, + STT_NOTYPE, 0, 0, nullptr); + Cmd->Sym = cast(Sym); + Cmd->Provide = false; +} + // Symbols defined in script should not be inlined by LTO. At the same time // we don't know their final values until late stages of link. Here we scan // over symbol assignment commands and create placeholder symbols if needed. void LinkerScript::declareSymbols() { assert(!Ctx); for (BaseCommand *Base : SectionCommands) { - auto *Cmd = dyn_cast(Base); - if (!Cmd || !shouldDefineSym(Cmd)) + if (auto *Cmd = dyn_cast(Base)) { + declareSymbol(Cmd); continue; - - // We can't calculate final value right now. - Symbol *Sym; - uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; - std::tie(Sym, std::ignore) = - Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, - /*CanOmitFromDynSym*/ false, - /*File*/ nullptr); - replaceSymbol(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, - STT_NOTYPE, 0, 0, nullptr); - Cmd->Sym = cast(Sym); - Cmd->Provide = false; + } + auto *Sec = dyn_cast(Base); + if (!Sec) + continue; + // If the output section directive has constraints, + // we can't say for sure if it is going to be included or not. + // Skip such sections for now. Improve the checks if we ever + // need symbols from that sections to be declared early. + if (Sec->Constraint != ConstraintKind::NoConstraint) + continue; + for (BaseCommand *Base2 : Sec->SectionCommands) + if (auto *Cmd = dyn_cast(Base2)) + declareSymbol(Cmd); } } Index: test/ELF/linkerscript/symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/symbols-synthetic.s +++ test/ELF/linkerscript/symbols-synthetic.s @@ -61,7 +61,6 @@ # SIMPLE-NEXT: 0000000000000120 .foo 00000000 _begin_sec # SIMPLE-NEXT: 0000000000000128 *ABS* 00000000 _end_sec_abs # SIMPLE-NEXT: 0000000000001048 .text 00000000 _start -# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_3 # SIMPLE-NEXT: 0000000000000120 .foo 00000000 begin_foo # SIMPLE-NEXT: 0000000000000128 .foo 00000000 end_foo # SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1 @@ -69,6 +68,7 @@ # SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar # SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar # SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_2 +# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_3 # SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start # SIMPLE-NEXT: 0000000000001010 *ABS* 00000000 __eh_frame_hdr_start2 # SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end Index: test/ELF/linkerscript/version-script.s =================================================================== --- test/ELF/linkerscript/version-script.s +++ test/ELF/linkerscript/version-script.s @@ -5,6 +5,11 @@ # RUN: ld.lld -T %t.script -shared --no-undefined-version %t.o -o %t.so # RUN: llvm-readobj -V %t.so | FileCheck %s +# RUN: echo "SECTIONS { .text : { bar = foo; *(.text) } }" > %t.script +# RUN: echo "VERSION { V { global: foo; bar; local: *; }; }" >> %t.script +# RUN: ld.lld -T %t.script -shared --no-undefined-version %t.o -o %t.so +# RUN: llvm-readobj -V %t.so | FileCheck %s + ## Check that we are able to version symbols defined in script. # CHECK: Symbols [ # CHECK-NEXT: Symbol {