diff options
Diffstat (limited to 'lld/ELF/Writer.cpp')
| -rw-r--r-- | lld/ELF/Writer.cpp | 244 |
1 files changed, 86 insertions, 158 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 6d97852aec43..07c5e2303374 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -91,67 +91,6 @@ private: }; } // anonymous namespace -static bool isSectionPrefix(StringRef prefix, StringRef name) { - return name.startswith(prefix) || name == prefix.drop_back(); -} - -StringRef elf::getOutputSectionName(const InputSectionBase *s) { - if (config->relocatable) - return s->name; - - // This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want - // to emit .rela.text.foo as .rela.text.bar for consistency (this is not - // technically required, but not doing it is odd). This code guarantees that. - if (auto *isec = dyn_cast<InputSection>(s)) { - if (InputSectionBase *rel = isec->getRelocatedSection()) { - OutputSection *out = rel->getOutputSection(); - if (s->type == SHT_RELA) - return saver.save(".rela" + out->name); - return saver.save(".rel" + out->name); - } - } - - // A BssSection created for a common symbol is identified as "COMMON" in - // linker scripts. It should go to .bss section. - if (s->name == "COMMON") - return ".bss"; - - if (script->hasSectionsCommand) - return s->name; - - // When no SECTIONS is specified, emulate GNU ld's internal linker scripts - // by grouping sections with certain prefixes. - - // GNU ld places text sections with prefix ".text.hot.", ".text.unknown.", - // ".text.unlikely.", ".text.startup." or ".text.exit." before others. - // We provide an option -z keep-text-section-prefix to group such sections - // into separate output sections. This is more flexible. See also - // sortISDBySectionOrder(). - // ".text.unknown" means the hotness of the section is unknown. When - // SampleFDO is used, if a function doesn't have sample, it could be very - // cold or it could be a new function never being sampled. Those functions - // will be kept in the ".text.unknown" section. - // ".text.split." holds symbols which are split out from functions in other - // input sections. For example, with -fsplit-machine-functions, placing the - // cold parts in .text.split instead of .text.unlikely mitigates against poor - // profile inaccuracy. Techniques such as hugepage remapping can make - // conservative decisions at the section granularity. - if (config->zKeepTextSectionPrefix) - for (StringRef v : {".text.hot.", ".text.unknown.", ".text.unlikely.", - ".text.startup.", ".text.exit.", ".text.split."}) - if (isSectionPrefix(v, s->name)) - return v.drop_back(); - - for (StringRef v : - {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", - ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", - ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) - if (isSectionPrefix(v, s->name)) - return v.drop_back(); - - return s->name; -} - static bool needsInterpSection() { return !config->relocatable && !config->shared && !config->dynamicLinker.empty() && script->needsInterpSection(); @@ -332,8 +271,8 @@ void elf::addReservedSymbols() { } static OutputSection *findSection(StringRef name, unsigned partition = 1) { - for (BaseCommand *base : script->sectionCommands) - if (auto *sec = dyn_cast<OutputSection>(base)) + for (SectionCommand *cmd : script->sectionCommands) + if (auto *sec = dyn_cast<OutputSection>(cmd)) if (sec->name == name && sec->partition == partition) return sec; return nullptr; @@ -342,7 +281,10 @@ static OutputSection *findSection(StringRef name, unsigned partition = 1) { template <class ELFT> void elf::createSyntheticSections() { // Initialize all pointers with NULL. This is needed because // you can call lld::elf::main more than once as a library. - memset(&Out::first, 0, sizeof(Out)); + Out::tlsPhdr = nullptr; + Out::preinitArray = nullptr; + Out::initArray = nullptr; + Out::finiArray = nullptr; // Add the .interp section first because it is not a SyntheticSection. // The removeUnusedSyntheticSections() function relies on the @@ -426,7 +368,6 @@ template <class ELFT> void elf::createSyntheticSections() { make<RelocationSection<ELFT>>(relaDynName, config->zCombreloc); if (config->hasDynSymTab) { - part.dynSymTab = make<SymbolTableSection<ELFT>>(*part.dynStrTab); add(part.dynSymTab); part.verSym = make<VersionTableSection>(); @@ -624,9 +565,8 @@ template <class ELFT> void Writer<ELFT>::run() { // --print-archive-stats=. Dump them before checkSections() because the files // may be useful in case checkSections() or openFile() fails, for example, due // to an erroneous file size. - writeMapFile(); + writeMapAndCref(); writeWhyExtract(); - writeCrossReferenceTable(); writeArchiveStats(); if (config->checkSections) @@ -787,16 +727,16 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { // referring to a section (that happens if the section is a synthetic one), we // don't create a section symbol for that section. template <class ELFT> void Writer<ELFT>::addSectionSymbols() { - for (BaseCommand *base : script->sectionCommands) { - auto *sec = dyn_cast<OutputSection>(base); + for (SectionCommand *cmd : script->sectionCommands) { + auto *sec = dyn_cast<OutputSection>(cmd); if (!sec) continue; - auto i = llvm::find_if(sec->sectionCommands, [](BaseCommand *base) { - if (auto *isd = dyn_cast<InputSectionDescription>(base)) + auto i = llvm::find_if(sec->commands, [](SectionCommand *cmd) { + if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) return !isd->sections.empty(); return false; }); - if (i == sec->sectionCommands.end()) + if (i == sec->commands.end()) continue; InputSectionBase *isec = cast<InputSectionDescription>(*i)->sections[0]; @@ -1053,7 +993,8 @@ static unsigned getSectionRank(const OutputSection *sec) { return rank; } -static bool compareSections(const BaseCommand *aCmd, const BaseCommand *bCmd) { +static bool compareSections(const SectionCommand *aCmd, + const SectionCommand *bCmd) { const OutputSection *a = cast<OutputSection>(aCmd); const OutputSection *b = cast<OutputSection>(bCmd); @@ -1210,7 +1151,7 @@ static int getRankProximityAux(OutputSection *a, OutputSection *b) { return countLeadingZeros(a->sortRank ^ b->sortRank); } -static int getRankProximity(OutputSection *a, BaseCommand *b) { +static int getRankProximity(OutputSection *a, SectionCommand *b) { auto *sec = dyn_cast<OutputSection>(b); return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1; } @@ -1229,7 +1170,7 @@ static int getRankProximity(OutputSection *a, BaseCommand *b) { // /* The RW PT_LOAD starts here*/ // rw_sec : { *(rw_sec) } // would mean that the RW PT_LOAD would become unaligned. -static bool shouldSkip(BaseCommand *cmd) { +static bool shouldSkip(SectionCommand *cmd) { if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) return assign->name != "."; return false; @@ -1238,13 +1179,13 @@ static bool shouldSkip(BaseCommand *cmd) { // We want to place orphan sections so that they share as much // characteristics with their neighbors as possible. For example, if // both are rw, or both are tls. -static std::vector<BaseCommand *>::iterator -findOrphanPos(std::vector<BaseCommand *>::iterator b, - std::vector<BaseCommand *>::iterator e) { +static std::vector<SectionCommand *>::iterator +findOrphanPos(std::vector<SectionCommand *>::iterator b, + std::vector<SectionCommand *>::iterator e) { OutputSection *sec = cast<OutputSection>(*e); // Find the first element that has as close a rank as possible. - auto i = std::max_element(b, e, [=](BaseCommand *a, BaseCommand *b) { + auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) { return getRankProximity(sec, a) < getRankProximity(sec, b); }); if (i == e) @@ -1273,7 +1214,7 @@ findOrphanPos(std::vector<BaseCommand *>::iterator b, break; } - auto isOutputSecWithInputSections = [](BaseCommand *cmd) { + auto isOutputSecWithInputSections = [](SectionCommand *cmd) { auto *os = dyn_cast<OutputSection>(cmd); return os && os->hasInputSections; }; @@ -1482,7 +1423,7 @@ static void sortSection(OutputSection *sec, // digit radix sort. The sections may be sorted stably again by a more // significant key. if (!order.empty()) - for (BaseCommand *b : sec->sectionCommands) + for (SectionCommand *b : sec->commands) if (auto *isd = dyn_cast<InputSectionDescription>(b)) sortISDBySectionOrder(isd, order); @@ -1499,8 +1440,8 @@ static void sortSection(OutputSection *sec, // addressable range of [.got, .got + 0xFFFC] for GOT-relative relocations. // To reduce the risk of relocation overflow, .toc contents are sorted so // that sections having smaller relocation offsets are at beginning of .toc - assert(sec->sectionCommands.size() == 1); - auto *isd = cast<InputSectionDescription>(sec->sectionCommands[0]); + assert(sec->commands.size() == 1); + auto *isd = cast<InputSectionDescription>(sec->commands[0]); llvm::stable_sort(isd->sections, [](const InputSection *a, const InputSection *b) -> bool { return a->file->ppc64SmallCodeModelTocRelocs && @@ -1515,8 +1456,8 @@ template <class ELFT> void Writer<ELFT>::sortInputSections() { // Build the order once since it is expensive. DenseMap<const InputSectionBase *, int> order = buildSectionOrder(); maybeShuffle(order); - for (BaseCommand *base : script->sectionCommands) - if (auto *sec = dyn_cast<OutputSection>(base)) + for (SectionCommand *cmd : script->sectionCommands) + if (auto *sec = dyn_cast<OutputSection>(cmd)) sortSection(sec, order); } @@ -1531,8 +1472,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() { sortInputSections(); - for (BaseCommand *base : script->sectionCommands) { - auto *os = dyn_cast<OutputSection>(base); + for (SectionCommand *cmd : script->sectionCommands) { + auto *os = dyn_cast<OutputSection>(cmd); if (!os) continue; os->sortRank = getSectionRank(os); @@ -1547,7 +1488,9 @@ template <class ELFT> void Writer<ELFT>::sortSections() { if (!script->hasSectionsCommand) { // We know that all the OutputSections are contiguous in this case. - auto isSection = [](BaseCommand *base) { return isa<OutputSection>(base); }; + auto isSection = [](SectionCommand *cmd) { + return isa<OutputSection>(cmd); + }; std::stable_sort( llvm::find_if(script->sectionCommands, isSection), llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(), @@ -1602,8 +1545,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() { auto i = script->sectionCommands.begin(); auto e = script->sectionCommands.end(); - auto nonScriptI = std::find_if(i, e, [](BaseCommand *base) { - if (auto *sec = dyn_cast<OutputSection>(base)) + auto nonScriptI = std::find_if(i, e, [](SectionCommand *cmd) { + if (auto *sec = dyn_cast<OutputSection>(cmd)) return sec->sectionIndex == UINT32_MAX; return false; }); @@ -1616,7 +1559,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() { // the script with ". = 0xabcd" and the expectation is that every section is // after that. auto firstSectionOrDotAssignment = - std::find_if(i, e, [](BaseCommand *cmd) { return !shouldSkip(cmd); }); + std::find_if(i, e, [](SectionCommand *cmd) { return !shouldSkip(cmd); }); if (firstSectionOrDotAssignment != e && isa<SymbolAssignment>(**firstSectionOrDotAssignment)) ++firstSectionOrDotAssignment; @@ -1629,7 +1572,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() { // As an optimization, find all sections with the same sort rank // and insert them with one rotate. unsigned rank = orphan->sortRank; - auto end = std::find_if(nonScriptI + 1, e, [=](BaseCommand *cmd) { + auto end = std::find_if(nonScriptI + 1, e, [=](SectionCommand *cmd) { return cast<OutputSection>(cmd)->sortRank != rank; }); std::rotate(pos, nonScriptI, end); @@ -1670,8 +1613,8 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { // Sorting is performed separately. std::vector<InputSection **> scriptSections; std::vector<InputSection *> sections; - for (BaseCommand *base : sec->sectionCommands) { - auto *isd = dyn_cast<InputSectionDescription>(base); + for (SectionCommand *cmd : sec->commands) { + auto *isd = dyn_cast<InputSectionDescription>(cmd); if (!isd) continue; bool hasLinkOrder = false; @@ -1774,7 +1717,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { // If addrExpr is set, the address may not be a multiple of the alignment. // Warn because this is error-prone. - for (BaseCommand *cmd : script->sectionCommands) + for (SectionCommand *cmd : script->sectionCommands) if (auto *os = dyn_cast<OutputSection>(cmd)) if (os->addr % os->alignment != 0) warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " + @@ -1892,36 +1835,30 @@ static void removeUnusedSyntheticSections() { }) .base(); - DenseSet<InputSectionDescription *> isdSet; - // Mark unused synthetic sections for deletion - auto end = std::stable_partition( - start, inputSections.end(), [&](InputSectionBase *s) { - SyntheticSection *ss = dyn_cast<SyntheticSection>(s); - OutputSection *os = ss->getParent(); - if (!os || ss->isNeeded()) - return true; - - // If we reach here, then ss is an unused synthetic section and we want - // to remove it from the corresponding input section description, and - // orphanSections. - for (BaseCommand *b : os->sectionCommands) - if (auto *isd = dyn_cast<InputSectionDescription>(b)) - isdSet.insert(isd); - - llvm::erase_if( - script->orphanSections, - [=](const InputSectionBase *isec) { return isec == ss; }); - - return false; + // Remove unused synthetic sections from inputSections; + DenseSet<InputSectionBase *> unused; + auto end = + std::remove_if(start, inputSections.end(), [&](InputSectionBase *s) { + auto *sec = cast<SyntheticSection>(s); + if (sec->getParent() && sec->isNeeded()) + return false; + unused.insert(sec); + return true; }); - - DenseSet<InputSectionBase *> unused(end, inputSections.end()); - for (auto *isd : isdSet) - llvm::erase_if(isd->sections, - [=](InputSection *isec) { return unused.count(isec); }); - - // Erase unused synthetic sections. inputSections.erase(end, inputSections.end()); + + // Remove unused synthetic sections from the corresponding input section + // description and orphanSections. + for (auto *sec : unused) + if (OutputSection *osec = cast<SyntheticSection>(sec)->getParent()) + for (SectionCommand *cmd : osec->commands) + if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) + llvm::erase_if(isd->sections, [&](InputSection *isec) { + return unused.count(isec); + }); + llvm::erase_if(script->orphanSections, [&](const InputSectionBase *sec) { + return unused.count(sec); + }); } // Create output section objects and add them to OutputSections. @@ -1935,8 +1872,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // addresses of each section by section name. Add such symbols. if (!config->relocatable) { addStartEndSymbols(); - for (BaseCommand *base : script->sectionCommands) - if (auto *sec = dyn_cast<OutputSection>(base)) + for (SectionCommand *cmd : script->sectionCommands) + if (auto *sec = dyn_cast<OutputSection>(cmd)) addStartStopSymbols(sec); } @@ -2087,11 +2024,14 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { sortSections(); - // Now that we have the final list, create a list of all the - // OutputSections for convenience. - for (BaseCommand *base : script->sectionCommands) - if (auto *sec = dyn_cast<OutputSection>(base)) - outputSections.push_back(sec); + // Create a list of OutputSections, assign sectionIndex, and populate + // in.shStrTab. + for (SectionCommand *cmd : script->sectionCommands) + if (auto *osec = dyn_cast<OutputSection>(cmd)) { + outputSections.push_back(osec); + osec->sectionIndex = outputSections.size(); + osec->shName = in.shStrTab->addString(osec->name); + } // Prefer command line supplied address over other constraints. for (OutputSection *sec : outputSections) { @@ -2113,12 +2053,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // to 1 to make __ehdr_start defined. The section number is not // particularly relevant. Out::elfHeader->sectionIndex = 1; - - for (size_t i = 0, e = outputSections.size(); i != e; ++i) { - OutputSection *sec = outputSections[i]; - sec->sectionIndex = i + 1; - sec->shName = in.shStrTab->addString(sec->name); - } + Out::elfHeader->size = sizeof(typename ELFT::Ehdr); // Binary and relocatable output does not have PHDRS. // The headers have to be created before finalize as that can influence the @@ -2608,17 +2543,6 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) { return first->offset + os->addr - first->addr; } -// Set an in-file position to a given section and returns the end position of -// the section. -static uint64_t setFileOffset(OutputSection *os, uint64_t off) { - off = computeFileOffset(os, off); - os->offset = off; - - if (os->type == SHT_NOBITS) - return off; - return off + os->size; -} - template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { // Compute the minimum LMA of all non-empty non-NOBITS sections as minAddr. auto needsOffset = [](OutputSection &sec) { @@ -2646,9 +2570,8 @@ static std::string rangeToString(uint64_t addr, uint64_t len) { // Assign file offsets to output sections. template <class ELFT> void Writer<ELFT>::assignFileOffsets() { - uint64_t off = 0; - off = setFileOffset(Out::elfHeader, off); - off = setFileOffset(Out::programHeaders, off); + Out::programHeaders->offset = Out::elfHeader->size; + uint64_t off = Out::elfHeader->size + Out::programHeaders->size; PhdrEntry *lastRX = nullptr; for (Partition &part : partitions) @@ -2661,18 +2584,23 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { for (OutputSection *sec : outputSections) { if (!(sec->flags & SHF_ALLOC)) continue; - off = setFileOffset(sec, off); + off = computeFileOffset(sec, off); + sec->offset = off; + if (sec->type != SHT_NOBITS) + off += sec->size; // If this is a last section of the last executable segment and that // segment is the last loadable segment, align the offset of the // following section to avoid loading non-segments parts of the file. if (config->zSeparate != SeparateSegmentKind::None && lastRX && lastRX->lastSec == sec) - off = alignTo(off, config->commonPageSize); + off = alignTo(off, config->maxPageSize); } - for (OutputSection *sec : outputSections) - if (!(sec->flags & SHF_ALLOC)) - off = setFileOffset(sec, off); + for (OutputSection *osec : outputSections) + if (!(osec->flags & SHF_ALLOC)) { + osec->offset = alignTo(off, osec->alignment); + off = osec->offset + osec->size; + } sectionHeaderOff = alignTo(off, config->wordsize); fileSize = sectionHeaderOff + (outputSections.size() + 1) * sizeof(Elf_Shdr); @@ -2946,9 +2874,9 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() { for (PhdrEntry *p : part.phdrs) if (p->p_type == PT_LOAD && (p->p_flags & PF_X)) fillTrap(Out::bufferStart + alignDown(p->firstSec->offset + p->p_filesz, - config->commonPageSize), + config->maxPageSize), Out::bufferStart + alignTo(p->firstSec->offset + p->p_filesz, - config->commonPageSize)); + config->maxPageSize)); // Round up the file size of the last segment to the page boundary iff it is // an executable segment to ensure that other tools don't accidentally @@ -2960,7 +2888,7 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() { if (last && (last->p_flags & PF_X)) last->p_memsz = last->p_filesz = - alignTo(last->p_filesz, config->commonPageSize); + alignTo(last->p_filesz, config->maxPageSize); } } |
