Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -36,6 +36,8 @@ StringRef Dest; StringRef SectionPattern; + + uint64_t Flags = 0; }; // This enum represents what we can observe in SECTIONS tag of script: @@ -89,6 +91,9 @@ public: typedef PhdrEntry Phdr; + void scanInputSection(InputSectionBase *S); + uintX_t getSectionFlags(InputSectionBase *S); + StringRef getOutputSection(InputSectionBase *S); ArrayRef getFiller(StringRef Name); bool isDiscarded(InputSectionBase *S); @@ -107,6 +112,8 @@ std::vector getPhdrIndicesForSection(StringRef Name); uintX_t Dot; + + llvm::DenseMap *, SectionRule *> InputSections; }; // Variable template is a C++14 feature, so we can't template Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -187,11 +187,34 @@ uint64_t ExprParser::parseExpr() { return parseExpr1(parsePrimary(), 0); } template +void LinkerScript::scanInputSection(InputSectionBase *S) { + if (!S || S == &InputSection::Discarded || !S->Live) + return; + + auto I = llvm::find_if(Opt.Sections, [&](SectionRule &R) { + return globMatch(R.SectionPattern, S->getSectionName()); + }); + if (I == Opt.Sections.end()) + return; + + InputSections[S] = &*I; + if (I->Dest == "/DISCARD/") + return; + + I->Flags |= S->getSectionHdr()->sh_flags; +} + +template +typename ELFT::uint +LinkerScript::getSectionFlags(InputSectionBase *S) { + SectionRule *Rule = InputSections[S]; + return Rule ? Rule->Flags : S->getSectionHdr()->sh_flags; +} + +template StringRef LinkerScript::getOutputSection(InputSectionBase *S) { - for (SectionRule &R : Opt.Sections) - if (globMatch(R.SectionPattern, S->getSectionName())) - return R.Dest; - return ""; + SectionRule *Rule = InputSections[S]; + return Rule ? Rule->Dest : ""; } template Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1785,7 +1785,9 @@ OutputSectionFactory::createKey(InputSectionBase *C, StringRef OutsecName) { const Elf_Shdr *H = C->getSectionHdr(); - uintX_t Flags = H->sh_flags & ~SHF_GROUP & ~SHF_COMPRESSED; + uintX_t Flags = ScriptConfig->DoLayout ? Script::X->getSectionFlags(C) + : H->sh_flags; + Flags &= ~SHF_GROUP & ~SHF_COMPRESSED; // For SHF_MERGE we create different output sections for each alignment. // This makes each output section simple and keeps a single level mapping from Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -625,11 +625,17 @@ // Create output section objects and add them to OutputSections. template void Writer::createSections() { + typedef const std::unique_ptr> ObjectFile; + + if (ScriptConfig->DoLayout) + for (ObjectFile &F : Symtab.getObjectFiles()) + for (InputSectionBase *C : F->getSections()) + Script::X->scanInputSection(C); + // Create output sections for input object file sections. std::vector *> RegularSections; OutputSectionFactory Factory; - for (const std::unique_ptr> &F : - Symtab.getObjectFiles()) { + for (ObjectFile &F : Symtab.getObjectFiles()) { for (InputSectionBase *C : F->getSections()) { if (isDiscarded(C)) { reportDiscarded(C, F); Index: test/ELF/linkerscript-repsection-va.s =================================================================== --- test/ELF/linkerscript-repsection-va.s +++ test/ELF/linkerscript-repsection-va.s @@ -7,9 +7,8 @@ # CHECK: Sections: # CHECK-NEXT: Idx Name Size Address Type # CHECK-NEXT: 0 00000000 0000000000000000 -# CHECK-NEXT: 1 .foo 00000004 0000000000000158 DATA -# CHECK-NEXT: 2 .foo 00000004 000000000000015c DATA -# CHECK-NEXT: 3 .text 00000001 0000000000000160 TEXT DATA +# CHECK-NEXT: 1 .foo 00000008 0000000000000158 DATA +# CHECK-NEXT: 2 .text 00000001 0000000000000160 TEXT DATA .global _start _start: