Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -87,6 +87,7 @@ std::vector AuxiliaryList; std::vector DynamicList; std::vector SearchPaths; + std::vector SymbolOrderingFile; std::vector Undefined; std::vector VersionScriptGlobals; std::vector BuildIdVector; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -576,6 +576,10 @@ if (Optional Buffer = readFile(Arg->getValue())) parseDynamicList(*Buffer); + if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) + if (Optional Buffer = readFile(Arg->getValue())) + parseSymbolOrderingList(*Buffer); + for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) Config->DynamicList.push_back(Arg->getValue()); Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -177,6 +177,9 @@ def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; +def symbol_ordering_file: S<"symbol-ordering-file">, + HelpText<"Layout sections in the order specified by symbol file">; + def sysroot: J<"sysroot=">, HelpText<"Set the system root">; def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">; Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -440,6 +440,7 @@ typedef typename ELFT::uint uintX_t; OutputSection(StringRef Name, uint32_t Type, uintX_t Flags); void addSection(InputSectionBase *C) override; + void sortByOrderList(llvm::DenseMap *, unsigned> &); void sortInitFini(); void sortCtorsDtors(); void writeTo(uint8_t *Buf) override; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -13,6 +13,7 @@ #include "LinkerScript.h" #include "GdbIndex.h" #include "Strings.h" +#include "SymbolListFile.h" #include "SymbolTable.h" #include "Target.h" #include "lld/Core/Parallel.h" @@ -982,6 +983,28 @@ this->Header.sh_size = Off; } +// Sort input sections by order of symbols specified in --symbol-ordering-file. +template +void OutputSection::sortByOrderList( + DenseMap *, unsigned> &Order) { + typedef std::pair *> Pair; + auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; + + std::vector V; + for (InputSection *S : Sections) { + auto It = Order.find(S); + if (It == Order.end()) + V.push_back({(unsigned)-1, S}); + else + V.push_back({It->second, S}); + } + + std::stable_sort(V.begin(), V.end(), Comp); + Sections.clear(); + for (Pair &P : V) + Sections.push_back(P.second); +} + // Sorts input sections by section name suffixes, so that .foo.N comes // before .foo.M if N < M. Used to sort .{init,fini}_array.N sections. // We want to keep the original order if the priorities are the same Index: ELF/SymbolListFile.h =================================================================== --- ELF/SymbolListFile.h +++ ELF/SymbolListFile.h @@ -17,6 +17,7 @@ namespace elf { void parseDynamicList(MemoryBufferRef MB); +void parseSymbolOrderingList(MemoryBufferRef MB); } // namespace elf } // namespace lld Index: ELF/SymbolListFile.cpp =================================================================== --- ELF/SymbolListFile.cpp +++ ELF/SymbolListFile.cpp @@ -56,3 +56,24 @@ void elf::parseDynamicList(MemoryBufferRef MB) { DynamicListParser(MB.getBuffer()).run(); } + +// Parse the --symbol-ordering-file argument. File has form: +// +// symbolName1 symbolName2 [...] symbolNameN + +namespace { +class SymbolOrderingListParser final : public ScriptParserBase { +public: + SymbolOrderingListParser(StringRef S) : ScriptParserBase(S) {} + void run(); +}; +} // end anonymous namespace + +void SymbolOrderingListParser::run() { + while (!atEOF() && !Error) + Config->SymbolOrderingFile.push_back(next()); +} + +void elf::parseSymbolOrderingList(MemoryBufferRef MB) { + SymbolOrderingListParser(MB.getBuffer()).run(); +} Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -670,6 +670,40 @@ reinterpret_cast *>(S)->sortCtorsDtors(); } +// Sort input sections using list provided by --symbol-ordering-file option. +template +static void sortSectionsByOrder(ArrayRef *> V) { + if (Config->SymbolOrderingFile.empty()) + return; + + unsigned Order = 0; + DenseMap *, unsigned> SectionsOrder; + + for (StringRef S : Config->SymbolOrderingFile) { + for (elf::ObjectFile *File : Symtab::X->getObjectFiles()) { + for (SymbolBody *Body : File->getSymbols()) { + auto *D = dyn_cast>(Body); + if (!D || !D->Section) + continue; + + StringRef StrTab = File->getStringTable(); + StringRef SymName = D->isLocal() + ? (StrTab.data() + Body->getNameOffset()) + : D->getName(); + if (SymName != S) + continue; + + SectionsOrder.insert({D->Section, Order}); + } + } + ++Order; + } + + for (OutputSectionBase *Base : V) + if (OutputSection *Sec = dyn_cast>(Base)) + Sec->sortByOrderList(SectionsOrder); +} + template void Writer::forEachRelSec( std::function &, const typename ELFT::Shdr &)> @@ -720,6 +754,7 @@ for (InputSectionData *ID : F->getSections()) Add(cast>(ID)); + sortSectionsByOrder(OutputSections); sortInitFini(findSection(".init_array")); sortInitFini(findSection(".fini_array")); sortCtorsDtors(findSection(".ctors")); Index: test/ELF/symbol-ordering-file.s =================================================================== --- test/ELF/symbol-ordering-file.s +++ test/ELF/symbol-ordering-file.s @@ -0,0 +1,30 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t.out +# RUN: llvm-objdump -s %t.out| FileCheck %s --check-prefix=BEFORE + +# BEFORE: Contents of section .text: +# BEFORE-NEXT: 11000 11223344 + +# RUN: echo "_ccc _aaa _text _bbb" > %t_order.txt +# RUN: ld.lld --symbol-ordering-file %t_order.txt %t.o -o %t2.out +# RUN: llvm-objdump -s %t2.out| FileCheck %s --check-prefix=AFTER + +# AFTER: Contents of section .text: +# AFTER-NEXT: 11000 44220000 1133 + +.section .text,"ax" +_text: + .byte 0x11 + +.section .text.aaa,"ax" +_aaa: + .byte 0x22 + +.section .text.bbb,"ax" +_bbb: + .byte 0x33 + +.section .text.ccc,"ax" +_ccc: + .byte 0x44