summaryrefslogtreecommitdiff
path: root/lld/ELF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Writer.cpp')
-rw-r--r--lld/ELF/Writer.cpp244
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);
}
}