diff options
Diffstat (limited to 'lld/ELF')
| -rw-r--r-- | lld/ELF/LinkerScript.cpp | 4 | ||||
| -rw-r--r-- | lld/ELF/LinkerScript.h | 4 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 40 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.h | 1 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 4 | ||||
| -rw-r--r-- | lld/ELF/Target.h | 4 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 2 |
8 files changed, 54 insertions, 11 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 7776889eaab..cd6093e5bc2 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -871,12 +871,12 @@ bool LinkerScript::ignoreInterpSection() { return true; } -uint32_t LinkerScript::getFiller(StringRef Name) { +Optional<uint32_t> LinkerScript::getFiller(StringRef Name) { for (BaseCommand *Base : Opt.Commands) if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) if (Cmd->Name == Name) return Cmd->Filler; - return 0; + return None; } static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 9841f4f7c14..04a388efb4e 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -126,7 +126,7 @@ struct OutputSectionCommand : BaseCommand { Expr SubalignExpr; std::vector<BaseCommand *> Commands; std::vector<StringRef> Phdrs; - uint32_t Filler = 0; + llvm::Optional<uint32_t> Filler; ConstraintKind Constraint = ConstraintKind::NoConstraint; std::string Location; std::string MemoryRegionName; @@ -264,7 +264,7 @@ public: std::vector<PhdrEntry> createPhdrs(); bool ignoreInterpSection(); - uint32_t getFiller(StringRef Name); + llvm::Optional<uint32_t> getFiller(StringRef Name); bool hasLMA(StringRef Name); bool shouldKeep(InputSectionBase *S); void assignOffsets(OutputSectionCommand *Cmd); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index d782fdac5d1..b721dd947ae 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -224,6 +224,9 @@ void OutputSection::sortCtorsDtors() { // Fill [Buf, Buf + Size) with Filler. Filler is written in big // endian order. This is used for linker script "=fillexp" command. static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { + if (Filler == 0) + return; + uint8_t V[4]; write32be(V, Filler); size_t I = 0; @@ -232,17 +235,44 @@ static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { memcpy(Buf + I, V, Size - I); } +uint32_t OutputSection::getFill() { + // 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(Name)) + return *Filler; + if (Flags & SHF_EXECINSTR) + return Target->TrapInstr; + return 0; +} + template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) { Loc = Buf; - if (uint32_t Filler = Script->getFiller(this->Name)) - fill(Buf, this->Size, Filler); - parallelForEach(Sections.begin(), Sections.end(), - [=](InputSection *IS) { IS->writeTo<ELFT>(Buf); }); + uint32_t Filler = getFill(); + + // Write leading padding. + size_t FillSize = Sections.empty() ? Size : Sections[0]->OutSecOff; + fill(Buf, FillSize, Filler); + + parallelFor(0, Sections.size(), [=](size_t I) { + InputSection *Sec = Sections[I]; + Sec->writeTo<ELFT>(Buf); + + // Fill gaps between sections with the specified fill value. + 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->Name, Buf); + Script->writeDataBytes(Name, Buf); } static uint64_t getOutFlags(InputSectionBase *S) { diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index a95f68a7a2c..1e27b9070fa 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -81,6 +81,7 @@ public: void sort(std::function<int(InputSectionBase *S)> Order); void sortInitFini(); void sortCtorsDtors(); + uint32_t getFill(); template <class ELFT> void writeTo(uint8_t *Buf); template <class ELFT> void finalize(); void assignOffsets(); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index c9cca76697b..4c2b91647e1 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2180,7 +2180,11 @@ MipsRldMapSection::MipsRldMapSection() void MipsRldMapSection::writeTo(uint8_t *Buf) { // Apply filler from linker script. - uint64_t Filler = Script->getFiller(this->Name); + Optional<uint32_t> Fill = Script->getFiller(this->Name); + if (!Fill || *Fill == 0) + return; + + uint64_t Filler = *Fill; Filler = (Filler << 32) | Filler; memcpy(Buf, &Filler, getSize()); } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 872d8e650ac..0f565c50c08 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -349,6 +349,8 @@ X86TargetInfo::X86TargetInfo() { PltEntrySize = 16; PltHeaderSize = 16; TlsGdRelaxSkip = 2; + // 0xCC is the "int3" (call debug exception handler) instruction. + TrapInstr = 0xcccccccc; } RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { @@ -647,6 +649,8 @@ template <class ELFT> X86_64TargetInfo<ELFT>::X86_64TargetInfo() { // Align to the large page size (known as a superpage or huge page). // FreeBSD automatically promotes large, superpage-aligned allocations. DefaultImageBase = 0x200000; + // 0xCC is the "int3" (call debug exception handler) instruction. + TrapInstr = 0xcccccccc; } template <class ELFT> diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index deb9cc45e70..410e856890c 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -90,6 +90,10 @@ public: bool NeedsThunks = false; + // A 4-byte field corresponding to one or more trap instructions, used to pad + // executable OutputSections. + uint32_t TrapInstr = 0; + virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, RelExpr Expr) const; virtual void relaxGot(uint8_t *Loc, uint64_t Val) const; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 56f1b5ee325..fd761d68d15 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1790,7 +1790,7 @@ template <class ELFT> void Writer<ELFT>::writeSections() { // The .eh_frame_hdr depends on .eh_frame section contents, therefore // it should be written after .eh_frame is written. - if (EhFrameHdr) + if (EhFrameHdr && !EhFrameHdr->Sections.empty()) EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset); } |

