aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/OutputSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
-rw-r--r--lld/ELF/OutputSections.cpp78
1 files changed, 41 insertions, 37 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 241b3ea3b418..bc940c7e6546 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -8,19 +8,17 @@
#include "OutputSections.h"
#include "Config.h"
+#include "InputFiles.h"
#include "LinkerScript.h"
-#include "SymbolTable.h"
+#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/Arrays.h"
#include "lld/Common/Memory.h"
-#include "lld/Common/Strings.h"
#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/Config/config.h" // LLVM_ENABLE_ZLIB
-#include "llvm/Support/MD5.h"
-#include "llvm/Support/MathExtras.h"
+#include "llvm/Config/llvm-config.h" // LLVM_ENABLE_ZLIB
#include "llvm/Support/Parallel.h"
-#include "llvm/Support/SHA1.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/TimeProfiler.h"
#if LLVM_ENABLE_ZLIB
#include <zlib.h>
@@ -70,8 +68,7 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) {
}
OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags)
- : SectionCommand(OutputSectionKind),
- SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
+ : SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
/*Info*/ 0, /*Link*/ 0) {}
// We allow sections of types listed below to merged into a
@@ -111,32 +108,40 @@ void OutputSection::recordSection(InputSectionBase *isec) {
// isec. Also check whether the InputSection flags and type are consistent with
// other InputSections.
void OutputSection::commitSection(InputSection *isec) {
+ if (LLVM_UNLIKELY(type != isec->type)) {
+ if (hasInputSections || typeIsSet) {
+ if (typeIsSet || !canMergeToProgbits(type) ||
+ !canMergeToProgbits(isec->type)) {
+ // Changing the type of a (NOLOAD) section is fishy, but some projects
+ // (e.g. https://github.com/ClangBuiltLinux/linux/issues/1597)
+ // traditionally rely on the behavior. Issue a warning to not break
+ // them. Other types get an error.
+ auto diagnose = type == SHT_NOBITS ? warn : errorOrWarn;
+ diagnose("section type mismatch for " + isec->name + "\n>>> " +
+ toString(isec) + ": " +
+ getELFSectionTypeName(config->emachine, isec->type) +
+ "\n>>> output section " + name + ": " +
+ getELFSectionTypeName(config->emachine, type));
+ }
+ if (!typeIsSet)
+ type = SHT_PROGBITS;
+ } else {
+ type = isec->type;
+ }
+ }
if (!hasInputSections) {
// If IS is the first section to be added to this section,
// initialize type, entsize and flags from isec.
hasInputSections = true;
- type = isec->type;
entsize = isec->entsize;
flags = isec->flags;
} else {
// Otherwise, check if new type or flags are compatible with existing ones.
if ((flags ^ isec->flags) & SHF_TLS)
- error("incompatible section flags for " + name + "\n>>> " + toString(isec) +
- ": 0x" + utohexstr(isec->flags) + "\n>>> output section " + name +
- ": 0x" + utohexstr(flags));
-
- if (type != isec->type) {
- if (!canMergeToProgbits(type) || !canMergeToProgbits(isec->type))
- error("section type mismatch for " + isec->name + "\n>>> " +
- toString(isec) + ": " +
- getELFSectionTypeName(config->emachine, isec->type) +
- "\n>>> output section " + name + ": " +
- getELFSectionTypeName(config->emachine, type));
- type = SHT_PROGBITS;
- }
+ error("incompatible section flags for " + name + "\n>>> " +
+ toString(isec) + ": 0x" + utohexstr(isec->flags) +
+ "\n>>> output section " + name + ": 0x" + utohexstr(flags));
}
- if (noload)
- type = SHT_NOBITS;
isec->parent = this;
uint64_t andMask =
@@ -246,10 +251,6 @@ uint64_t elf::getHeaderSize() {
return Out::elfHeader->size + Out::programHeaders->size;
}
-bool OutputSection::classof(const SectionCommand *c) {
- return c->kind == OutputSectionKind;
-}
-
void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) {
assert(isLive());
for (SectionCommand *b : commands)
@@ -349,7 +350,7 @@ template <class ELFT> void OutputSection::maybeCompress() {
// concatenated with the next shard.
auto shardsOut = std::make_unique<SmallVector<uint8_t, 0>[]>(numShards);
auto shardsAdler = std::make_unique<uint32_t[]>(numShards);
- parallelForEachN(0, numShards, [&](size_t i) {
+ parallelFor(0, numShards, [&](size_t i) {
shardsOut[i] = deflateShard(shardsIn[i], level,
i != numShards - 1 ? Z_SYNC_FLUSH : Z_FINISH);
shardsAdler[i] = adler32(1, shardsIn[i].data(), shardsIn[i].size());
@@ -408,7 +409,7 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *buf) {
buf[0] = 0x78; // CMF
buf[1] = 0x01; // FLG: best speed
- parallelForEachN(0, compressed.numShards, [&](size_t i) {
+ parallelFor(0, compressed.numShards, [&](size_t i) {
memcpy(buf + offsets[i], compressed.shards[i].data(),
compressed.shards[i].size());
});
@@ -424,9 +425,12 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *buf) {
if (nonZeroFiller)
fill(buf, sections.empty() ? size : sections[0]->outSecOff, filler);
- parallelForEachN(0, sections.size(), [&](size_t i) {
+ parallelFor(0, sections.size(), [&](size_t i) {
InputSection *isec = sections[i];
- isec->writeTo<ELFT>(buf + isec->outSecOff);
+ if (auto *s = dyn_cast<SyntheticSection>(isec))
+ s->writeTo(buf + isec->outSecOff);
+ else
+ isec->writeTo<ELFT>(buf + isec->outSecOff);
// Fill gaps between sections.
if (nonZeroFiller) {
@@ -451,14 +455,14 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *buf) {
writeInt(buf + data->offset, data->expression().getValue(), data->size);
}
-static void finalizeShtGroup(OutputSection *os,
- InputSection *section) {
- assert(config->relocatable);
-
+static void finalizeShtGroup(OutputSection *os, InputSection *section) {
// sh_link field for SHT_GROUP sections should contain the section index of
// the symbol table.
os->link = in.symTab->getParent()->sectionIndex;
+ if (!section)
+ return;
+
// sh_info then contain index of an entry in symbol table section which
// provides signature of the section group.
ArrayRef<Symbol *> symbols = section->file->getSymbols();
@@ -619,7 +623,7 @@ void OutputSection::checkDynRelAddends(const uint8_t *bufStart) {
assert(config->writeAddends && config->checkDynamicRelocs);
assert(type == SHT_REL || type == SHT_RELA);
SmallVector<InputSection *, 0> sections = getInputSections(*this);
- parallelForEachN(0, sections.size(), [&](size_t i) {
+ parallelFor(0, sections.size(), [&](size_t i) {
// When linking with -r or --emit-relocs we might also call this function
// for input .rel[a].<sec> sections which we simply pass through to the
// output. We skip over those and only look at the synthetic relocation