diff options
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r-- | ELF/Writer.cpp | 167 |
1 files changed, 89 insertions, 78 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 080d8e787301..bf43ee5c5f91 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -73,13 +73,12 @@ private: std::unique_ptr<FileOutputBuffer> Buffer; - OutputSectionFactory Factory{OutputSections}; + OutputSectionFactory Factory; void addRelIpltSymbols(); void addStartEndSymbols(); void addStartStopSymbols(OutputSection *Sec); uint64_t getEntryAddr(); - OutputSection *findSection(StringRef Name); OutputSection *findSectionInScript(StringRef Name); OutputSectionCommand *findSectionCommand(StringRef Name); @@ -152,10 +151,6 @@ template <class ELFT> static void combineEhFrameSections() { } template <class ELFT> void Writer<ELFT>::clearOutputSections() { - if (Script->Opt.HasSections) - Script->createOrphanCommands(); - else - Script->fabricateDefaultCommands(); // Clear the OutputSections to make sure it is not used anymore. Any // code from this point on should be using the linker script // commands. @@ -190,9 +185,10 @@ 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); + createSections(); } + clearOutputSections(); if (Config->Discard != DiscardPolicy::All) copyLocalSymbols(); @@ -218,7 +214,8 @@ template <class ELFT> void Writer<ELFT>::run() { OutputSectionCommands.begin(), OutputSectionCommands.end(), [](OutputSectionCommand *Cmd) { Cmd->maybeCompress<ELFT>(); }); - Script->assignAddresses(Phdrs); + Script->assignAddresses(); + Script->allocateHeaders(Phdrs); // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a // 0 sized region. This has to be done late since only after assignAddresses @@ -383,7 +380,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { Add(InX::IgotPlt); if (Config->GdbIndex) { - InX::GdbIndex = make<GdbIndexSection>(); + InX::GdbIndex = createGdbIndex<ELFT>(); Add(InX::GdbIndex); } @@ -499,11 +496,18 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { template <class ELFT> void Writer<ELFT>::addSectionSymbols() { // Create one STT_SECTION symbol for each output section we might // have a relocation with. - for (OutputSection *Sec : OutputSections) { - if (Sec->Sections.empty()) + for (BaseCommand *Base : Script->Opt.Commands) { + auto *Cmd = dyn_cast<OutputSectionCommand>(Base); + if (!Cmd) continue; - - InputSection *IS = Sec->Sections[0]; + auto I = llvm::find_if(Cmd->Commands, [](BaseCommand *Base) { + if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) + return !ISD->Sections.empty(); + return false; + }); + if (I == Cmd->Commands.end()) + continue; + InputSection *IS = cast<InputSectionDescription>(*I)->Sections[0]; if (isa<SyntheticSection>(IS) || IS->Type == SHT_REL || IS->Type == SHT_RELA) continue; @@ -864,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) - reinterpret_cast<OutputSection *>(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) - reinterpret_cast<OutputSection *>(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; @@ -902,9 +905,9 @@ static void sortBySymbolsOrder(ArrayRef<OutputSection *> OutputSections) { } // Sort sections by priority. - for (OutputSection *Base : OutputSections) - if (auto *Sec = dyn_cast<OutputSection>(Base)) - 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> @@ -934,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. @@ -1132,7 +1136,7 @@ static void applySynthetic(const std::vector<SyntheticSection *> &Sections, // to make them visible from linkescript side. But not all sections are always // required to be in output. For example we don't need dynamic section content // sometimes. This function filters out such unused sections from the output. -static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) { +static void removeUnusedSyntheticSections() { // All input synthetic sections that can be empty are placed after // all regular ones. We iterate over them all and exit at first // non-synthetic. @@ -1145,29 +1149,53 @@ static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) { continue; if ((SS == InX::Got || SS == InX::MipsGot) && ElfSym::GlobalOffsetTable) continue; - OS->Sections.erase(std::find(OS->Sections.begin(), OS->Sections.end(), SS)); - SS->Live = false; + + OutputSectionCommand *Cmd = Script->getCmd(OS); + std::vector<BaseCommand *>::iterator Empty = Cmd->Commands.end(); + for (auto I = Cmd->Commands.begin(), E = Cmd->Commands.end(); I != E; ++I) { + BaseCommand *B = *I; + if (auto *ISD = dyn_cast<InputSectionDescription>(B)) { + auto P = std::find(ISD->Sections.begin(), ISD->Sections.end(), SS); + if (P != ISD->Sections.end()) + ISD->Sections.erase(P); + if (ISD->Sections.empty()) + Empty = I; + } + } + if (Empty != Cmd->Commands.end()) + Cmd->Commands.erase(Empty); + // If there are no other sections in the output section, remove it from the // output. - if (OS->Sections.empty()) - V.erase(std::find(V.begin(), V.end(), OS)); + if (Cmd->Commands.empty()) { + // Also remove script commands matching the output section. + auto &Cmds = Script->Opt.Commands; + auto I = std::remove_if(Cmds.begin(), Cmds.end(), [&](BaseCommand *Cmd) { + if (auto *OSCmd = dyn_cast<OutputSectionCommand>(Cmd)) + return OSCmd->Sec == OS; + return false; + }); + Cmds.erase(I, Cmds.end()); + } } } // Create output section objects and add them to OutputSections. template <class ELFT> void Writer<ELFT>::finalizeSections() { - Out::DebugInfo = findSection(".debug_info"); - Out::PreinitArray = findSection(".preinit_array"); - Out::InitArray = findSection(".init_array"); - Out::FiniArray = findSection(".fini_array"); + Out::DebugInfo = findSectionInScript(".debug_info"); + Out::PreinitArray = findSectionInScript(".preinit_array"); + Out::InitArray = findSectionInScript(".init_array"); + Out::FiniArray = findSectionInScript(".fini_array"); // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop // symbols for sections, so that the runtime can get the start and end // addresses of each section by section name. Add such symbols. if (!Config->Relocatable) { addStartEndSymbols(); - for (OutputSection *Sec : OutputSections) - addStartStopSymbols(Sec); + for (BaseCommand *Base : Script->Opt.Commands) + if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) + if (Cmd->Sec) + addStartStopSymbols(Cmd->Sec); } // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. @@ -1218,9 +1246,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { return; addPredefinedSections(); - removeUnusedSyntheticSections(OutputSections); + removeUnusedSyntheticSections(); - clearOutputSections(); sortSections(); // Now that we have the final list, create a list of all the @@ -1257,12 +1284,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); } - // Compute the size of .rela.dyn and .rela.plt early since we need - // them to populate .dynamic. - for (SyntheticSection *SS : {In<ELFT>::RelaDyn, In<ELFT>::RelaPlt}) - if (SS->getParent() && !SS->empty()) - SS->getParent()->assignOffsets(); - // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. applySynthetic({InX::DynSymTab, InX::Bss, InX::BssRelRo, @@ -1286,6 +1307,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // are out of range. This will need to turn into a loop that converges // when no more Thunks are added ThunkCreator TC; + Script->assignAddresses(); if (TC.createThunks(OutputSectionCommands)) { applySynthetic({InX::MipsGot}, [](SyntheticSection *SS) { SS->updateAllocSize(); }); @@ -1308,21 +1330,18 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { template <class ELFT> void Writer<ELFT>::addPredefinedSections() { // ARM ABI requires .ARM.exidx to be terminated by some piece of data. // We have the terminater synthetic section class. Add that at the end. - auto *OS = dyn_cast_or_null<OutputSection>(findSection(".ARM.exidx")); - if (!OS || OS->Sections.empty() || Config->Relocatable) + OutputSectionCommand *Cmd = findSectionCommand(".ARM.exidx"); + if (!Cmd || Cmd->Commands.empty() || Config->Relocatable) return; auto *Sentinel = make<ARMExidxSentinelSection>(); - OS->addSection(Sentinel); - // If there are linker script commands existing at this point then add the - // sentinel to the last of these too. - if (OutputSectionCommand *C = Script->getCmd(OS)) { - auto ISD = std::find_if(C->Commands.rbegin(), C->Commands.rend(), - [](const BaseCommand *Base) { - return isa<InputSectionDescription>(Base); - }); - cast<InputSectionDescription>(*ISD)->Sections.push_back(Sentinel); - } + Cmd->Sec->addSection(Sentinel); + // Add the sentinel to the last of these too. + auto ISD = std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(), + [](const BaseCommand *Base) { + return isa<InputSectionDescription>(Base); + }); + cast<InputSectionDescription>(*ISD)->Sections.push_back(Sentinel); } // The linker is expected to define SECNAME_start and SECNAME_end @@ -1346,7 +1365,7 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { Define("__init_array_start", "__init_array_end", Out::InitArray); Define("__fini_array_start", "__fini_array_end", Out::FiniArray); - if (OutputSection *Sec = findSection(".ARM.exidx")) + if (OutputSection *Sec = findSectionInScript(".ARM.exidx")) Define("__exidx_start", "__exidx_end", Sec); } @@ -1366,9 +1385,10 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) { template <class ELFT> OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) { - for (OutputSectionCommand *Cmd : OutputSectionCommands) - if (Cmd->Name == Name) - return Cmd; + for (BaseCommand *Base : Script->Opt.Commands) + if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) + if (Cmd->Name == Name) + return Cmd; return nullptr; } @@ -1378,13 +1398,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; @@ -1446,7 +1459,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { // different flags or is loaded at a discontiguous address using AT linker // script command. uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); - if (Script->hasLMA(Sec) || Flags != NewFlags) { + if (Cmd->LMAExpr || Flags != NewFlags) { Load = AddHdr(PT_LOAD, NewFlags); Flags = NewFlags; } @@ -1514,7 +1527,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { for (OutputSectionCommand *Cmd : OutputSectionCommands) { OutputSection *Sec = Cmd->Sec; if (Sec->Type == SHT_NOTE) { - if (!Note || Script->hasLMA(Sec)) + if (!Note || Cmd->LMAExpr) Note = AddHdr(PT_NOTE, PF_R); Note->add(Sec); } else { @@ -1528,11 +1541,9 @@ template <class ELFT> void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) { if (Config->EMachine != EM_ARM) return; - auto I = - std::find_if(OutputSectionCommands.begin(), OutputSectionCommands.end(), - [](OutputSectionCommand *Cmd) { - return Cmd->Sec->Type == SHT_ARM_EXIDX; - }); + auto I = llvm::find_if(OutputSectionCommands, [](OutputSectionCommand *Cmd) { + return Cmd->Sec->Type == SHT_ARM_EXIDX; + }); if (I == OutputSectionCommands.end()) return; |