[lld] r303784 - Move writeTo to OutputSectionCommand.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Wed May 24 11:08:05 PDT 2017
Author: rafael
Date: Wed May 24 13:08:04 2017
New Revision: 303784
URL: http://llvm.org/viewvc/llvm-project?rev=303784&view=rev
Log:
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.
Modified:
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/LinkerScript.h
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=303784&r1=303783&r2=303784&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed May 24 13:08:04 2017
@@ -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
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::getC
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, uint6
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
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);
Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=303784&r1=303783&r2=303784&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed May 24 13:08:04 2017
@@ -130,6 +130,9 @@ struct OutputSectionCommand : BaseComman
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);
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=303784&r1=303783&r2=303784&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed May 24 13:08:04 2017
@@ -103,7 +103,7 @@ template <class ELFT> void OutputSection
// 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::maybeCompre
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);
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=303784&r1=303783&r2=303784&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Wed May 24 13:08:04 2017
@@ -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();
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=303784&r1=303783&r2=303784&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed May 24 13:08:04 2017
@@ -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());
}
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=303784&r1=303783&r2=303784&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed May 24 13:08:04 2017
@@ -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>:
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>:
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(O
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>:
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>:
// 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>:
// 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() {
More information about the llvm-commits
mailing list