Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -171,6 +171,9 @@ std::vector *> getInputSections(const InputSectionDescription *); + OutputSectionBase *findSection(StringRef Name, + ConstraintKind Constraint); + void discard(OutputSectionCommand &Cmd); std::vector *> @@ -184,6 +187,7 @@ size_t getPhdrIndex(StringRef PhdrName); uintX_t Dot; + std::vector *> EmptySections; }; // Variable template is a C++14 feature, so we can't template Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -159,6 +159,8 @@ } static bool checkConstraint(uint64_t Flags, ConstraintKind Kind) { + if (Kind == ConstraintKind::NoConstraint) + return true; bool RO = (Kind == ConstraintKind::ReadOnly); bool RW = (Kind == ConstraintKind::ReadWrite); bool Writable = Flags & SHF_WRITE; @@ -233,8 +235,12 @@ } std::vector *> V = createInputSectionList(*Cmd); - if (V.empty()) + if (V.empty()) { + EmptySections.push_back( + new OutputSectionBase(Cmd->Name, SHT_NULL, SHF_ALLOC)); + Out::Pool.emplace_back(EmptySections.back()); continue; + } OutputSectionBase *OutSec; bool IsNew; @@ -267,6 +273,36 @@ } } +// Empty section is a section defined in linker script without +// any input section or other kind of data associated with it. +// Empty sections may occur when same linker script is used to +// link multiple applications, which may or may not contain +// EH frames, TLS data, e.t.c. Those sections are not written +// to output file and section-defined symbols should be made +// absolute, otherwise we'll have invalid entries in the symbol table. +template +void addEmptySectionSymbols(OutputSectionCommand *Cmd, + OutputSectionBase *Sec) { + for (std::unique_ptr &Base : Cmd->Commands) { + auto *AssignCmd = dyn_cast(Base.get()); + if (!AssignCmd || !AssignCmd->Sym || + !isa>(AssignCmd->Sym)) + continue; + + auto *Synthetic = cast>(AssignCmd->Sym); + Symbol *S = Synthetic->symbol(); + auto GotIndex = Synthetic->GotIndex; + auto DynsymIndex = Synthetic->DynsymIndex; + + replaceBody>(S, Cmd->Name, + static_cast(S->Visibility)); + auto *Regular = cast>(AssignCmd->Sym); + Regular->GotIndex = GotIndex; + Regular->DynsymIndex = DynsymIndex; + Regular->Value = AssignCmd->Expression(Sec->getVA()); + } +} + // Linker script may define start and end symbols for special section types, // like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list // of regular input input sections, therefore our way of defining symbols for @@ -298,6 +334,12 @@ template void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase *Sec) { + // Add symbols for empty output section. + if (Sec->getType() == SHT_NULL) { + addEmptySectionSymbols(Cmd, Sec); + return; + } + auto *OutSec = dyn_cast>(Sec); if (!OutSec) { Sec->assignOffsets(); @@ -353,15 +395,18 @@ } template -static OutputSectionBase * -findSection(OutputSectionCommand &Cmd, - ArrayRef *> Sections) { - for (OutputSectionBase *Sec : Sections) { - if (Sec->getName() != Cmd.Name) +OutputSectionBase * +LinkerScript::findSection(StringRef Name, ConstraintKind Constraint) { + for (OutputSectionBase *Sec : *OutputSections) { + if (Sec->getName() != Name) continue; - if (checkConstraint(Sec->getFlags(), Cmd.Constraint)) + if (checkConstraint(Sec->getFlags(), Constraint)) return Sec; } + for (OutputSectionBase *Sec : EmptySections) + if (Sec->getName() == Name) + return Sec; + return nullptr; } @@ -398,7 +443,7 @@ } auto *Cmd = cast(Base.get()); - OutputSectionBase *Sec = findSection(*Cmd, *OutputSections); + OutputSectionBase *Sec = findSection(Cmd->Name, Cmd->Constraint); if (!Sec) continue; @@ -543,18 +588,18 @@ template typename ELFT::uint LinkerScript::getOutputSectionAddress(StringRef Name) { - for (OutputSectionBase *Sec : *OutputSections) - if (Sec->getName() == Name) - return Sec->getVA(); + if (OutputSectionBase *Sec = + findSection(Name, ConstraintKind::NoConstraint)) + return Sec->getVA(); error("undefined section " + Name); return 0; } template typename ELFT::uint LinkerScript::getOutputSectionSize(StringRef Name) { - for (OutputSectionBase *Sec : *OutputSections) - if (Sec->getName() == Name) - return Sec->getSize(); + if (OutputSectionBase *Sec = + findSection(Name, ConstraintKind::NoConstraint)) + return Sec->getSize(); error("undefined section " + Name); return 0; } Index: test/ELF/linkerscript/symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/symbols-synthetic.s +++ test/ELF/linkerscript/symbols-synthetic.s @@ -50,6 +50,19 @@ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# Check symbols inside empty section. Also check its size and address. +# RUN: echo "SECTIONS { \ +# RUN: .aaa : { \ +# RUN: PROVIDE_HIDDEN(_begin_sec = .); \ +# RUN: *(.bbb) \ +# RUN: *(.ccc) \ +# RUN: PROVIDE_HIDDEN(_end_sec = .); } \ +# RUN: addr_of_aaa = ADDR(.aaa); \ +# RUN: size_of_aaa = SIZEOF(.aaa); \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=EMPTY %s + # SIMPLE: 0000000000000160 .foo 00000000 .hidden _end_sec # SIMPLE: 0000000000000158 .foo 00000000 _begin_sec # SIMPLE-NEXT: 0000000000000158 .foo 00000000 begin_foo @@ -63,8 +76,15 @@ # SIMPLE-NEXT: 0000000000001010 .eh_frame_hdr 00000000 __eh_frame_hdr_start2 # SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end # SIMPLE-NEXT: 0000000000001020 .eh_frame_hdr 00000000 __eh_frame_hdr_end2 + # ERROR: section '.eh_frame_hdr' supports only start and end symbols +# EMPTY: 0000000000000120 *ABS* 00000000 .hidden _begin_sec +# EMPTY-NEXT: 0000000000000120 *ABS* 00000000 .hidden _end_sec +# EMPTY-NEXT: 0000000000000160 .text 00000000 _start +# EMPTY-NEXT: 0000000000000120 *ABS* 00000000 addr_of_aaa +# EMPTY-NEXT: 0000000000000000 *ABS* 00000000 size_of_aaa + .global _start _start: nop