diff options
Diffstat (limited to 'ELF/LinkerScript.cpp')
-rw-r--r-- | ELF/LinkerScript.cpp | 127 |
1 files changed, 86 insertions, 41 deletions
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp index 99c464e3714c..75df2cd4bd5c 100644 --- a/ELF/LinkerScript.cpp +++ b/ELF/LinkerScript.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" @@ -51,9 +52,8 @@ LinkerScript *elf::Script; uint64_t ExprValue::getValue() const { if (Sec) { - if (Sec->getOutputSection()) - return alignTo(Sec->getOffset(Val) + Sec->getOutputSection()->Addr, - Alignment); + if (OutputSection *OS = Sec->getOutputSection()) + return alignTo(Sec->getOffset(Val) + OS->Addr, Alignment); error("unable to evaluate expression: input section " + Sec->Name + " has no output section assigned"); } @@ -85,29 +85,28 @@ template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) { return Sym->body(); } -OutputSection *LinkerScript::getOutputSection(const Twine &Loc, - StringRef Name) { - for (OutputSection *Sec : *OutputSections) - if (Sec->Name == Name) - return Sec; - - static OutputSection Dummy("", 0, 0); - if (ErrorOnMissingSection) - error(Loc + ": undefined section " + Name); - return &Dummy; +OutputSectionCommand * +LinkerScript::createOutputSectionCommand(StringRef Name, StringRef Location) { + OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name]; + OutputSectionCommand *Cmd; + if (CmdRef && CmdRef->Location.empty()) { + // There was a forward reference. + Cmd = CmdRef; + } else { + Cmd = make<OutputSectionCommand>(Name); + if (!CmdRef) + CmdRef = Cmd; + } + Cmd->Location = Location; + return Cmd; } -// This function is essentially the same as getOutputSection(Name)->Size, -// but it won't print out an error message if a given section is not found. -// -// Linker script does not create an output section if its content is empty. -// We want to allow SIZEOF(.foo) where .foo is a section which happened to -// be empty. That is why this function is different from getOutputSection(). -uint64_t LinkerScript::getOutputSectionSize(StringRef Name) { - for (OutputSection *Sec : *OutputSections) - if (Sec->Name == Name) - return Sec->Size; - return 0; +OutputSectionCommand * +LinkerScript::getOrCreateOutputSectionCommand(StringRef Name) { + OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name]; + if (!CmdRef) + CmdRef = make<OutputSectionCommand>(Name); + return CmdRef; } void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { @@ -291,11 +290,13 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { size_t SizeBefore = Ret.size(); for (InputSectionBase *Sec : InputSections) { - if (!isa<InputSection>(Sec)) + if (Sec->Assigned) continue; - if (Sec->Assigned) + if (!Sec->Live) { + reportDiscarded(Sec); continue; + } // For -emit-relocs we have to ignore entries like // .rela.dyn : { *(.rela.data) } @@ -455,7 +456,7 @@ void LinkerScript::fabricateDefaultCommands() { // For each OutputSection that needs a VA fabricate an OutputSectionCommand // with an InputSectionDescription describing the InputSections for (OutputSection *Sec : *OutputSections) { - auto *OSCmd = make<OutputSectionCommand>(Sec->Name); + auto *OSCmd = createOutputSectionCommand(Sec->Name, "<internal>"); OSCmd->Sec = Sec; SecToCommand[Sec] = OSCmd; @@ -487,7 +488,7 @@ void LinkerScript::fabricateDefaultCommands() { // Add sections that didn't match any sections command. void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { for (InputSectionBase *S : InputSections) { - if (!S->Live || S->OutSec) + if (!S->Live || S->Parent) continue; StringRef Name = getOutputSectionName(S->Name); auto I = std::find_if( @@ -590,7 +591,7 @@ void LinkerScript::process(BaseCommand &Base) { // It calculates and assigns the offsets for each section and also // updates the output section size. auto &Cmd = cast<InputSectionDescription>(Base); - for (InputSectionBase *Sec : Cmd.Sections) { + for (InputSection *Sec : Cmd.Sections) { // We tentatively added all synthetic sections at the beginning and removed // empty ones afterwards (because there is no way to know whether they were // going be empty or not other than actually running linker scripts.) @@ -601,8 +602,8 @@ void LinkerScript::process(BaseCommand &Base) { if (!Sec->Live) continue; - assert(CurOutSec == Sec->OutSec); - output(cast<InputSection>(Sec)); + assert(CurOutSec == Sec->getParent()); + output(Sec); } } @@ -842,7 +843,7 @@ void LinkerScript::placeOrphanSections() { // representations agree on which input sections to use. OutputSectionCommand *Cmd = getCmd(Sec); if (!Cmd) { - Cmd = make<OutputSectionCommand>(Name); + Cmd = createOutputSectionCommand(Name, "<internal>"); Opt.Commands.insert(CmdIter, Cmd); ++CmdIndex; @@ -919,9 +920,10 @@ void LinkerScript::synchronize() { } } -static bool allocateHeaders(std::vector<PhdrEntry> &Phdrs, - ArrayRef<OutputSection *> OutputSections, - uint64_t Min) { +static bool +allocateHeaders(std::vector<PhdrEntry> &Phdrs, + ArrayRef<OutputSectionCommand *> OutputSectionCommands, + uint64_t Min) { auto FirstPTLoad = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); @@ -938,16 +940,19 @@ static bool allocateHeaders(std::vector<PhdrEntry> &Phdrs, assert(FirstPTLoad->First == Out::ElfHeader); OutputSection *ActualFirst = nullptr; - for (OutputSection *Sec : OutputSections) { + for (OutputSectionCommand *Cmd : OutputSectionCommands) { + OutputSection *Sec = Cmd->Sec; if (Sec->FirstInPtLoad == Out::ElfHeader) { ActualFirst = Sec; break; } } if (ActualFirst) { - for (OutputSection *Sec : OutputSections) + for (OutputSectionCommand *Cmd : OutputSectionCommands) { + OutputSection *Sec = Cmd->Sec; if (Sec->FirstInPtLoad == Out::ElfHeader) Sec->FirstInPtLoad = ActualFirst; + } FirstPTLoad->First = ActualFirst; } else { Phdrs.erase(FirstPTLoad); @@ -961,7 +966,9 @@ static bool allocateHeaders(std::vector<PhdrEntry> &Phdrs, return false; } -void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) { +void LinkerScript::assignAddresses( + std::vector<PhdrEntry> &Phdrs, + ArrayRef<OutputSectionCommand *> OutputSectionCommands) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; ErrorOnMissingSection = true; @@ -983,14 +990,15 @@ void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) { } uint64_t MinVA = std::numeric_limits<uint64_t>::max(); - for (OutputSection *Sec : *OutputSections) { + for (OutputSectionCommand *Cmd : OutputSectionCommands) { + OutputSection *Sec = Cmd->Sec; if (Sec->Flags & SHF_ALLOC) MinVA = std::min<uint64_t>(MinVA, Sec->Addr); else Sec->Addr = 0; } - allocateHeaders(Phdrs, *OutputSections, MinVA); + allocateHeaders(Phdrs, OutputSectionCommands, MinVA); } // Creates program headers as instructed by PHDRS linker script command. @@ -1068,6 +1076,33 @@ static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { llvm_unreachable("unsupported Size argument"); } +// Compress section contents if this section contains debug info. +template <class ELFT> void OutputSectionCommand::maybeCompress() { + typedef typename ELFT::Chdr Elf_Chdr; + + // Compress only DWARF debug sections. + if (!Config->CompressDebugSections || (Sec->Flags & SHF_ALLOC) || + !Name.startswith(".debug_")) + return; + + // Create a section header. + Sec->ZDebugHeader.resize(sizeof(Elf_Chdr)); + auto *Hdr = reinterpret_cast<Elf_Chdr *>(Sec->ZDebugHeader.data()); + Hdr->ch_type = ELFCOMPRESS_ZLIB; + Hdr->ch_size = Sec->Size; + Hdr->ch_addralign = Sec->Alignment; + + // Write section contents to a temporary buffer and compress it. + std::vector<uint8_t> Buf(Sec->Size); + writeTo<ELFT>(Buf.data()); + if (Error E = zlib::compress(toStringRef(Buf), Sec->CompressedData)) + fatal("compress failed: " + llvm::toString(std::move(E))); + + // Update section headers. + Sec->Size = sizeof(Elf_Chdr) + Sec->CompressedData.size(); + Sec->Flags |= SHF_COMPRESSED; +} + template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) { Sec->Loc = Buf; @@ -1084,7 +1119,12 @@ template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) { return; // Write leading padding. - ArrayRef<InputSection *> Sections = Sec->Sections; + std::vector<InputSection *> Sections; + for (BaseCommand *Cmd : Commands) + if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd)) + for (InputSection *IS : ISD->Sections) + if (IS->Live) + Sections.push_back(IS); uint32_t Filler = getFiller(); if (Filler) fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler); @@ -1161,3 +1201,8 @@ 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); + +template void OutputSectionCommand::maybeCompress<ELF32LE>(); +template void OutputSectionCommand::maybeCompress<ELF32BE>(); +template void OutputSectionCommand::maybeCompress<ELF64LE>(); +template void OutputSectionCommand::maybeCompress<ELF64BE>(); |