Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -76,13 +76,11 @@ void fixupLocations(std::vector *> &); uint64_t evaluate(std::vector &Tokens, uint64_t LocCounter); template SectionRule *find(InputSectionBase *S); + uint32_t getSectionOrder(StringRef Name); // SECTIONS commands. std::vector Sections; - // Output sections are sorted by this order. - std::vector SectionOrder; - // Section fill attribute for each section. llvm::StringMap> Filler; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -90,6 +90,15 @@ return R && R->Keep; } +uint32_t LinkerScript::getSectionOrder(StringRef Name) { + auto Begin = Locations.begin(); + auto End = Locations.end(); + auto I = std::find_if(Begin, End, [&](LocationNode &N) { + return N.Type == Command::Section && N.SectionName == Name; + }); + return I == End ? (uint32_t)-1 : (I - Begin); +} + // This method finalizes the Locations list. Adds neccesary locations for // orphan sections, what prepares it for futher use without // changes in LinkerScript::assignAddresses(). @@ -102,8 +111,7 @@ // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections. for (OutputSectionBase *Sec : S) { StringRef Name = Sec->getName(); - auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name); - if (I == SectionOrder.end()) + if (getSectionOrder(Name) == (uint32_t)-1) Locations.push_back({Command::Section, {}, {Name}}); } } @@ -157,14 +165,13 @@ return I->second; } -// A compartor to sort output sections. Returns -1 or 1 if both -// A and B are mentioned in linker scripts. Otherwise, returns 0 +// A compartor to sort output sections. Returns -1 or 1 if +// A or B are mentioned in linker script. Otherwise, returns 0 // to use the default rule which is implemented in Writer.cpp. int LinkerScript::compareSections(StringRef A, StringRef B) { - auto E = SectionOrder.end(); - auto I = std::find(SectionOrder.begin(), E, A); - auto J = std::find(SectionOrder.begin(), E, B); - if (I == E || J == E) + uint32_t I = getSectionOrder(A); + uint32_t J = getSectionOrder(B); + if (I == (uint32_t)-1 && J == (uint32_t)-1) return 0; return I < J ? -1 : 1; } @@ -415,7 +422,6 @@ void ScriptParser::readOutputSectionDescription() { StringRef OutSec = next(); - Script->SectionOrder.push_back(OutSec); Script->Locations.push_back({Command::Section, {}, {OutSec}}); expect(":"); expect("{"); Index: test/ELF/linkerscript-orphans.s =================================================================== --- test/ELF/linkerscript-orphans.s +++ test/ELF/linkerscript-orphans.s @@ -0,0 +1,31 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { .writable : { *(.writable) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=TEXTORPHAN %s + +# RUN: echo "SECTIONS { .text : { *(.text) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | \ +# RUN: FileCheck -check-prefix=WRITABLEORPHAN %s + +# TEXTORPHAN: Sections: +# TEXTORPHAN-NEXT: Idx Name +# TEXTORPHAN-NEXT: 0 +# TEXTORPHAN-NEXT: 1 .writable +# TEXTORPHAN-NEXT: 2 .text + +# WRITABLEORPHAN: Sections: +# WRITABLEORPHAN-NEXT: Idx Name +# WRITABLEORPHAN-NEXT: 0 +# WRITABLEORPHAN-NEXT: 1 .text +# WRITABLEORPHAN-NEXT: 2 .writable + +.global _start +_start: + nop + +.section .writable,"aw" + .zero 4