Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -24,6 +24,7 @@ namespace elf { class InputFile; +class SectionBase; struct Symbol; enum ELFKind { @@ -73,6 +74,13 @@ uint8_t OriginalBinding; }; +// For handling --symbol-ordering-file. +struct SymbolOrdering { + // A map from section to it's priority. + llvm::DenseMap SectionsOrder; + std::vector Symbols; +}; + // This struct contains the global configuration for the linker. // Most fields are direct mapping from the command line options // and such fields have the same name as the corresponding options. @@ -102,7 +110,6 @@ std::vector AuxiliaryList; std::vector FilterList; std::vector SearchPaths; - std::vector SymbolOrderingFile; std::vector Undefined; std::vector VersionScriptGlobals; std::vector VersionScriptLocals; @@ -162,6 +169,7 @@ DiscardPolicy Discard; SortSectionPolicy SortSection; StripPolicy Strip; + SymbolOrdering SymbolOrderingFile; UnresolvedPolicy UnresolvedSymbols; Target2Policy Target2; BuildIdKind BuildId = BuildIdKind::None; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -726,7 +726,7 @@ if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) if (Optional Buffer = readFile(Arg->getValue())) - Config->SymbolOrderingFile = getLines(*Buffer); + Config->SymbolOrderingFile.Symbols = getLines(*Buffer); // If --retain-symbol-file is used, we'll keep only the symbols listed in // the file and discard all others. Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -286,6 +286,29 @@ std::stable_sort(Begin, End, getComparator(K)); } +static void 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; +} + +static void sortBySymbolsOrder(InputSection **Begin, InputSection **End) { + if (Config->SymbolOrderingFile.SectionsOrder.empty()) + return; + MutableArrayRef In(Begin, End - Begin); + sortByOrder(In, [&](InputSectionBase *S) { + return Config->SymbolOrderingFile.SectionsOrder.lookup(S); + }); +} + // Compute and remember which sections the InputSectionDescription matches. std::vector LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { @@ -331,8 +354,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) { + sortBySymbolsOrder(Begin, End); + continue; + } if (Pat.SortOuter != SortSectionPolicy::None) { if (Pat.SortInner == SortSectionPolicy::Default) sortSections(Begin, End, Config->SortSection); @@ -927,18 +957,8 @@ } void OutputSectionCommand::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); } // Returns true if S matches /Filename.?\.o$/. Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -172,6 +172,9 @@ if (!Config->Relocatable) addReservedSymbols(); + if (!Config->SymbolOrderingFile.Symbols.empty()) + scanSectionOrderFile(); + // Create output sections. if (Script->Opt.HasSections) { // If linker script contains SECTIONS commands, let it create sections. @@ -794,6 +797,27 @@ addOptionalRegular(S, In::RelaIplt, -1, STV_HIDDEN, STB_WEAK); } +template static void scanSectionOrderFile() { + // 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.Symbols.size(); + for (StringRef S : Config->SymbolOrderingFile.Symbols) + SymbolOrder.insert({S, Priority++}); + + // Build a map from sections to their priorities. + for (elf::ObjectFile *File : Symtab::X->getObjectFiles()) { + for (SymbolBody *Body : File->getSymbols()) { + auto *D = dyn_cast(Body); + if (!D || !D->Section) + continue; + int &Priority = Config->SymbolOrderingFile.SectionsOrder[D->Section]; + Priority = std::min(Priority, SymbolOrder.lookup(D->getName())); + } + } +} + // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. template void Writer::addReservedSymbols() { @@ -880,33 +904,14 @@ // Sort input sections using the list provided by --symbol-ordering-file. template static void sortBySymbolsOrder() { - if (Config->SymbolOrderingFile.empty()) + if (Config->SymbolOrderingFile.SectionsOrder.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 (elf::ObjectFile *File : Symtab::X->getObjectFiles()) { - 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. for (BaseCommand *Base : Script->Opt.Commands) if (auto *Cmd = dyn_cast(Base)) - Cmd->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); }); + Cmd->sort([&](InputSectionBase *S) { + return Config->SymbolOrderingFile.SectionsOrder.lookup(S); + }); } template Index: test/ELF/linkerscript/symbol-ordering-file.s =================================================================== --- test/ELF/linkerscript/symbol-ordering-file.s +++ 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