Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -171,7 +171,7 @@ // into single output sections. We currently do not support adding // mergeable input sections to regular output ones as well as adding // regular input sections to mergeable output. - if (ScriptConfig->HasContents) + if (ScriptConfig->HasSections) return false; // A mergeable section with size 0 is useless because they don't have Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -138,15 +138,13 @@ // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { - // Used to create symbol assignments outside SECTIONS command. - std::vector> Assignments; // Used to assign addresses to sections. std::vector> Commands; // Used to assign sections to headers. std::vector PhdrsCommands; - bool HasContents = false; + bool HasSections = false; llvm::BumpPtrAllocator Alloc; @@ -164,7 +162,7 @@ public: LinkerScript(); ~LinkerScript(); - void createAssignments(); + void processCommands(OutputSectionFactory &Factory); void createSections(OutputSectionFactory &Factory); std::vector> createPhdrs(); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -48,6 +48,11 @@ Symbol *Sym = Symtab::X->addRegular(Cmd->Name, STB_GLOBAL, STV_DEFAULT); Sym->Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; 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); } template static void addSynthetic(SymbolAssignment *Cmd) { @@ -205,23 +210,22 @@ return Ret; } -template void LinkerScript::createAssignments() { - for (const std::unique_ptr &Cmd : Opt.Assignments) { - if (shouldDefine(Cmd.get())) - addRegular(Cmd.get()); - if (Cmd->Sym) - cast>(Cmd->Sym)->Value = Cmd->Expression(0); - } -} - template -void LinkerScript::createSections(OutputSectionFactory &Factory) { +void LinkerScript::processCommands(OutputSectionFactory &Factory) { for (const std::unique_ptr &Base1 : Opt.Commands) { if (auto *Cmd = dyn_cast(Base1.get())) { if (shouldDefine(Cmd)) addRegular(Cmd); continue; } + if (auto *Cmd = dyn_cast(Base1.get())) { + // If we don't have SECTIONS then output sections have already been + // created by Writer. The LinkerScript::assignAddresses + // will not be called, so ASSERT should be evaluated now. + if (!Opt.HasSections) + Cmd->Expression(0); + continue; + } if (auto *Cmd = dyn_cast(Base1.get())) { std::vector *> V = createInputSectionList(*Cmd); @@ -249,7 +253,11 @@ } } } +} +template +void LinkerScript::createSections(OutputSectionFactory &Factory) { + processCommands(Factory); // Add orphan sections. for (const std::unique_ptr> &F : Symtab::X->getObjectFiles()) { @@ -714,7 +722,9 @@ if (Tok == ";") continue; - if (Tok == "ENTRY") { + if (Tok == "ASSERT") { + Opt.Commands.emplace_back(new AssertCommand(readAssert())); + } else if (Tok == "ENTRY") { readEntry(); } else if (Tok == "EXTERN") { readExtern(); @@ -737,10 +747,7 @@ } else if (Tok == "VERSION") { readVersion(); } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok, true)) { - if (Opt.HasContents) - Opt.Commands.emplace_back(Cmd); - else - Opt.Assignments.emplace_back(Cmd); + Opt.Commands.emplace_back(Cmd); } else { setError("unknown directive: " + Tok); } @@ -898,7 +905,7 @@ } void ScriptParser::readSections() { - Opt.HasContents = true; + Opt.HasSections = true; expect("{"); while (!Error && !skip("}")) { StringRef Tok = next(); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -249,13 +249,13 @@ CommonInputSection Common(getCommonSymbols()); CommonInputSection::X = &Common; - Script::X->createAssignments(); - Script::X->OutputSections = &OutputSections; - if (ScriptConfig->HasContents) + if (ScriptConfig->HasSections) { Script::X->createSections(Factory); - else + } else { createSections(); + Script::X->processCommands(Factory); + } finalizeSections(); if (HasError) @@ -267,7 +267,7 @@ Phdrs = Script::X->hasPhdrsCommands() ? Script::X->createPhdrs() : createPhdrs(); fixHeaders(); - if (ScriptConfig->HasContents) { + if (ScriptConfig->HasSections) { Script::X->assignAddresses(); } else { fixSectionAlignments(); @@ -611,7 +611,7 @@ Symtab::X->addIgnored("__tls_get_addr"); // If linker script do layout we do not need to create any standart symbols. - if (ScriptConfig->HasContents) + if (ScriptConfig->HasSections) return; ElfSym::EhdrStart = Symtab::X->addIgnored("__ehdr_start"); @@ -1063,7 +1063,7 @@ // sections. These are special, we do not include them into output sections // list, but have them to simplify the code. template void Writer::fixHeaders() { - uintX_t BaseVA = ScriptConfig->HasContents ? 0 : Config->ImageBase; + uintX_t BaseVA = ScriptConfig->HasSections ? 0 : Config->ImageBase; Out::ElfHeader->setVA(BaseVA); uintX_t Off = Out::ElfHeader->getSize(); Out::ProgramHeaders->setVA(Off + BaseVA); Index: test/ELF/linkerscript/assert.s =================================================================== --- test/ELF/linkerscript/assert.s +++ test/ELF/linkerscript/assert.s @@ -25,3 +25,18 @@ # RUN: }" > %t4.script # RUN: ld.lld -shared -o %t4 --script %t4.script %t1.o # RUN: llvm-readobj %t4 > /dev/null + +# RUN: echo "SECTIONS { \ +# RUN: .foo : { *(.foo) } \ +# RUN: } \ +# RUN: ASSERT(SIZEOF(.foo) == 8, \"true\");" > %t5.script +# RUN: ld.lld -shared -o %t5 --script %t5.script %t1.o +# RUN: llvm-readobj %t5 > /dev/null + +## Even without SECTIONS block we still use section names +## in expressions +# RUN: echo "ASSERT(SIZEOF(.foo) == 8, \"true\");" > %t5.script +# RUN: ld.lld -shared -o %t5 --script %t5.script %t1.o +# RUN: llvm-readobj %t5 > /dev/null +.section .foo, "a" + .quad 0