diff options
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 78 |
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 |
