aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lld/ELF/Writer.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-03-20 11:40:34 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-05-14 11:43:05 +0000
commit349cc55c9796c4596a5b9904cd3281af295f878f (patch)
tree410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/lld/ELF/Writer.cpp
parentcb2ae6163174b90e999326ecec3699ee093a5d43 (diff)
parentc0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff)
Merge llvm-project main llvmorg-14-init-10186-gff7f2cfa959b
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-14-init-10186-gff7f2cfa959b. PR: 261742 MFC after: 2 weeks
Diffstat (limited to 'contrib/llvm-project/lld/ELF/Writer.cpp')
-rw-r--r--contrib/llvm-project/lld/ELF/Writer.cpp119
1 files changed, 53 insertions, 66 deletions
diff --git a/contrib/llvm-project/lld/ELF/Writer.cpp b/contrib/llvm-project/lld/ELF/Writer.cpp
index 321599b0055a..6d97852aec43 100644
--- a/contrib/llvm-project/lld/ELF/Writer.cpp
+++ b/contrib/llvm-project/lld/ELF/Writer.cpp
@@ -221,18 +221,17 @@ void elf::combineEhSections() {
}
}
- std::vector<InputSectionBase *> &v = inputSections;
- v.erase(std::remove(v.begin(), v.end(), nullptr), v.end());
+ llvm::erase_value(inputSections, nullptr);
}
static Defined *addOptionalRegular(StringRef name, SectionBase *sec,
- uint64_t val, uint8_t stOther = STV_HIDDEN,
- uint8_t binding = STB_GLOBAL) {
+ uint64_t val, uint8_t stOther = STV_HIDDEN) {
Symbol *s = symtab->find(name);
if (!s || s->isDefined())
return nullptr;
- s->resolve(Defined{/*file=*/nullptr, name, binding, stOther, STT_NOTYPE, val,
+ s->resolve(Defined{/*file=*/nullptr, name, STB_GLOBAL, stOther, STT_NOTYPE,
+ val,
/*size=*/0, sec});
return cast<Defined>(s);
}
@@ -595,9 +594,8 @@ template <class ELFT> void Writer<ELFT>::run() {
if (errorCount())
return;
- // If -compressed-debug-sections is specified, we need to compress
- // .debug_* sections. Do it right now because it changes the size of
- // output sections.
+ // If --compressed-debug-sections is specified, compress .debug_* sections.
+ // Do it right now because it changes the size of output sections.
for (OutputSection *sec : outputSections)
sec->maybeCompress<ELFT>();
@@ -622,11 +620,12 @@ template <class ELFT> void Writer<ELFT>::run() {
for (OutputSection *sec : outputSections)
sec->addr = 0;
- // Handle --print-map(-M)/--Map, --cref and --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.
+ // Handle --print-map(-M)/--Map, --why-extract=, --cref and
+ // --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();
+ writeWhyExtract();
writeCrossReferenceTable();
writeArchiveStats();
@@ -727,16 +726,11 @@ static bool shouldKeepInSymtab(const Defined &sym) {
// * --discard-locals is used.
// * The symbol is in a SHF_MERGE section, which is normally the reason for
// the assembler keeping the .L symbol.
- StringRef name = sym.getName();
- bool isLocal = name.startswith(".L") || name.empty();
- if (!isLocal)
- return true;
-
- if (config->discard == DiscardPolicy::Locals)
+ if (sym.getName().startswith(".L") &&
+ (config->discard == DiscardPolicy::Locals ||
+ (sym.section && (sym.section->flags & SHF_MERGE))))
return false;
-
- SectionBase *sec = sym.section;
- return !sec || !(sec->flags & SHF_MERGE);
+ return true;
}
static bool includeInSymtab(const Symbol &b) {
@@ -812,7 +806,7 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
// Unlike other synthetic sections, mergeable output sections contain data
// copied from input sections, and there may be a relocation pointing to its
- // contents if -r or -emit-reloc are given.
+ // contents if -r or --emit-reloc is given.
if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE))
continue;
@@ -1097,11 +1091,11 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
// sure that .rela.plt exists in output.
ElfSym::relaIpltStart = addOptionalRegular(
config->isRela ? "__rela_iplt_start" : "__rel_iplt_start",
- Out::elfHeader, 0, STV_HIDDEN, STB_WEAK);
+ Out::elfHeader, 0, STV_HIDDEN);
ElfSym::relaIpltEnd = addOptionalRegular(
config->isRela ? "__rela_iplt_end" : "__rel_iplt_end",
- Out::elfHeader, 0, STV_HIDDEN, STB_WEAK);
+ Out::elfHeader, 0, STV_HIDDEN);
}
template <class ELFT>
@@ -1255,15 +1249,27 @@ findOrphanPos(std::vector<BaseCommand *>::iterator b,
});
if (i == e)
return e;
+ auto foundSec = dyn_cast<OutputSection>(*i);
+ if (!foundSec)
+ return e;
// Consider all existing sections with the same proximity.
int proximity = getRankProximity(sec, *i);
+ unsigned sortRank = sec->sortRank;
+ if (script->hasPhdrsCommands() || !script->memoryRegions.empty())
+ // Prevent the orphan section to be placed before the found section. If
+ // custom program headers are defined, that helps to avoid adding it to a
+ // previous segment and changing flags of that segment, for example, making
+ // a read-only segment writable. If memory regions are defined, an orphan
+ // section should continue the same region as the found section to better
+ // resemble the behavior of GNU ld.
+ sortRank = std::max(sortRank, foundSec->sortRank);
for (; i != e; ++i) {
auto *curSec = dyn_cast<OutputSection>(*i);
if (!curSec || !curSec->hasInputSections)
continue;
if (getRankProximity(sec, curSec) != proximity ||
- sec->sortRank < curSec->sortRank)
+ sortRank < curSec->sortRank)
break;
}
@@ -1331,7 +1337,7 @@ static void maybeShuffle(DenseMap<const InputSectionBase *, int> &order) {
// Builds section order for handling --symbol-ordering-file.
static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
DenseMap<const InputSectionBase *, int> sectionOrder;
- // Use the rarely used option -call-graph-ordering-file to sort sections.
+ // Use the rarely used option --call-graph-ordering-file to sort sections.
if (!config->callGraphProfile.empty())
return computeCallGraphProfileOrder();
@@ -1480,29 +1486,19 @@ static void sortSection(OutputSection *sec,
if (auto *isd = dyn_cast<InputSectionDescription>(b))
sortISDBySectionOrder(isd, order);
- // Sort input sections by section name suffixes for
- // __attribute__((init_priority(N))).
- if (name == ".init_array" || name == ".fini_array") {
- if (!script->hasSectionsCommand)
- sec->sortInitFini();
- return;
- }
-
- // Sort input sections by the special rule for .ctors and .dtors.
- if (name == ".ctors" || name == ".dtors") {
- if (!script->hasSectionsCommand)
- sec->sortCtorsDtors();
+ if (script->hasSectionsCommand)
return;
- }
- // .toc is allocated just after .got and is accessed using GOT-relative
- // relocations. Object files compiled with small code model have an
- // 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
- if (config->emachine == EM_PPC64 && name == ".toc") {
- if (script->hasSectionsCommand)
- return;
+ if (name == ".init_array" || name == ".fini_array") {
+ sec->sortInitFini();
+ } else if (name == ".ctors" || name == ".dtors") {
+ sec->sortCtorsDtors();
+ } else if (config->emachine == EM_PPC64 && name == ".toc") {
+ // .toc is allocated just after .got and is accessed using GOT-relative
+ // relocations. Object files compiled with small code model have an
+ // 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]);
llvm::stable_sort(isd->sections,
@@ -1510,7 +1506,6 @@ static void sortSection(OutputSection *sec,
return a->file->ppc64SmallCodeModelTocRelocs &&
!b->file->ppc64SmallCodeModelTocRelocs;
});
- return;
}
}
@@ -1965,10 +1960,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
OutputSection *sec = findSection(".sdata");
ElfSym::riscvGlobalPointer =
addOptionalRegular("__global_pointer$", sec ? sec : Out::elfHeader,
- 0x800, STV_DEFAULT, STB_GLOBAL);
+ 0x800, STV_DEFAULT);
}
- if (config->emachine == EM_X86_64) {
+ if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
// On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
// way that:
//
@@ -2243,8 +2238,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
}
// Ensure data sections are not mixed with executable sections when
-// -execute-only is used. -execute-only is a feature to make pages executable
-// but not readable, and the feature is currently supported only on AArch64.
+// --execute-only is used. --execute-only make pages executable but not
+// readable.
template <class ELFT> void Writer<ELFT>::checkExecuteOnly() {
if (!config->executeOnly)
return;
@@ -2281,7 +2276,7 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
Default = Out::elfHeader;
auto define = [=](StringRef start, StringRef end, OutputSection *os) {
- if (os) {
+ if (os && !script->isDiscarded(os)) {
addOptionalRegular(start, os, 0);
addOptionalRegular(end, os, -1);
} else {
@@ -2597,9 +2592,10 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) {
return alignTo(off, os->ptLoad->p_align, os->addr);
// File offsets are not significant for .bss sections other than the first one
- // in a PT_LOAD. By convention, we keep section offsets monotonically
+ // in a PT_LOAD/PT_TLS. By convention, we keep section offsets monotonically
// increasing rather than setting to zero.
- if (os->type == SHT_NOBITS)
+ if (os->type == SHT_NOBITS &&
+ (!Out::tlsPhdr || Out::tlsPhdr->firstSec != os))
return off;
// If the section is not in a PT_LOAD, we just have to align it.
@@ -2832,8 +2828,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
// 2. the ENTRY(symbol) command in a linker control script;
// 3. the value of the symbol _start, if present;
// 4. the number represented by the entry symbol, if it is a number;
-// 5. the address of the first byte of the .text section, if present;
-// 6. the address 0.
+// 5. the address 0.
static uint64_t getEntryAddr() {
// Case 1, 2 or 3
if (Symbol *b = symtab->find(config->entry))
@@ -2845,14 +2840,6 @@ static uint64_t getEntryAddr() {
return addr;
// Case 5
- if (OutputSection *sec = findSection(".text")) {
- if (config->warnMissingEntry)
- warn("cannot find entry symbol " + config->entry + "; defaulting to 0x" +
- utohexstr(sec->addr));
- return sec->addr;
- }
-
- // Case 6
if (config->warnMissingEntry)
warn("cannot find entry symbol " + config->entry +
"; not setting start address");
@@ -2979,7 +2966,7 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
// Write section contents to a mmap'ed file.
template <class ELFT> void Writer<ELFT>::writeSections() {
- // In -r or -emit-relocs mode, write the relocation sections first as in
+ // In -r or --emit-relocs mode, write the relocation sections first as in
// ELf_Rel targets we might find out that we need to modify the relocated
// section while doing it.
for (OutputSection *sec : outputSections)