diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2017-05-24 18:08:04 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2017-05-24 18:08:04 +0000 |
commit | 55b169bf5dd84246f9d71ed6cd2b05d65e10d1fc (patch) | |
tree | e5b0d0aae42938c104df5125da83e01617450cdd | |
parent | c98741c79e83ee64592fb82b9577119958793d80 (diff) | |
download | bcm5719-llvm-55b169bf5dd84246f9d71ed6cd2b05d65e10d1fc.tar.gz bcm5719-llvm-55b169bf5dd84246f9d71ed6cd2b05d65e10d1fc.zip |
Move writeTo to OutputSectionCommand.
This reduces how many times we have to map from OutputSection to
OutputSectionCommand. It is a required step to moving
clearOutputSections earlier.
In order to always use writeTo in OutputSectionCommand we have to call
fabricateDefaultCommands for -r links and move section compression
after it.
llvm-svn: 303784
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 70 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 7 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 66 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 2 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 5 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 71 |
6 files changed, 118 insertions, 103 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 6eed99db3d7..492b81c1fa7 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -20,6 +20,8 @@ #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" +#include "Target.h" +#include "Threads.h" #include "Writer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -198,6 +200,15 @@ bool OutputSectionCommand::classof(const BaseCommand *C) { return C->Kind == OutputSectionKind; } +// 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); +} + bool InputSectionDescription::classof(const BaseCommand *C) { return C->Kind == InputSectionKind; } @@ -1032,10 +1043,12 @@ OutputSectionCommand *LinkerScript::getCmd(OutputSection *Sec) const { return I->second; } -Optional<uint32_t> LinkerScript::getFiller(OutputSection *Sec) { - if (OutputSectionCommand *Cmd = getCmd(Sec)) - return Cmd->Filler; - return None; +uint32_t OutputSectionCommand::getFiller() { + if (Filler) + return *Filler; + if (Sec->Flags & SHF_EXECINSTR) + return Target->TrapInstr; + return 0; } static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { @@ -1051,11 +1064,45 @@ static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { llvm_unreachable("unsupported Size argument"); } -void LinkerScript::writeDataBytes(OutputSection *Sec, uint8_t *Buf) { - if (OutputSectionCommand *Cmd = getCmd(Sec)) - for (BaseCommand *Base : Cmd->Commands) - if (auto *Data = dyn_cast<BytesDataCommand>(Base)) - writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); +template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) { + Sec->Loc = Buf; + + // We may have already rendered compressed content when using + // -compress-debug-sections option. Write it together with header. + if (!Sec->CompressedData.empty()) { + memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size()); + memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(), + Sec->CompressedData.size()); + return; + } + + // Write leading padding. + ArrayRef<InputSection *> Sections = Sec->Sections; + uint32_t Filler = getFiller(); + if (Filler) + fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler); + + parallelForEachN(0, Sections.size(), [=](size_t I) { + InputSection *IS = Sections[I]; + IS->writeTo<ELFT>(Buf); + + // Fill gaps between sections. + if (Filler) { + uint8_t *Start = Buf + IS->OutSecOff + IS->getSize(); + uint8_t *End; + if (I + 1 == Sections.size()) + End = Buf + Sec->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. + for (BaseCommand *Base : Commands) + if (auto *Data = dyn_cast<BytesDataCommand>(Base)) + writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); } bool LinkerScript::hasLMA(OutputSection *Sec) { @@ -1102,3 +1149,8 @@ size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) { error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); return 0; } + +template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf); +template void OutputSectionCommand::writeTo<ELF32BE>(uint8_t *Buf); +template void OutputSectionCommand::writeTo<ELF64LE>(uint8_t *Buf); +template void OutputSectionCommand::writeTo<ELF64BE>(uint8_t *Buf); diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index e85a279ca7a..e56e569d4e7 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -130,6 +130,9 @@ struct OutputSectionCommand : BaseCommand { ConstraintKind Constraint = ConstraintKind::NoConstraint; std::string Location; std::string MemoryRegionName; + + template <class ELFT> void writeTo(uint8_t *Buf); + uint32_t getFiller(); }; // This struct represents one section match pattern in SECTIONS() command. @@ -213,7 +216,6 @@ struct ScriptConfiguration { class LinkerScript final { llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand; - OutputSectionCommand *getCmd(OutputSection *Sec) const; void assignSymbol(SymbolAssignment *Cmd, bool InSec); void setDot(Expr E, const Twine &Loc, bool InSec); @@ -244,6 +246,7 @@ class LinkerScript final { MemoryRegion *CurMemRegion = nullptr; public: + OutputSectionCommand *getCmd(OutputSection *Sec) const; bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } uint64_t getDot() { return Dot; } OutputSection *getOutputSection(const Twine &Loc, StringRef S); @@ -263,7 +266,6 @@ public: std::vector<PhdrEntry> createPhdrs(); bool ignoreInterpSection(); - llvm::Optional<uint32_t> getFiller(OutputSection *Sec); bool hasLMA(OutputSection *Sec); bool shouldKeep(InputSectionBase *S); void assignOffsets(OutputSectionCommand *Cmd); @@ -272,7 +274,6 @@ public: void synchronize(); void assignAddresses(std::vector<PhdrEntry> &Phdrs); - void writeDataBytes(OutputSection *Sec, uint8_t *Buf); void addSymbol(SymbolAssignment *Cmd); void processCommands(OutputSectionFactory &Factory); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index dcefd03766d..a26b0968f45 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/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))); @@ -259,65 +259,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; } @@ -484,8 +425,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); diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 413871b60cf..08655a9ed67 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -82,8 +82,6 @@ public: void sort(std::function<int(InputSectionBase *S)> Order); void sortInitFini(); void sortCtorsDtors(); - uint32_t getFiller(); - template <class ELFT> void writeTo(uint8_t *Buf); template <class ELFT> void finalize(); template <class ELFT> void maybeCompress(); void assignOffsets(); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 599f1441a47..bcfb7754247 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2175,11 +2175,10 @@ MipsRldMapSection::MipsRldMapSection() void MipsRldMapSection::writeTo(uint8_t *Buf) { // Apply filler from linker script. - Optional<uint32_t> Fill = Script->getFiller(this->OutSec); - if (!Fill || *Fill == 0) + uint64_t Filler = Script->getCmd(this->OutSec)->getFiller(); + if (Filler == 0) return; - uint64_t Filler = *Fill; Filler = (Filler << 32) | Filler; memcpy(Buf, &Filler, getSize()); } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index dbb2bdb7753..84e3e4eff8e 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -81,6 +81,7 @@ private: void addStartStopSymbols(OutputSection *Sec); uint64_t getEntryAddr(); OutputSection *findSection(StringRef Name); + OutputSectionCommand *findSectionInScript(StringRef Name); std::vector<PhdrEntry> Phdrs; @@ -254,13 +255,21 @@ template <class ELFT> void Writer<ELFT>::run() { if (ErrorCount) return; + if (!Script->Opt.HasSections) { + if (!Config->Relocatable) + fixSectionAlignments(); + Script->fabricateDefaultCommands(); + } + + // If -compressed-debug-sections is specified, we need to compress + // .debug_* sections. Do it right now because it changes the size of + // output sections. + parallelForEach(OutputSections.begin(), OutputSections.end(), + [](OutputSection *S) { S->maybeCompress<ELFT>(); }); + if (Config->Relocatable) { assignFileOffsets(); } else { - if (!Script->Opt.HasSections) { - fixSectionAlignments(); - Script->fabricateDefaultCommands(); - } Script->synchronize(); Script->assignAddresses(Phdrs); @@ -1246,12 +1255,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { for (OutputSection *Sec : OutputSections) Sec->finalize<ELFT>(); - // If -compressed-debug-sections is specified, we need to compress - // .debug_* sections. Do it right now because it changes the size of - // output sections. - parallelForEach(OutputSections.begin(), OutputSections.end(), - [](OutputSection *S) { S->maybeCompress<ELFT>(); }); - // createThunks may have added local symbols to the static symbol table applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab}, [](SyntheticSection *SS) { SS->postThunkContents(); }); @@ -1304,6 +1307,15 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) { addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); } +template <class ELFT> +OutputSectionCommand *Writer<ELFT>::findSectionInScript(StringRef Name) { + for (BaseCommand *Base : Script->Opt.Commands) + if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) + if (Cmd->Name == Name) + return Cmd; + return nullptr; +} + template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) { for (OutputSection *Sec : OutputSections) if (Sec->Name == Name) @@ -1743,9 +1755,14 @@ template <class ELFT> void Writer<ELFT>::openFile() { template <class ELFT> void Writer<ELFT>::writeSectionsBinary() { uint8_t *Buf = Buffer->getBufferStart(); - for (OutputSection *Sec : OutputSections) + for (BaseCommand *Base : Script->Opt.Commands) { + auto *Cmd = dyn_cast<OutputSectionCommand>(Base); + if (!Cmd) + continue; + OutputSection *Sec = Cmd->Sec; if (Sec->Flags & SHF_ALLOC) - Sec->writeTo<ELFT>(Buf + Sec->Offset); + Cmd->writeTo<ELFT>(Buf + Sec->Offset); + } } // Write section contents to a mmap'ed file. @@ -1754,10 +1771,10 @@ template <class ELFT> void Writer<ELFT>::writeSections() { // PPC64 needs to process relocations in the .opd section // before processing relocations in code-containing sections. - Out::Opd = findSection(".opd"); - if (Out::Opd) { + if (auto *OpdCmd = findSectionInScript(".opd")) { + Out::Opd = OpdCmd->Sec; Out::OpdBuf = Buf + Out::Opd->Offset; - Out::Opd->template writeTo<ELFT>(Buf + Out::Opd->Offset); + OpdCmd->template writeTo<ELFT>(Buf + Out::Opd->Offset); } OutputSection *EhFrameHdr = @@ -1766,19 +1783,31 @@ template <class ELFT> void Writer<ELFT>::writeSections() { // 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) + for (BaseCommand *Base : Script->Opt.Commands) { + auto *Cmd = dyn_cast<OutputSectionCommand>(Base); + if (!Cmd) + continue; + OutputSection *Sec = Cmd->Sec; if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) - Sec->writeTo<ELFT>(Buf + Sec->Offset); + Cmd->writeTo<ELFT>(Buf + Sec->Offset); + } - for (OutputSection *Sec : OutputSections) + for (BaseCommand *Base : Script->Opt.Commands) { + auto *Cmd = dyn_cast<OutputSectionCommand>(Base); + if (!Cmd) + continue; + OutputSection *Sec = Cmd->Sec; if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL && Sec->Type != SHT_RELA) - Sec->writeTo<ELFT>(Buf + Sec->Offset); + Cmd->writeTo<ELFT>(Buf + Sec->Offset); + } // The .eh_frame_hdr depends on .eh_frame section contents, therefore // it should be written after .eh_frame is written. - if (EhFrameHdr && !EhFrameHdr->Sections.empty()) - EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset); + if (EhFrameHdr && !EhFrameHdr->Sections.empty()) { + OutputSectionCommand *Cmd = Script->getCmd(EhFrameHdr); + Cmd->writeTo<ELFT>(Buf + EhFrameHdr->Offset); + } } template <class ELFT> void Writer<ELFT>::writeBuildId() { |