Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -59,15 +59,16 @@ }; void copyLocalSymbols(); - void addReservedSymbols(); + void addReservedSymbols(ArrayRef *> Sections); void createSections(); + void fillSymTables(); void addPredefinedSections(); bool needsGot(); template void scanRelocs(InputSectionBase &C, ArrayRef Rels); - void scanRelocs(InputSection &C); + void scanRelocs(); void scanRelocs(InputSectionBase &S, const Elf_Shdr &RelSec); void createPhdrs(); void assignAddresses(); @@ -93,7 +94,7 @@ ArrayRef Rels); void ensureBss(); - void addCommonSymbols(std::vector &Syms); + void addCommonSymbols(); void addCopyRelSymbol(SharedSymbol *Sym); std::unique_ptr Buffer; @@ -210,7 +211,6 @@ template void Writer::run() { if (!Config->DiscardAll) copyLocalSymbols(); - addReservedSymbols(); createSections(); if (HasError) return; @@ -719,9 +719,29 @@ scanRelocsForThunks(File, Rels); } -template void Writer::scanRelocs(InputSection &C) { - for (const Elf_Shdr *RelSec : C.RelocSections) - scanRelocs(C, *RelSec); +template void Writer::scanRelocs() { + // Scan relocations. This must be done after every symbol is declared so that + // we can correctly decide if a dynamic relocation is needed. + // Check size() each time to guard against .bss being created. + for (unsigned I = 0; I < OutputSections.size(); ++I) { + OutputSectionBase *Sec = OutputSections[I]; + Sec->forEachInputSection([&](InputSectionBase *S) { + if (auto *IS = dyn_cast>(S)) { + // Set OutSecOff so that scanRelocs can use it. + uintX_t Off = alignTo(Sec->getSize(), S->Align); + IS->OutSecOff = Off; + + for (const Elf_Shdr *RelSec : IS->RelocSections) + scanRelocs(*IS, *RelSec); + + // Now that scan relocs possibly changed the size, update the offset. + Sec->setSize(Off + S->getSize()); + } else if (auto *EH = dyn_cast>(S)) { + if (EH->RelocSection) + scanRelocs(*EH, *EH->RelocSection); + } + }); + } } template @@ -948,8 +968,12 @@ // Until this function is called, common symbols do not belong to any section. // This function adds them to end of BSS section. -template -void Writer::addCommonSymbols(std::vector &Syms) { +template void Writer::addCommonSymbols() { + std::vector Syms; + for (Symbol *S : Symtab.getSymbols()) + if (auto *C = dyn_cast(S->Body)) + Syms.push_back(C); + if (Syms.empty()) return; @@ -1154,7 +1178,9 @@ // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. -template void Writer::addReservedSymbols() { +template +void Writer::addReservedSymbols( + ArrayRef *> Sections) { if (Config->EMachine == EM_MIPS) { // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer // so that it points to an absolute address which is relative to GOT. @@ -1213,6 +1239,25 @@ Define("_end", ElfSym::End, ElfSym::End2); Define("_etext", ElfSym::Etext, ElfSym::Etext2); Define("_edata", ElfSym::Edata, ElfSym::Edata2); + + // 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 (OutputSectionBase *Sec : Sections) + addStartStopSymbols(Sec); + } + + // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. + // It should be okay as no one seems to care about the type. + // Even the author of gold doesn't remember why gold behaves that way. + // https://sourceware.org/ml/binutils/2002-03/msg00360.html + if (isOutputDynamic()) + Symtab.addSynthetic("_DYNAMIC", *Out::Dynamic, 0); + + // Define __rel[a]_iplt_{start,end} symbols if needed. + addRelIpltSymbols(); } // Sort input sections by section name suffixes for @@ -1228,19 +1273,32 @@ reinterpret_cast *>(S)->sortCtorsDtors(); } -// Create output section objects and add them to OutputSections. -template void Writer::createSections() { - // Add .interp first because some loaders want to see that section - // on the first page of the executable file when loaded into memory. - if (needsInterpSection()) - OutputSections.push_back(Out::Interp); +template void Writer::fillSymTables() { + // Now that we have defined all possible symbols including linker- + // synthesized ones. Visit all symbols to give the finishing touches. + for (Symbol *S : Symtab.getSymbols()) { + SymbolBody *Body = S->Body; - // A core file does not usually contain unmodified segments except - // the first page of the executable. Add the build ID section now - // so that the section is included in the first page. - if (Out::BuildId) - OutputSections.push_back(Out::BuildId); + // Set "used" bit for --as-needed. + if (S->IsUsedInRegularObj && !S->isWeak()) + if (auto *SS = dyn_cast>(Body)) + SS->File->IsUsed = true; + + if (Body->isUndefined() && !S->isWeak()) + reportUndefined(Symtab, Body); + + if (!includeInSymtab(*Body)) + continue; + if (Out::SymTab) + Out::SymTab->addSymbol(Body); + + if (isOutputDynamic() && S->includeInDynsym()) + Out::DynSymTab->addSymbol(Body); + } +} +// Create output section objects and add them to OutputSections. +template void Writer::createSections() { // Create output sections for input object file sections. std::vector *> RegularSections; OutputSectionFactory Factory; @@ -1284,81 +1342,19 @@ sortCtorsDtors(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); sortCtorsDtors(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); - // 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 (OutputSectionBase *Sec : RegularSections) - addStartStopSymbols(Sec); - } - - // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. - // It should be okay as no one seems to care about the type. - // Even the author of gold doesn't remember why gold behaves that way. - // https://sourceware.org/ml/binutils/2002-03/msg00360.html - if (isOutputDynamic()) - Symtab.addSynthetic("_DYNAMIC", *Out::Dynamic, 0); - - // Define __rel[a]_iplt_{start,end} symbols if needed. - addRelIpltSymbols(); + addReservedSymbols(RegularSections); if (Out::EhFrameHdr->Sec) Out::EhFrameHdr->Sec->finalize(); - // Scan relocations. This must be done after every symbol is declared so that - // we can correctly decide if a dynamic relocation is needed. - // Check size() each time to guard against .bss being created. - for (unsigned I = 0; I < OutputSections.size(); ++I) { - OutputSectionBase *Sec = OutputSections[I]; - Sec->forEachInputSection([&](InputSectionBase *S) { - if (auto *IS = dyn_cast>(S)) { - // Set OutSecOff so that scanRelocs can use it. - uintX_t Off = alignTo(Sec->getSize(), S->Align); - IS->OutSecOff = Off; - - scanRelocs(*IS); - - // Now that scan relocs possibly changed the size, update the offset. - Sec->setSize(Off + S->getSize()); - } else if (auto *EH = dyn_cast>(S)) { - if (EH->RelocSection) - scanRelocs(*EH, *EH->RelocSection); - } - }); - } - - // Now that we have defined all possible symbols including linker- - // synthesized ones. Visit all symbols to give the finishing touches. - std::vector CommonSymbols; - for (Symbol *S : Symtab.getSymbols()) { - SymbolBody *Body = S->Body; - - // Set "used" bit for --as-needed. - if (S->IsUsedInRegularObj && !S->isWeak()) - if (auto *SS = dyn_cast>(Body)) - SS->File->IsUsed = true; - - if (Body->isUndefined() && !S->isWeak()) - reportUndefined(Symtab, Body); - - if (auto *C = dyn_cast(Body)) - CommonSymbols.push_back(C); - - if (!includeInSymtab(*Body)) - continue; - if (Out::SymTab) - Out::SymTab->addSymbol(Body); - - if (isOutputDynamic() && S->includeInDynsym()) - Out::DynSymTab->addSymbol(Body); - } + scanRelocs(); + fillSymTables(); // Do not proceed if there was an undefined symbol. if (HasError) return; - addCommonSymbols(CommonSymbols); + addCommonSymbols(); // So far we have added sections from input object files. // This function adds linker-created Out::* sections. @@ -1412,6 +1408,18 @@ OutputSections.push_back(C); }; + // Add .interp at first because some loaders want to see that section + // on the first page of the executable file when loaded into memory. + auto I = OutputSections.begin(); + if (needsInterpSection()) + I = OutputSections.insert(I, Out::Interp); + + // A core file does not usually contain unmodified segments except + // the first page of the executable. Add the build ID section now + // so that the section is included in the first page. + if (Out::BuildId) + OutputSections.insert(I, Out::BuildId); + // This order is not the same as the final output order // because we sort the sections using their attributes below. Add(Out::SymTab);