summaryrefslogtreecommitdiffstats
path: root/lld/ELF/LinkerScript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/LinkerScript.cpp')
-rw-r--r--lld/ELF/LinkerScript.cpp70
1 files changed, 61 insertions, 9 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);
OpenPOWER on IntegriCloud