diff options
Diffstat (limited to 'ELF/OutputSections.cpp')
-rw-r--r-- | ELF/OutputSections.cpp | 93 |
1 files changed, 23 insertions, 70 deletions
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index dcefd03766d7..d82fdcdc31ba 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -103,7 +103,7 @@ template <class ELFT> void OutputSection::maybeCompress() { // Write section contents to a temporary buffer and compress it. std::vector<uint8_t> Buf(Size); - writeTo<ELFT>(Buf.data()); + Script->getCmd(this)->writeTo<ELFT>(Buf.data()); if (Error E = zlib::compress(toStringRef(Buf), CompressedData)) fatal("compress failed: " + llvm::toString(std::move(E))); @@ -112,6 +112,19 @@ template <class ELFT> void OutputSection::maybeCompress() { Flags |= SHF_COMPRESSED; } +template <class ELFT> static void finalizeShtGroup(OutputSection *Sec) { + // sh_link field for SHT_GROUP sections should contain the section index of + // the symbol table. + Sec->Link = InX::SymTab->OutSec->SectionIndex; + + // sh_link then contain index of an entry in symbol table section which + // provides signature of the section group. + elf::ObjectFile<ELFT> *Obj = Sec->Sections[0]->getFile<ELFT>(); + assert(Config->Relocatable && Sec->Sections.size() == 1); + ArrayRef<SymbolBody *> Symbols = Obj->getSymbols(); + Sec->Info = InX::SymTab->getSymbolIndex(Symbols[Sec->Sections[0]->Info - 1]); +} + template <class ELFT> void OutputSection::finalize() { if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) { std::sort(Sections.begin(), Sections.end(), compareByFilePosition); @@ -126,6 +139,11 @@ template <class ELFT> void OutputSection::finalize() { } uint32_t Type = this->Type; + if (Type == SHT_GROUP) { + finalizeShtGroup<ELFT>(this); + return; + } + if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL)) return; @@ -259,69 +277,6 @@ void OutputSection::sortCtorsDtors() { std::stable_sort(Sections.begin(), Sections.end(), compCtors); } -// Fill [Buf, Buf + Size) with Filler. -// This is used for linker script "=fillexp" command. -static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { - size_t I = 0; - for (; I + 4 < Size; I += 4) - memcpy(Buf + I, &Filler, 4); - memcpy(Buf + I, &Filler, Size - I); -} - -uint32_t OutputSection::getFiller() { - // Determine what to fill gaps between InputSections with, as specified by the - // linker script. If nothing is specified and this is an executable section, - // fall back to trap instructions to prevent bad diassembly and detect invalid - // jumps to padding. - if (Optional<uint32_t> Filler = Script->getFiller(this)) - return *Filler; - if (Flags & SHF_EXECINSTR) - return Target->TrapInstr; - return 0; -} - -template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) { - Loc = Buf; - - // We may have already rendered compressed content when using - // -compress-debug-sections option. Write it together with header. - if (!CompressedData.empty()) { - memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size()); - memcpy(Buf + ZDebugHeader.size(), CompressedData.data(), - CompressedData.size()); - return; - } - - // Write leading padding. - uint32_t Filler = getFiller(); - if (Filler) - fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler); - - parallelForEachN(0, Sections.size(), [=](size_t I) { - InputSection *Sec = Sections[I]; - Sec->writeTo<ELFT>(Buf); - - // Fill gaps between sections. - if (Filler) { - uint8_t *Start = Buf + Sec->OutSecOff + Sec->getSize(); - uint8_t *End; - if (I + 1 == Sections.size()) - End = Buf + Size; - else - End = Buf + Sections[I + 1]->OutSecOff; - fill(Start, End - Start, Filler); - } - }); - - // Linker scripts may have BYTE()-family commands with which you - // can write arbitrary bytes to the output. Process them if any. - Script->writeDataBytes(this, Buf); -} - -static uint64_t getOutFlags(InputSectionBase *S) { - return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; -} - static SectionKey createKey(InputSectionBase *C, StringRef OutsecName) { // The ELF spec just says // ---------------------------------------------------------------- @@ -418,7 +373,10 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS, return; } - uint64_t Flags = getOutFlags(IS); + uint64_t Flags = IS->Flags; + if (!Config->Relocatable) + Flags &= ~(uint64_t)SHF_GROUP; + if (Sec) { if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags)) error("incompatible section flags for " + Sec->Name + @@ -484,8 +442,3 @@ template void OutputSection::maybeCompress<ELF32LE>(); template void OutputSection::maybeCompress<ELF32BE>(); template void OutputSection::maybeCompress<ELF64LE>(); template void OutputSection::maybeCompress<ELF64BE>(); - -template void OutputSection::writeTo<ELF32LE>(uint8_t *Buf); -template void OutputSection::writeTo<ELF32BE>(uint8_t *Buf); -template void OutputSection::writeTo<ELF64LE>(uint8_t *Buf); -template void OutputSection::writeTo<ELF64BE>(uint8_t *Buf); |