diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 86 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 4 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 82 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 3 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 42 |
5 files changed, 107 insertions, 110 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index c5276221fbe..f66bdac07cd 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -901,6 +901,92 @@ OutputSectionCommand *LinkerScript::getCmd(OutputSection *Sec) const { return I->second; } +void OutputSectionCommand::sort(std::function<int(InputSectionBase *S)> Order) { + typedef std::pair<unsigned, InputSection *> Pair; + auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; + + std::vector<Pair> V; + assert(Commands.size() == 1); + auto *ISD = cast<InputSectionDescription>(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); +} + +// Returns true if S matches /Filename.?\.o$/. +static bool isCrtBeginEnd(StringRef S, StringRef Filename) { + if (!S.endswith(".o")) + return false; + S = S.drop_back(2); + if (S.endswith(Filename)) + return true; + return !S.empty() && S.drop_back().endswith(Filename); +} + +static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); } +static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); } + +// .ctors and .dtors are sorted by this priority from highest to lowest. +// +// 1. The section was contained in crtbegin (crtbegin contains +// some sentinel value in its .ctors and .dtors so that the runtime +// can find the beginning of the sections.) +// +// 2. The section has an optional priority value in the form of ".ctors.N" +// or ".dtors.N" where N is a number. Unlike .{init,fini}_array, +// they are compared as string rather than number. +// +// 3. The section is just ".ctors" or ".dtors". +// +// 4. The section was contained in crtend, which contains an end marker. +// +// In an ideal world, we don't need this function because .init_array and +// .ctors are duplicate features (and .init_array is newer.) However, there +// are too many real-world use cases of .ctors, so we had no choice to +// support that with this rather ad-hoc semantics. +static bool compCtors(const InputSection *A, const InputSection *B) { + bool BeginA = isCrtbegin(A->File->getName()); + bool BeginB = isCrtbegin(B->File->getName()); + if (BeginA != BeginB) + return BeginA; + bool EndA = isCrtend(A->File->getName()); + bool EndB = isCrtend(B->File->getName()); + if (EndA != EndB) + return EndB; + StringRef X = A->Name; + StringRef Y = B->Name; + assert(X.startswith(".ctors") || X.startswith(".dtors")); + assert(Y.startswith(".ctors") || Y.startswith(".dtors")); + X = X.substr(6); + Y = Y.substr(6); + if (X.empty() && Y.empty()) + return false; + return X < Y; +} + +// Sorts input sections by the special rules for .ctors and .dtors. +// Unfortunately, the rules are different from the one for .{init,fini}_array. +// Read the comment above. +void OutputSectionCommand::sortCtorsDtors() { + assert(Commands.size() == 1); + auto *ISD = cast<InputSectionDescription>(Commands[0]); + std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors); +} + +// 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 +// because the compiler keeps the original initialization order in a +// translation unit and we need to respect that. +// For more detail, read the section of the GCC's manual about init_priority. +void OutputSectionCommand::sortInitFini() { + // Sort sections by priority. + sort([](InputSectionBase *S) { return getPriority(S->Name); }); +} + uint32_t OutputSectionCommand::getFiller() { if (Filler) return *Filler; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 3be7d2d087d..21543e4507d 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -140,6 +140,10 @@ struct OutputSectionCommand : BaseCommand { template <class ELFT> void writeTo(uint8_t *Buf); template <class ELFT> void maybeCompress(); uint32_t getFiller(); + + void sort(std::function<int(InputSectionBase *S)> Order); + void sortInitFini(); + void sortCtorsDtors(); }; // This struct represents one section match pattern in SECTIONS() command. diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index f40ecbe4675..06aaad7785f 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -101,88 +101,6 @@ void OutputSection::addSection(InputSection *S) { this->Entsize = std::max(this->Entsize, S->Entsize); } -void OutputSection::sort(std::function<int(InputSectionBase *S)> Order) { - typedef std::pair<unsigned, InputSection *> Pair; - auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; - - std::vector<Pair> V; - for (InputSection *S : Sections) - V.push_back({Order(S), 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 -// because the compiler keeps the original initialization order in a -// translation unit and we need to respect that. -// For more detail, read the section of the GCC's manual about init_priority. -void OutputSection::sortInitFini() { - // Sort sections by priority. - sort([](InputSectionBase *S) { return getPriority(S->Name); }); -} - -// Returns true if S matches /Filename.?\.o$/. -static bool isCrtBeginEnd(StringRef S, StringRef Filename) { - if (!S.endswith(".o")) - return false; - S = S.drop_back(2); - if (S.endswith(Filename)) - return true; - return !S.empty() && S.drop_back().endswith(Filename); -} - -static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); } -static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); } - -// .ctors and .dtors are sorted by this priority from highest to lowest. -// -// 1. The section was contained in crtbegin (crtbegin contains -// some sentinel value in its .ctors and .dtors so that the runtime -// can find the beginning of the sections.) -// -// 2. The section has an optional priority value in the form of ".ctors.N" -// or ".dtors.N" where N is a number. Unlike .{init,fini}_array, -// they are compared as string rather than number. -// -// 3. The section is just ".ctors" or ".dtors". -// -// 4. The section was contained in crtend, which contains an end marker. -// -// In an ideal world, we don't need this function because .init_array and -// .ctors are duplicate features (and .init_array is newer.) However, there -// are too many real-world use cases of .ctors, so we had no choice to -// support that with this rather ad-hoc semantics. -static bool compCtors(const InputSection *A, const InputSection *B) { - bool BeginA = isCrtbegin(A->File->getName()); - bool BeginB = isCrtbegin(B->File->getName()); - if (BeginA != BeginB) - return BeginA; - bool EndA = isCrtend(A->File->getName()); - bool EndB = isCrtend(B->File->getName()); - if (EndA != EndB) - return EndB; - StringRef X = A->Name; - StringRef Y = B->Name; - assert(X.startswith(".ctors") || X.startswith(".dtors")); - assert(Y.startswith(".ctors") || Y.startswith(".dtors")); - X = X.substr(6); - Y = Y.substr(6); - if (X.empty() && Y.empty()) - return false; - return X < Y; -} - -// Sorts input sections by the special rules for .ctors and .dtors. -// Unfortunately, the rules are different from the one for .{init,fini}_array. -// Read the comment above. -void OutputSection::sortCtorsDtors() { - std::stable_sort(Sections.begin(), Sections.end(), compCtors); -} - static SectionKey createKey(InputSectionBase *C, StringRef OutsecName) { // The ELF spec just says // ---------------------------------------------------------------- diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 9e856c20d30..2ecb6c29969 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -80,9 +80,6 @@ public: uint32_t ShName = 0; void addSection(InputSection *S); - void sort(std::function<int(InputSectionBase *S)> Order); - void sortInitFini(); - void sortCtorsDtors(); std::vector<InputSection *> Sections; // Used for implementation of --compress-debug-sections option. diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index df883ef98ba..6828dba1ea6 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -79,7 +79,6 @@ private: void addStartEndSymbols(); void addStartStopSymbols(OutputSection *Sec); uint64_t getEntryAddr(); - OutputSection *findSection(StringRef Name); OutputSection *findSectionInScript(StringRef Name); OutputSectionCommand *findSectionCommand(StringRef Name); @@ -186,9 +185,8 @@ template <class ELFT> void Writer<ELFT>::run() { // output sections by default rules. We still need to give the // linker script a chance to run, because it might contain // non-SECTIONS commands such as ASSERT. - createSections(); Script->processCommands(Factory); - Script->fabricateDefaultCommands(); + createSections(); } clearOutputSections(); @@ -870,20 +868,19 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() { // Sort input sections by section name suffixes for // __attribute__((init_priority(N))). -static void sortInitFini(OutputSection *S) { - if (S) - S->sortInitFini(); +static void sortInitFini(OutputSectionCommand *Cmd) { + if (Cmd) + Cmd->sortInitFini(); } // Sort input sections by the special rule for .ctors and .dtors. -static void sortCtorsDtors(OutputSection *S) { - if (S) - S->sortCtorsDtors(); +static void sortCtorsDtors(OutputSectionCommand *Cmd) { + if (Cmd) + Cmd->sortCtorsDtors(); } // Sort input sections using the list provided by --symbol-ordering-file. -template <class ELFT> -static void sortBySymbolsOrder(ArrayRef<OutputSection *> OutputSections) { +template <class ELFT> static void sortBySymbolsOrder() { if (Config->SymbolOrderingFile.empty()) return; @@ -908,8 +905,9 @@ static void sortBySymbolsOrder(ArrayRef<OutputSection *> OutputSections) { } // Sort sections by priority. - for (OutputSection *Sec : OutputSections) - Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); }); + for (BaseCommand *Base : Script->Opt.Commands) + if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) + Cmd->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); }); } template <class ELFT> @@ -939,11 +937,12 @@ template <class ELFT> void Writer<ELFT>::createSections() { if (IS) Factory.addInputSec(IS, getOutputSectionName(IS->Name)); - sortBySymbolsOrder<ELFT>(OutputSections); - sortInitFini(findSection(".init_array")); - sortInitFini(findSection(".fini_array")); - sortCtorsDtors(findSection(".ctors")); - sortCtorsDtors(findSection(".dtors")); + Script->fabricateDefaultCommands(); + sortBySymbolsOrder<ELFT>(); + sortInitFini(findSectionCommand(".init_array")); + sortInitFini(findSectionCommand(".fini_array")); + sortCtorsDtors(findSectionCommand(".ctors")); + sortCtorsDtors(findSectionCommand(".dtors")); } // We want to find how similar two ranks are. @@ -1398,13 +1397,6 @@ template <class ELFT> OutputSection *Writer<ELFT>::findSectionInScript(StringRef return nullptr; } -template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) { - for (OutputSection *Sec : OutputSections) - if (Sec->Name == Name) - return Sec; - return nullptr; -} - static bool needsPtLoad(OutputSection *Sec) { if (!(Sec->Flags & SHF_ALLOC)) return false; |