Index: lld/trunk/ELF/InputSection.h =================================================================== --- lld/trunk/ELF/InputSection.h +++ lld/trunk/ELF/InputSection.h @@ -331,6 +331,9 @@ // The list of all input sections. extern std::vector InputSections; +// Builds section order for handling --symbol-ordering-file. +template llvm::DenseMap buildSectionOrder(); + } // namespace elf std::string toString(const elf::InputSectionBase *); Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -44,6 +44,29 @@ return (toString(Sec->File) + ":(" + Sec->Name + ")").str(); } +template DenseMap elf::buildSectionOrder() { + // Build a map from symbols to their priorities. Symbols that didn't + // appear in the symbol ordering file have the lowest priority 0. + // All explicitly mentioned symbols have negative (higher) priorities. + DenseMap SymbolOrder; + int Priority = -Config->SymbolOrderingFile.size(); + for (StringRef S : Config->SymbolOrderingFile) + SymbolOrder.insert({S, Priority++}); + + // Build a map from sections to their priorities. + DenseMap SectionOrder; + for (ObjFile *File : ObjFile::Instances) { + for (SymbolBody *Body : File->getSymbols()) { + auto *D = dyn_cast(Body); + if (!D || !D->Section) + continue; + int &Priority = SectionOrder[D->Section]; + Priority = std::min(Priority, SymbolOrder.lookup(D->getName())); + } + } + return SectionOrder; +} + template static ArrayRef getSectionContents(ObjFile *File, const typename ELFT::Shdr *Hdr) { @@ -982,6 +1005,11 @@ return Piece.OutputOff + Addend; } +template DenseMap elf::buildSectionOrder(); +template DenseMap elf::buildSectionOrder(); +template DenseMap elf::buildSectionOrder(); +template DenseMap elf::buildSectionOrder(); + template InputSection::InputSection(ObjFile *, const ELF32LE::Shdr *, StringRef); template InputSection::InputSection(ObjFile *, const ELF32BE::Shdr *, Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -228,6 +228,29 @@ std::stable_sort(Begin, End, getComparator(K)); } +static llvm::DenseMap getSectionOrder() { + switch (Config->EKind) { + case ELF32LEKind: + return buildSectionOrder(); + case ELF32BEKind: + return buildSectionOrder(); + case ELF64LEKind: + return buildSectionOrder(); + case ELF64BEKind: + return buildSectionOrder(); + default: + llvm_unreachable("unknown ELF type"); + } +} + +static void sortBySymbolOrder(InputSection **Begin, InputSection **End) { + if (Config->SymbolOrderingFile.empty()) + return; + static llvm::DenseMap Order = getSectionOrder(); + MutableArrayRef In(Begin, End - Begin); + sortByOrder(In, [&](InputSectionBase *S) { return Order.lookup(S); }); +} + // Compute and remember which sections the InputSectionDescription matches. std::vector LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { @@ -273,8 +296,15 @@ // --sort-section is handled as an inner SORT command. // 3. If one SORT command is given, and if it is SORT_NONE, don't sort. // 4. If no SORT command is given, sort according to --sort-section. + // 5. If no SORT commands are given and --sort-section is not specified, + // apply sorting provided by --symbol-ordering-file if any exist. InputSection **Begin = Ret.data() + SizeBefore; InputSection **End = Ret.data() + Ret.size(); + if (Pat.SortOuter == SortSectionPolicy::Default && + Config->SortSection == SortSectionPolicy::Default) { + sortBySymbolOrder(Begin, End); + continue; + } if (Pat.SortOuter != SortSectionPolicy::None) { if (Pat.SortInner == SortSectionPolicy::Default) sortSections(Begin, End, Config->SortSection); Index: lld/trunk/ELF/OutputSections.h =================================================================== --- lld/trunk/ELF/OutputSections.h +++ lld/trunk/ELF/OutputSections.h @@ -170,6 +170,8 @@ uint64_t getHeaderSize(); void reportDiscarded(InputSectionBase *IS); +void sortByOrder(llvm::MutableArrayRef In, + std::function Order); extern std::vector OutputSections; } // namespace elf Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -184,6 +184,20 @@ Type == SHT_NOTE; } +void elf::sortByOrder(MutableArrayRef In, + std::function Order) { + typedef std::pair Pair; + auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; + + std::vector V; + for (InputSection *S : In) + V.push_back({Order(S), S}); + std::stable_sort(V.begin(), V.end(), Comp); + + for (size_t I = 0; I < V.size(); ++I) + In[I] = V[I].second; +} + void elf::reportDiscarded(InputSectionBase *IS) { if (!Config->PrintGcSections) return; @@ -291,18 +305,8 @@ } void OutputSection::sort(std::function Order) { - typedef std::pair Pair; - auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; - - std::vector V; assert(Commands.size() == 1); - auto *ISD = cast(Commands[0]); - for (InputSection *S : ISD->Sections) - V.push_back({Order(S), S}); - std::stable_sort(V.begin(), V.end(), Comp); - ISD->Sections.clear(); - for (Pair &P : V) - ISD->Sections.push_back(P.second); + sortByOrder(cast(Commands[0])->Sections, Order); } // Fill [Buf, Buf + Size) with Filler. Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -872,27 +872,8 @@ if (Config->SymbolOrderingFile.empty()) return; - // Build a map from symbols to their priorities. Symbols that didn't - // appear in the symbol ordering file have the lowest priority 0. - // All explicitly mentioned symbols have negative (higher) priorities. - DenseMap SymbolOrder; - int Priority = -Config->SymbolOrderingFile.size(); - for (StringRef S : Config->SymbolOrderingFile) - SymbolOrder.insert({S, Priority++}); - - // Build a map from sections to their priorities. - DenseMap SectionOrder; - for (ObjFile *File : ObjFile::Instances) { - for (SymbolBody *Body : File->getSymbols()) { - auto *D = dyn_cast(Body); - if (!D || !D->Section) - continue; - int &Priority = SectionOrder[D->Section]; - Priority = std::min(Priority, SymbolOrder.lookup(D->getName())); - } - } - // Sort sections by priority. + DenseMap SectionOrder = buildSectionOrder(); for (BaseCommand *Base : Script->Opt.Commands) if (auto *Sec = dyn_cast(Base)) Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); }); Index: lld/trunk/test/ELF/linkerscript/symbol-ordering-file.s =================================================================== --- lld/trunk/test/ELF/linkerscript/symbol-ordering-file.s +++ lld/trunk/test/ELF/linkerscript/symbol-ordering-file.s @@ -0,0 +1,23 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { .foo : { *(.foo) } }" > %t.script + +# RUN: ld.lld %t.o --script %t.script -o %t.out +# RUN: llvm-objdump -s %t.out| FileCheck %s --check-prefix=BEFORE +# BEFORE: Contents of section .foo: +# BEFORE-NEXT: 1122 + +# RUN: echo "_foo2" > %t.ord +# RUN: echo "_foo1" >> %t.ord +# RUN: ld.lld --symbol-ordering-file %t.ord %t.o --script %t.script -o %t2.out +# RUN: llvm-objdump -s %t2.out| FileCheck %s --check-prefix=AFTER +# AFTER: Contents of section .foo: +# AFTER-NEXT: 2211 + +.section .foo,"ax",@progbits,unique,1 +_foo1: + .byte 0x11 + +.section .foo,"ax",@progbits,unique,2 +_foo2: + .byte 0x22