diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-01 20:59:20 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-01 20:59:20 +0000 |
commit | 80350c116f86dbb87e055a630b1b2be0c66b244b (patch) | |
tree | 022e6b2a1e0e5a03028fa465a30338d8f6dbbf48 | |
parent | cbb560c9ba3c378189c7a438bed9977b482410fb (diff) | |
download | src-test2-80350c116f86dbb87e055a630b1b2be0c66b244b.tar.gz src-test2-80350c116f86dbb87e055a630b1b2be0c66b244b.zip |
Notes
-rw-r--r-- | ELF/InputSection.cpp | 50 | ||||
-rw-r--r-- | ELF/InputSection.h | 19 | ||||
-rw-r--r-- | ELF/LinkerScript.cpp | 127 | ||||
-rw-r--r-- | ELF/LinkerScript.h | 14 | ||||
-rw-r--r-- | ELF/MarkLive.cpp | 3 | ||||
-rw-r--r-- | ELF/OutputSections.cpp | 53 | ||||
-rw-r--r-- | ELF/OutputSections.h | 2 | ||||
-rw-r--r-- | ELF/Relocations.cpp | 8 | ||||
-rw-r--r-- | ELF/ScriptParser.cpp | 32 | ||||
-rw-r--r-- | ELF/Symbols.cpp | 8 | ||||
-rw-r--r-- | ELF/SyntheticSections.cpp | 97 | ||||
-rw-r--r-- | ELF/SyntheticSections.h | 2 | ||||
-rw-r--r-- | ELF/Target.cpp | 4 | ||||
-rw-r--r-- | ELF/Writer.cpp | 82 | ||||
-rw-r--r-- | test/ELF/gc-absolute.s | 7 | ||||
-rw-r--r-- | test/ELF/i386-gotpc-dynamic.s | 32 | ||||
-rw-r--r-- | test/ELF/mips64-eh-abs-reloc.s | 38 | ||||
-rw-r--r-- | test/ELF/section-metadata-err.s | 15 |
18 files changed, 379 insertions, 214 deletions
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp index 466656efbf08..4af05c1a187b 100644 --- a/ELF/InputSection.cpp +++ b/ELF/InputSection.cpp @@ -139,21 +139,24 @@ uint64_t SectionBase::getOffset(uint64_t Offset) const { return Offset; case Merge: const MergeInputSection *MS = cast<MergeInputSection>(this); - if (MS->MergeSec) - return MS->MergeSec->OutSecOff + MS->getOffset(Offset); + if (InputSection *IS = MS->getParent()) + return IS->OutSecOff + MS->getOffset(Offset); return MS->getOffset(Offset); } llvm_unreachable("invalid section kind"); } OutputSection *SectionBase::getOutputSection() { + InputSection *Sec; if (auto *IS = dyn_cast<InputSection>(this)) - return IS->OutSec; - if (auto *MS = dyn_cast<MergeInputSection>(this)) - return MS->MergeSec ? MS->MergeSec->OutSec : nullptr; - if (auto *EH = dyn_cast<EhInputSection>(this)) - return EH->EHSec->OutSec; - return cast<OutputSection>(this); + Sec = IS; + else if (auto *MS = dyn_cast<MergeInputSection>(this)) + Sec = MS->getParent(); + else if (auto *EH = dyn_cast<EhInputSection>(this)) + Sec = EH->getParent(); + else + return cast<OutputSection>(this); + return Sec ? Sec->getParent() : nullptr; } // Uncompress section contents. Note that this function is called @@ -181,9 +184,15 @@ uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const { return getOffset(Sym.Value); } -InputSectionBase *InputSectionBase::getLinkOrderDep() const { - if ((Flags & SHF_LINK_ORDER) && Link != 0) - return File->getSections()[Link]; +InputSection *InputSectionBase::getLinkOrderDep() const { + if ((Flags & SHF_LINK_ORDER) && Link != 0) { + InputSectionBase *L = File->getSections()[Link]; + if (auto *IS = dyn_cast<InputSection>(L)) + return IS; + error( + "Merge and .eh_frame sections are not supported with SHF_LINK_ORDER " + + toString(L)); + } return nullptr; } @@ -295,6 +304,10 @@ bool InputSectionBase::classof(const SectionBase *S) { return S->kind() != Output; } +OutputSection *InputSection::getParent() const { + return cast_or_null<OutputSection>(Parent); +} + void InputSection::copyShtGroup(uint8_t *Buf) { assert(this->Type == SHT_GROUP); @@ -309,7 +322,8 @@ void InputSection::copyShtGroup(uint8_t *Buf) { ArrayRef<InputSectionBase *> Sections = this->File->getSections(); for (uint32_t Val : From.slice(1)) { uint32_t Index = read32(&Val, Config->Endianness); - write32(To++, Sections[Index]->OutSec->SectionIndex, Config->Endianness); + write32(To++, Sections[Index]->getOutputSection()->SectionIndex, + Config->Endianness); } } @@ -342,7 +356,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { // Output section VA is zero for -r, so r_offset is an offset within the // section, but for --emit-relocs it is an virtual address. - P->r_offset = RelocatedSection->OutSec->Addr + + P->r_offset = RelocatedSection->getOutputSection()->Addr + RelocatedSection->getOffset(Rel.r_offset); P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Body), Type, Config->IsMips64EL); @@ -596,7 +610,7 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { return; } - uint64_t AddrLoc = this->OutSec->Addr + Offset; + uint64_t AddrLoc = getParent()->Addr + Offset; uint64_t SymVA = 0; if (!Sym.isTls() || Out::TlsPhdr) SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( @@ -729,6 +743,10 @@ EhInputSection::EhInputSection(elf::ObjectFile<ELFT> *F, this->Live = true; } +SyntheticSection *EhInputSection::getParent() const { + return cast_or_null<SyntheticSection>(Parent); +} + bool EhInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::EHFrame; } @@ -797,6 +815,10 @@ static size_t findNull(ArrayRef<uint8_t> A, size_t EntSize) { return StringRef::npos; } +SyntheticSection *MergeInputSection::getParent() const { + return cast_or_null<SyntheticSection>(Parent); +} + // Split SHF_STRINGS section. Such section is a sequence of // null-terminated strings. void MergeInputSection::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) { diff --git a/ELF/InputSection.h b/ELF/InputSection.h index 4ef4328e8a5d..97ca2133f905 100644 --- a/ELF/InputSection.h +++ b/ELF/InputSection.h @@ -120,7 +120,12 @@ public: uint64_t Entsize, uint32_t Link, uint32_t Info, uint32_t Alignment, ArrayRef<uint8_t> Data, StringRef Name, Kind SectionKind); - OutputSection *OutSec = nullptr; + + // Input sections are part of an output section. Special sections + // like .eh_frame and merge sections are first combined into a + // synthetic section that is then added to an output section. In all + // cases this points one level up. + SectionBase *Parent = nullptr; // Relocations that refer to this section. const void *FirstRelocation = nullptr; @@ -158,7 +163,7 @@ public: return getFile<ELFT>()->getObj(); } - InputSectionBase *getLinkOrderDep() const; + InputSection *getLinkOrderDep() const; void uncompress(); @@ -237,10 +242,7 @@ public: SectionPiece *getSectionPiece(uint64_t Offset); const SectionPiece *getSectionPiece(uint64_t Offset) const; - // MergeInputSections are aggregated to a synthetic input sections, - // and then added to an OutputSection. This pointer points to a - // synthetic MergeSyntheticSection which this section belongs to. - MergeSyntheticSection *MergeSec = nullptr; + SyntheticSection *getParent() const; private: void splitStrings(ArrayRef<uint8_t> A, size_t Size); @@ -280,7 +282,8 @@ public: // Splittable sections are handled as a sequence of data // rather than a single large blob of data. std::vector<EhSectionPiece> Pieces; - SyntheticSection *EHSec = nullptr; + + SyntheticSection *getParent() const; }; // This is a section that is added directly to an output section @@ -299,6 +302,8 @@ public: // beginning of the output section. template <class ELFT> void writeTo(uint8_t *Buf); + OutputSection *getParent() const; + // The offset from beginning of the output sections this section was assigned // to. The writer sets a value. uint64_t OutSecOff = 0; 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>(); diff --git a/ELF/LinkerScript.h b/ELF/LinkerScript.h index 08f60f4517a7..a708ea7f61d5 100644 --- a/ELF/LinkerScript.h +++ b/ELF/LinkerScript.h @@ -137,6 +137,7 @@ struct OutputSectionCommand : BaseCommand { std::string MemoryRegionName; template <class ELFT> void writeTo(uint8_t *Buf); + template <class ELFT> void maybeCompress(); uint32_t getFiller(); }; @@ -221,6 +222,8 @@ struct ScriptConfiguration { class LinkerScript final { llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand; + llvm::DenseMap<StringRef, OutputSectionCommand *> NameToOutputSectionCommand; + void assignSymbol(SymbolAssignment *Cmd, bool InSec); void setDot(Expr E, const Twine &Loc, bool InSec); @@ -241,7 +244,6 @@ class LinkerScript final { void process(BaseCommand &Base); OutputSection *Aether; - bool ErrorOnMissingSection = false; uint64_t Dot; uint64_t ThreadBssOffset = 0; @@ -251,11 +253,14 @@ class LinkerScript final { MemoryRegion *CurMemRegion = nullptr; public: + bool ErrorOnMissingSection = false; + OutputSectionCommand *createOutputSectionCommand(StringRef Name, + StringRef Location); + OutputSectionCommand *getOrCreateOutputSectionCommand(StringRef Name); + OutputSectionCommand *getCmd(OutputSection *Sec) const; bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } uint64_t getDot() { return Dot; } - OutputSection *getOutputSection(const Twine &Loc, StringRef S); - uint64_t getOutputSectionSize(StringRef S); void discard(ArrayRef<InputSectionBase *> V); ExprValue getSymbolValue(const Twine &Loc, StringRef S); @@ -277,7 +282,8 @@ public: void placeOrphanSections(); void processNonSectionCommands(); void synchronize(); - void assignAddresses(std::vector<PhdrEntry> &Phdrs); + void assignAddresses(std::vector<PhdrEntry> &Phdrs, + ArrayRef<OutputSectionCommand *> OutputSectionCommands); void addSymbol(SymbolAssignment *Cmd); void processCommands(OutputSectionFactory &Factory); diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp index ee499265886e..b77c84ff75a0 100644 --- a/ELF/MarkLive.cpp +++ b/ELF/MarkLive.cpp @@ -220,7 +220,8 @@ template <class ELFT> void elf::markLive() { auto MarkSymbol = [&](const SymbolBody *Sym) { if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) - Enqueue({cast<InputSectionBase>(D->Section), D->Value}); + if (auto *IS = cast_or_null<InputSectionBase>(D->Section)) + Enqueue({IS, D->Value}); }; // Add GC root symbols. diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index f117690c3828..4f8906a32081 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -16,7 +16,6 @@ #include "SyntheticSections.h" #include "Target.h" #include "Threads.h" -#include "llvm/Support/Compression.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" @@ -76,46 +75,19 @@ static bool compareByFilePosition(InputSection *A, InputSection *B) { if (A->kind() == InputSectionBase::Synthetic || B->kind() == InputSectionBase::Synthetic) return false; - auto *LA = cast<InputSection>(A->getLinkOrderDep()); - auto *LB = cast<InputSection>(B->getLinkOrderDep()); - OutputSection *AOut = LA->OutSec; - OutputSection *BOut = LB->OutSec; + InputSection *LA = A->getLinkOrderDep(); + InputSection *LB = B->getLinkOrderDep(); + OutputSection *AOut = LA->getParent(); + OutputSection *BOut = LB->getParent(); if (AOut != BOut) return AOut->SectionIndex < BOut->SectionIndex; return LA->OutSecOff < LB->OutSecOff; } -// Compress section contents if this section contains debug info. -template <class ELFT> void OutputSection::maybeCompress() { - typedef typename ELFT::Chdr Elf_Chdr; - - // Compress only DWARF debug sections. - if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) || - !Name.startswith(".debug_")) - return; - - // Create a section header. - ZDebugHeader.resize(sizeof(Elf_Chdr)); - auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data()); - Hdr->ch_type = ELFCOMPRESS_ZLIB; - Hdr->ch_size = Size; - Hdr->ch_addralign = Alignment; - - // Write section contents to a temporary buffer and compress it. - std::vector<uint8_t> Buf(Size); - Script->getCmd(this)->writeTo<ELFT>(Buf.data()); - if (Error E = zlib::compress(toStringRef(Buf), CompressedData)) - fatal("compress failed: " + llvm::toString(std::move(E))); - - // Update section headers. - Size = sizeof(Elf_Chdr) + CompressedData.size(); - Flags |= SHF_COMPRESSED; -} - template <class ELFT> static void finalizeShtGroup(OutputSection *Sec) { // sh_link field for SHT_GROUP sections should contain the section index of // the symbol table. - Sec->Link = InX::SymTab->OutSec->SectionIndex; + Sec->Link = InX::SymTab->getParent()->SectionIndex; // sh_info then contain index of an entry in symbol table section which // provides signature of the section group. @@ -135,7 +107,7 @@ template <class ELFT> void OutputSection::finalize() { // need to translate the InputSection sh_link to the OutputSection sh_link, // all InputSections in the OutputSection have the same dependency. if (auto *D = this->Sections.front()->getLinkOrderDep()) - this->Link = D->OutSec->SectionIndex; + this->Link = D->getParent()->SectionIndex; } uint32_t Type = this->Type; @@ -151,11 +123,11 @@ template <class ELFT> void OutputSection::finalize() { if (isa<SyntheticSection>(First)) return; - this->Link = InX::SymTab->OutSec->SectionIndex; + this->Link = InX::SymTab->getParent()->SectionIndex; // sh_info for SHT_REL[A] sections should contain the section header index of // the section to which the relocation applies. InputSectionBase *S = First->getRelocatedSection(); - this->Info = S->OutSec->SectionIndex; + Info = S->getOutputSection()->SectionIndex; } static uint64_t updateOffset(uint64_t Off, InputSection *S) { @@ -167,7 +139,7 @@ static uint64_t updateOffset(uint64_t Off, InputSection *S) { void OutputSection::addSection(InputSection *S) { assert(S->Live); Sections.push_back(S); - S->OutSec = this; + S->Parent = this; this->updateAlignment(S->Alignment); // The actual offsets will be computed by assignAddresses. For now, use @@ -351,7 +323,7 @@ static bool canMergeToProgbits(unsigned Type) { Type == SHT_NOTE; } -static void reportDiscarded(InputSectionBase *IS) { +void elf::reportDiscarded(InputSectionBase *IS) { if (!Config->PrintGcSections) return; message("removing unused section from '" + IS->Name + "' in file '" + @@ -437,8 +409,3 @@ template void OutputSection::finalize<ELF32LE>(); template void OutputSection::finalize<ELF32BE>(); template void OutputSection::finalize<ELF64LE>(); template void OutputSection::finalize<ELF64BE>(); - -template void OutputSection::maybeCompress<ELF32LE>(); -template void OutputSection::maybeCompress<ELF32BE>(); -template void OutputSection::maybeCompress<ELF64LE>(); -template void OutputSection::maybeCompress<ELF64BE>(); diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h index 08655a9ed67b..326348cd5a20 100644 --- a/ELF/OutputSections.h +++ b/ELF/OutputSections.h @@ -83,7 +83,6 @@ public: void sortInitFini(); void sortCtorsDtors(); template <class ELFT> void finalize(); - template <class ELFT> void maybeCompress(); void assignOffsets(); std::vector<InputSection *> Sections; @@ -149,6 +148,7 @@ private: }; uint64_t getHeaderSize(); +void reportDiscarded(InputSectionBase *IS); } // namespace elf } // namespace lld diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 5564ea246eeb..54cc6dd89d46 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -360,9 +360,9 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, // These expressions always compute a constant if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, - R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_PLT_PC, - R_TLSGD_PC, R_TLSGD, R_PPC_PLT_OPD, R_TLSDESC_CALL, - R_TLSDESC_PAGE, R_HINT>(E)) + R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, + R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD, + R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E)) return true; // These never do, except if the entire file is position dependent or if @@ -1015,7 +1015,7 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) { ThunkSection *TS = ThunkedSections.lookup(IS); if (TS) return TS; - auto *TOS = cast<OutputSection>(IS->OutSec); + auto *TOS = IS->getParent(); TS = make<ThunkSection>(TOS, IS->OutSecOff); ThunkSections[TOS].push_back(TS); ThunkedSections[IS] = TS; diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp index 4b77e35b9bae..02212fa8ba14 100644 --- a/ELF/ScriptParser.cpp +++ b/ELF/ScriptParser.cpp @@ -55,6 +55,7 @@ public: private: void addFile(StringRef Path); + OutputSection *checkSection(OutputSectionCommand *Cmd, StringRef Loccation); void readAsNeeded(); void readEntry(); @@ -564,8 +565,8 @@ uint32_t ScriptParser::readFill() { OutputSectionCommand * ScriptParser::readOutputSectionDescription(StringRef OutSec) { - OutputSectionCommand *Cmd = make<OutputSectionCommand>(OutSec); - Cmd->Location = getCurrentLocation(); + OutputSectionCommand *Cmd = + Script->createOutputSectionCommand(OutSec, getCurrentLocation()); // Read an address expression. // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html @@ -819,6 +820,16 @@ StringRef ScriptParser::readParenLiteral() { return Tok; } +OutputSection *ScriptParser::checkSection(OutputSectionCommand *Cmd, + StringRef Location) { + if (Cmd->Location.empty() && Script->ErrorOnMissingSection) + error(Location + ": undefined section " + Cmd->Name); + if (Cmd->Sec) + return Cmd->Sec; + static OutputSection Dummy("", 0, 0); + return &Dummy; +} + Expr ScriptParser::readPrimary() { if (peek() == "(") return readParenExpr(); @@ -847,9 +858,8 @@ Expr ScriptParser::readPrimary() { } if (Tok == "ADDR") { StringRef Name = readParenLiteral(); - return [=]() -> ExprValue { - return {Script->getOutputSection(Location, Name), 0}; - }; + OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); + return [=]() -> ExprValue { return {checkSection(Cmd, Location), 0}; }; } if (Tok == "ALIGN") { expect("("); @@ -867,7 +877,8 @@ Expr ScriptParser::readPrimary() { } if (Tok == "ALIGNOF") { StringRef Name = readParenLiteral(); - return [=] { return Script->getOutputSection(Location, Name)->Alignment; }; + OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); + return [=] { return checkSection(Cmd, Location)->Alignment; }; } if (Tok == "ASSERT") return readAssertExpr(); @@ -912,7 +923,8 @@ Expr ScriptParser::readPrimary() { } if (Tok == "LOADADDR") { StringRef Name = readParenLiteral(); - return [=] { return Script->getOutputSection(Location, Name)->getLMA(); }; + OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); + return [=] { return checkSection(Cmd, Location)->getLMA(); }; } if (Tok == "ORIGIN") { StringRef Name = readParenLiteral(); @@ -930,7 +942,11 @@ Expr ScriptParser::readPrimary() { } if (Tok == "SIZEOF") { StringRef Name = readParenLiteral(); - return [=] { return Script->getOutputSectionSize(Name); }; + OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); + // 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. + return [=] { return Cmd->Sec ? Cmd->Sec->Size : 0; }; } if (Tok == "SIZEOF_HEADERS") return [=] { return elf::getHeaderSize(); }; diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp index 7ce1f5354b1b..67e57d9c8f00 100644 --- a/ELF/Symbols.cpp +++ b/ELF/Symbols.cpp @@ -101,12 +101,12 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { case SymbolBody::DefinedCommonKind: if (!Config->DefineCommon) return 0; - return InX::Common->OutSec->Addr + InX::Common->OutSecOff + + return InX::Common->getParent()->Addr + InX::Common->OutSecOff + cast<DefinedCommon>(Body).Offset; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol>(Body); if (SS.NeedsCopy) - return SS.CopyRelSec->OutSec->Addr + SS.CopyRelSec->OutSecOff + + return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff + SS.CopyRelSecOff; if (SS.NeedsPltAddr) return Body.getPltVA(); @@ -207,13 +207,13 @@ OutputSection *SymbolBody::getOutputSection() const { if (auto *S = dyn_cast<SharedSymbol>(this)) { if (S->NeedsCopy) - return S->CopyRelSec->OutSec; + return S->CopyRelSec->getParent(); return nullptr; } if (isa<DefinedCommon>(this)) { if (Config->DefineCommon) - return InX::Common->OutSec; + return InX::Common->getParent(); return nullptr; } diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp index d3db32613a8a..223fc9a0fd07 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -48,8 +48,8 @@ using namespace lld; using namespace lld::elf; uint64_t SyntheticSection::getVA() const { - if (this->OutSec) - return this->OutSec->Addr + this->OutSecOff; + if (OutputSection *Sec = getParent()) + return Sec->Addr + OutSecOff; return 0; } @@ -367,8 +367,8 @@ BssSection::BssSection(StringRef Name) : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 0, Name) {} size_t BssSection::reserveSpace(uint64_t Size, uint32_t Alignment) { - if (OutSec) - OutSec->updateAlignment(Alignment); + if (OutputSection *Sec = getParent()) + Sec->updateAlignment(Alignment); this->Size = alignTo(this->Size, Alignment) + Size; this->Alignment = std::max(this->Alignment, Alignment); return this->Size - Size; @@ -494,7 +494,7 @@ void EhFrameSection<ELFT>::addSectionAux(EhInputSection *Sec, template <class ELFT> void EhFrameSection<ELFT>::addSection(InputSectionBase *C) { auto *Sec = cast<EhInputSection>(C); - Sec->EHSec = this; + Sec->Parent = this; updateAlignment(Sec->Alignment); Sections.push_back(Sec); for (auto *DS : Sec->DependentSections) @@ -579,7 +579,7 @@ uint64_t EhFrameSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff, if ((Enc & 0x70) == DW_EH_PE_absptr) return Addr; if ((Enc & 0x70) == DW_EH_PE_pcrel) - return Addr + this->OutSec->Addr + Off; + return Addr + getParent()->Addr + Off; fatal("unknown FDE size relative encoding"); } @@ -610,7 +610,7 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) { uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece); for (SectionPiece *Fde : Cie->FdePieces) { uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); - uint64_t FdeVA = this->OutSec->Addr + Fde->OutputOff; + uint64_t FdeVA = getParent()->Addr + Fde->OutputOff; In<ELFT>::EhFrameHdr->addFde(Pc, FdeVA); } } @@ -698,8 +698,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { // sections referenced by GOT relocations. Then later in the `finalize` // method calculate number of "pages" required to cover all saved output // section and allocate appropriate number of GOT entries. - auto *DefSym = cast<DefinedRegular>(&Sym); - PageIndexMap.insert({DefSym->Section->getOutputSection(), 0}); + PageIndexMap.insert({Sym.getOutputSection(), 0}); return; } if (Sym.isTls()) { @@ -766,8 +765,7 @@ static uint64_t getMipsPageCount(uint64_t Size) { uint64_t MipsGotSection::getPageEntryOffset(const SymbolBody &B, int64_t Addend) const { - const OutputSection *OutSec = - cast<DefinedRegular>(&B)->Section->getOutputSection(); + const OutputSection *OutSec = B.getOutputSection(); uint64_t SecAddr = getMipsPageAddr(OutSec->Addr); uint64_t SymAddr = getMipsPageAddr(B.getVA(Addend)); uint64_t Index = PageIndexMap.lookup(OutSec) + (SymAddr - SecAddr) / 0xffff; @@ -1071,11 +1069,11 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { if (this->Size) return; // Already finalized. - this->Link = InX::DynStrTab->OutSec->SectionIndex; - if (In<ELFT>::RelaDyn->OutSec->Size > 0) { + this->Link = InX::DynStrTab->getParent()->SectionIndex; + if (In<ELFT>::RelaDyn->getParent()->Size > 0) { bool IsRela = Config->IsRela; add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn}); - add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->OutSec->Size}); + add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->getParent()->Size}); add({IsRela ? DT_RELAENT : DT_RELENT, uint64_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); @@ -1088,9 +1086,9 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels}); } } - if (In<ELFT>::RelaPlt->OutSec->Size > 0) { + if (In<ELFT>::RelaPlt->getParent()->Size > 0) { add({DT_JMPREL, In<ELFT>::RelaPlt}); - add({DT_PLTRELSZ, In<ELFT>::RelaPlt->OutSec->Size}); + add({DT_PLTRELSZ, In<ELFT>::RelaPlt->getParent()->Size}); add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, InX::GotPlt}); add({DT_PLTREL, uint64_t(Config->IsRela ? DT_RELA : DT_REL)}); @@ -1152,7 +1150,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { add({DT_MIPS_RLD_MAP, InX::MipsRldMap}); } - this->OutSec->Link = this->Link; + getParent()->Link = this->Link; // +1 for DT_NULL this->Size = (Entries.size() + 1) * this->Entsize; @@ -1168,7 +1166,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { P->d_un.d_ptr = E.OutSec->Addr; break; case Entry::InSecAddr: - P->d_un.d_ptr = E.InSec->OutSec->Addr + E.InSec->OutSecOff; + P->d_un.d_ptr = E.InSec->getParent()->Addr + E.InSec->OutSecOff; break; case Entry::SecSize: P->d_un.d_val = E.OutSec->Size; @@ -1185,7 +1183,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { } uint64_t DynamicReloc::getOffset() const { - return InputSec->OutSec->Addr + InputSec->getOffset(OffsetInSec); + return InputSec->getOutputSection()->Addr + InputSec->getOffset(OffsetInSec); } int64_t DynamicReloc::getAddend() const { @@ -1258,11 +1256,11 @@ template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() { } template <class ELFT> void RelocationSection<ELFT>::finalizeContents() { - this->Link = InX::DynSymTab ? InX::DynSymTab->OutSec->SectionIndex - : InX::SymTab->OutSec->SectionIndex; + this->Link = InX::DynSymTab ? InX::DynSymTab->getParent()->SectionIndex + : InX::SymTab->getParent()->SectionIndex; // Set required output section properties. - this->OutSec->Link = this->Link; + getParent()->Link = this->Link; } SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec) @@ -1293,14 +1291,14 @@ static bool sortMipsSymbols(const SymbolTableEntry &L, // function. (For .dynsym, we don't do that because symbols for // dynamic linking are inherently all globals.) void SymbolTableBaseSection::finalizeContents() { - this->OutSec->Link = StrTabSec.OutSec->SectionIndex; + getParent()->Link = StrTabSec.getParent()->SectionIndex; // If it is a .dynsym, there should be no local symbols, but we need // to do a few things for the dynamic linker. if (this->Type == SHT_DYNSYM) { // Section's Info field has the index of the first non-local symbol. // Because the first symbol entry is a null entry, 1 is the first. - this->OutSec->Info = 1; + getParent()->Info = 1; if (InX::GnuHashTab) { // NB: It also sorts Symbols to meet the GNU hash table requirements. @@ -1326,7 +1324,7 @@ void SymbolTableBaseSection::postThunkContents() { S.Symbol->symbol()->computeBinding() == STB_LOCAL; }); size_t NumLocals = It - Symbols.begin(); - this->OutSec->Info = NumLocals + 1; + getParent()->Info = NumLocals + 1; } void SymbolTableBaseSection::addSymbol(SymbolBody *B) { @@ -1344,8 +1342,7 @@ size_t SymbolTableBaseSection::getSymbolIndex(SymbolBody *Body) { // This is used for -r, so we have to handle multiple section // symbols being combined. if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION) - return cast<DefinedRegular>(Body)->Section->getOutputSection() == - cast<DefinedRegular>(E.Symbol)->Section->getOutputSection(); + return Body->getOutputSection() == E.Symbol->getOutputSection(); return false; }); if (I == Symbols.end()) @@ -1456,7 +1453,7 @@ GnuHashTableSection::GnuHashTableSection() } void GnuHashTableSection::finalizeContents() { - this->OutSec->Link = InX::DynSymTab->OutSec->SectionIndex; + getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; // Computes bloom filter size in word size. We want to allocate 8 // bits for each symbol. It must be a power of two. @@ -1590,7 +1587,7 @@ HashTableSection<ELFT>::HashTableSection() } template <class ELFT> void HashTableSection<ELFT>::finalizeContents() { - this->OutSec->Link = InX::DynSymTab->OutSec->SectionIndex; + getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; unsigned NumEntries = 2; // nbucket and nchain. NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries. @@ -1801,7 +1798,7 @@ void GdbIndexSection::finalizeContents() { for (InputSectionBase *S : InputSections) if (InputSection *IS = dyn_cast<InputSection>(S)) - if (IS->OutSec && IS->Name == ".debug_info") + if (IS->getParent() && IS->Name == ".debug_info") readDwarf(IS); SymbolTable.finalizeContents(); @@ -1846,7 +1843,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { // Write the address area. for (AddressEntry &E : AddressArea) { - uint64_t BaseAddr = E.Section->OutSec->Addr + E.Section->getOffset(0); + uint64_t BaseAddr = E.Section->getParent()->Addr + E.Section->getOffset(0); write64le(Buf, BaseAddr + E.LowAddress); write64le(Buf + 8, BaseAddr + E.HighAddress); write32le(Buf + 16, E.CuIndex); @@ -1906,7 +1903,7 @@ template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) { Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; Buf[2] = DW_EH_PE_udata4; Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; - write32<E>(Buf + 4, In<ELFT>::EhFrame->OutSec->Addr - this->getVA() - 4); + write32<E>(Buf + 4, In<ELFT>::EhFrame->getParent()->Addr - this->getVA() - 4); write32<E>(Buf + 8, Fdes.size()); Buf += 12; @@ -1948,12 +1945,12 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() { for (VersionDefinition &V : Config->VersionDefinitions) V.NameOff = InX::DynStrTab->addString(V.Name); - this->OutSec->Link = InX::DynStrTab->OutSec->SectionIndex; + getParent()->Link = InX::DynStrTab->getParent()->SectionIndex; // sh_info should be set to the number of definitions. This fact is missed in // documentation, but confirmed by binutils community: // https://sourceware.org/ml/binutils/2014-11/msg00355.html - this->OutSec->Info = getVerDefNum(); + getParent()->Info = getVerDefNum(); } template <class ELFT> @@ -2001,7 +1998,7 @@ VersionTableSection<ELFT>::VersionTableSection() template <class ELFT> void VersionTableSection<ELFT>::finalizeContents() { // At the moment of june 2016 GNU docs does not mention that sh_link field // should be set, but Sun docs do. Also readelf relies on this field. - this->OutSec->Link = InX::DynSymTab->OutSec->SectionIndex; + getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; } template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const { @@ -2093,8 +2090,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) { } template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { - this->OutSec->Link = InX::DynStrTab->OutSec->SectionIndex; - this->OutSec->Info = Needed.size(); + getParent()->Link = InX::DynStrTab->getParent()->SectionIndex; + getParent()->Info = Needed.size(); } template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const { @@ -2115,7 +2112,7 @@ MergeSyntheticSection::MergeSyntheticSection(StringRef Name, uint32_t Type, void MergeSyntheticSection::addSection(MergeInputSection *MS) { assert(!Finalized); - MS->MergeSec = this; + MS->Parent = this; Sections.push_back(MS); } @@ -2186,13 +2183,23 @@ ARMExidxSentinelSection::ARMExidxSentinelSection() // This section will have been sorted last in the .ARM.exidx table. // This table entry will have the form: // | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND | +// The sentinel must have the PREL31 value of an address higher than any +// address described by any other table entry. void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { - // Get the InputSection before us, we are by definition last - auto RI = this->OutSec->Sections.rbegin(); - InputSection *LE = *(++RI); - InputSection *LC = cast<InputSection>(LE->getLinkOrderDep()); - uint64_t S = LC->OutSec->Addr + LC->getOffset(LC->getSize()); - uint64_t P = this->getVA(); + // The Sections are sorted in order of ascending PREL31 address with the + // sentinel last. We need to find the InputSection that precedes the + // sentinel. By construction the Sentinel is in the last + // InputSectionDescription as the InputSection that precedes it. + OutputSectionCommand *C = Script->getCmd(getParent()); + auto ISD = std::find_if(C->Commands.rbegin(), C->Commands.rend(), + [](const BaseCommand *Base) { + return isa<InputSectionDescription>(Base); + }); + auto L = cast<InputSectionDescription>(*ISD); + InputSection *Highest = L->Sections[L->Sections.size() - 2]; + InputSection *LS = Highest->getLinkOrderDep(); + uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize()); + uint64_t P = getVA(); Target->relocateOne(Buf, R_ARM_PREL31, S - P); write32le(Buf + 4, 0x1); } @@ -2200,7 +2207,7 @@ void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, Config->Wordsize, ".text.thunk") { - this->OutSec = OS; + this->Parent = OS; this->OutSecOff = Off; } diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h index 61cc03de222e..b47d2fab24ec 100644 --- a/ELF/SyntheticSections.h +++ b/ELF/SyntheticSections.h @@ -53,7 +53,7 @@ public: virtual bool empty() const { return false; } uint64_t getVA() const; - static bool classof(const InputSectionBase *D) { + static bool classof(const SectionBase *D) { return D->kind() == InputSectionBase::Synthetic; } }; diff --git a/ELF/Target.cpp b/ELF/Target.cpp index cf7d912ad829..b6c6e7089365 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -62,10 +62,10 @@ static void or32be(uint8_t *P, int32_t V) { write32be(P, read32be(P) | V); } template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) { for (InputSectionBase *D : InputSections) { auto *IS = dyn_cast_or_null<InputSection>(D); - if (!IS || !IS->OutSec) + if (!IS || !IS->getParent()) continue; - uint8_t *ISLoc = cast<OutputSection>(IS->OutSec)->Loc + IS->OutSecOff; + uint8_t *ISLoc = IS->getParent()->Loc + IS->OutSecOff; if (ISLoc <= Loc && Loc < ISLoc + IS->getSize()) return IS->template getLocation<ELFT>(Loc - ISLoc) + ": "; } diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 77d6412f80ad..258d5e26ef7f 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -261,23 +261,26 @@ template <class ELFT> void Writer<ELFT>::run() { if (!Config->Relocatable) fixSectionAlignments(); Script->fabricateDefaultCommands(); + } else { + Script->synchronize(); } for (BaseCommand *Base : Script->Opt.Commands) if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) OutputSectionCommands.push_back(Cmd); + clearOutputSections(); // 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>(); }); + parallelForEach( + OutputSectionCommands.begin(), OutputSectionCommands.end(), + [](OutputSectionCommand *Cmd) { Cmd->maybeCompress<ELFT>(); }); if (Config->Relocatable) { assignFileOffsets(); } else { - Script->synchronize(); - Script->assignAddresses(Phdrs); + Script->assignAddresses(Phdrs, OutputSectionCommands); // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a // 0 sized region. This has to be done late since only after assignAddresses @@ -300,13 +303,13 @@ template <class ELFT> void Writer<ELFT>::run() { openFile(); if (ErrorCount) return; + if (!Config->OFormatBinary) { writeHeader(); writeSections(); } else { writeSectionsBinary(); } - clearOutputSections(); // Backfill .note.gnu.build-id section content. This is done at last // because the content is usually a hash value of the entire output file. @@ -613,27 +616,27 @@ bool elf::isRelroSection(const OutputSection *Sec) { // .got contains pointers to external symbols. They are resolved by // the dynamic linker when a module is loaded into memory, and after // that they are not expected to change. So, it can be in RELRO. - if (InX::Got && Sec == InX::Got->OutSec) + if (InX::Got && Sec == InX::Got->getParent()) return true; // .got.plt contains pointers to external function symbols. They are // by default resolved lazily, so we usually cannot put it into RELRO. // However, if "-z now" is given, the lazy symbol resolution is // disabled, which enables us to put it into RELRO. - if (Sec == InX::GotPlt->OutSec) + if (Sec == InX::GotPlt->getParent()) return Config->ZNow; // .dynamic section contains data for the dynamic linker, and // there's no need to write to it at runtime, so it's better to put // it into RELRO. - if (Sec == InX::Dynamic->OutSec) + if (Sec == InX::Dynamic->getParent()) return true; // .bss.rel.ro is used for copy relocations for read-only symbols. // Since the dynamic linker needs to process copy relocations, the // section cannot be read-only, but once initialized, they shouldn't // change. - if (Sec == InX::BssRelRo->OutSec) + if (Sec == InX::BssRelRo->getParent()) return true; // Sections with some special names are put into RELRO. This is a @@ -1112,9 +1115,9 @@ template <class ELFT> void Writer<ELFT>::sortSections() { static void applySynthetic(const std::vector<SyntheticSection *> &Sections, std::function<void(SyntheticSection *)> Fn) { for (SyntheticSection *SS : Sections) - if (SS && SS->OutSec && !SS->empty()) { + if (SS && SS->getParent() && !SS->empty()) { Fn(SS); - SS->OutSec->assignOffsets(); + SS->getParent()->assignOffsets(); } } @@ -1130,16 +1133,15 @@ static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) { SyntheticSection *SS = dyn_cast<SyntheticSection>(S); if (!SS) return; - if (!SS->empty() || !SS->OutSec) + OutputSection *OS = SS->getParent(); + if (!SS->empty() || !OS) continue; - - SS->OutSec->Sections.erase(std::find(SS->OutSec->Sections.begin(), - SS->OutSec->Sections.end(), SS)); + OS->Sections.erase(std::find(OS->Sections.begin(), OS->Sections.end(), SS)); SS->Live = false; // If there are no other sections in the output section, remove it from the // output. - if (SS->OutSec->Sections.empty()) - V.erase(std::find(V.begin(), V.end(), SS->OutSec)); + if (OS->Sections.empty()) + V.erase(std::find(V.begin(), V.end(), OS)); } } @@ -1427,8 +1429,8 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { // Add an entry for .dynamic. if (InX::DynSymTab) - AddHdr(PT_DYNAMIC, InX::Dynamic->OutSec->getPhdrFlags()) - ->add(InX::Dynamic->OutSec); + AddHdr(PT_DYNAMIC, InX::Dynamic->getParent()->getPhdrFlags()) + ->add(InX::Dynamic->getParent()); // PT_GNU_RELRO includes all sections that should be marked as // read-only by dynamic linker after proccessing relocations. @@ -1441,9 +1443,9 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. if (!In<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr && - In<ELFT>::EhFrame->OutSec && In<ELFT>::EhFrameHdr->OutSec) - AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->OutSec->getPhdrFlags()) - ->add(In<ELFT>::EhFrameHdr->OutSec); + In<ELFT>::EhFrame->getParent() && In<ELFT>::EhFrameHdr->getParent()) + AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->getParent()->getPhdrFlags()) + ->add(In<ELFT>::EhFrameHdr->getParent()); // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes // the dynamic linker fill the segment with random data. @@ -1556,9 +1558,11 @@ static uint64_t setOffset(OutputSection *Sec, uint64_t Off) { template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { uint64_t Off = 0; - for (OutputSection *Sec : OutputSections) + for (OutputSectionCommand *Cmd : OutputSectionCommands) { + OutputSection *Sec = Cmd->Sec; if (Sec->Flags & SHF_ALLOC) Off = setOffset(Sec, Off); + } FileSize = alignTo(Off, Config->Wordsize); } @@ -1568,11 +1572,12 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { Off = setOffset(Out::ElfHeader, Off); Off = setOffset(Out::ProgramHeaders, Off); - for (OutputSection *Sec : OutputSections) - Off = setOffset(Sec, Off); + for (OutputSectionCommand *Cmd : OutputSectionCommands) + Off = setOffset(Cmd->Sec, Off); SectionHeaderOff = alignTo(Off, Config->Wordsize); - FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr); + FileSize = + SectionHeaderOff + (OutputSectionCommands.size() + 1) * sizeof(Elf_Shdr); } // Finalize the program headers. We call this function after we assign @@ -1695,16 +1700,15 @@ template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() { // Setup MIPS _gp_disp/__gnu_local_gp symbols which should // be equal to the _gp symbol's value. - if (Config->EMachine == EM_MIPS) { - if (!ElfSym::MipsGp->Value) { - // Find GP-relative section with the lowest address - // and use this address to calculate default _gp value. - uint64_t Gp = -1; - for (const OutputSection *OS : OutputSections) - if ((OS->Flags & SHF_MIPS_GPREL) && OS->Addr < Gp) - Gp = OS->Addr; - if (Gp != (uint64_t)-1) - ElfSym::MipsGp->Value = Gp + 0x7ff0; + if (Config->EMachine == EM_MIPS && !ElfSym::MipsGp->Value) { + // Find GP-relative section with the lowest address + // and use this address to calculate default _gp value. + for (const OutputSectionCommand *Cmd : OutputSectionCommands) { + OutputSection *OS = Cmd->Sec; + if (OS->Flags & SHF_MIPS_GPREL) { + ElfSym::MipsGp->Value = OS->Addr + 0x7ff0; + break; + } } } } @@ -1728,7 +1732,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { EHdr->e_phnum = Phdrs.size(); EHdr->e_shentsize = sizeof(Elf_Shdr); EHdr->e_shnum = OutputSectionCommands.size() + 1; - EHdr->e_shstrndx = InX::ShStrTab->OutSec->SectionIndex; + EHdr->e_shstrndx = InX::ShStrTab->getParent()->SectionIndex; if (Config->EMachine == EM_ARM) // We don't currently use any features incompatible with EF_ARM_EABI_VER5, @@ -1804,7 +1808,7 @@ template <class ELFT> void Writer<ELFT>::writeSections() { OutputSection *EhFrameHdr = (In<ELFT>::EhFrameHdr && !In<ELFT>::EhFrameHdr->empty()) - ? In<ELFT>::EhFrameHdr->OutSec + ? In<ELFT>::EhFrameHdr->getParent() : nullptr; // In -r or -emit-relocs mode, write the relocation sections first as in @@ -1832,7 +1836,7 @@ template <class ELFT> void Writer<ELFT>::writeSections() { } template <class ELFT> void Writer<ELFT>::writeBuildId() { - if (!InX::BuildId || !InX::BuildId->OutSec) + if (!InX::BuildId || !InX::BuildId->getParent()) return; // Compute a hash of all sections of the output file. diff --git a/test/ELF/gc-absolute.s b/test/ELF/gc-absolute.s new file mode 100644 index 000000000000..29e671678ee7 --- /dev/null +++ b/test/ELF/gc-absolute.s @@ -0,0 +1,7 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: ld.lld %t -o %t2 -shared --gc-sections + +.global foo +foo = 0x123 diff --git a/test/ELF/i386-gotpc-dynamic.s b/test/ELF/i386-gotpc-dynamic.s new file mode 100644 index 000000000000..da8a607d5753 --- /dev/null +++ b/test/ELF/i386-gotpc-dynamic.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t.so -shared +# RUN: llvm-readobj -s %t.so | FileCheck %s +# RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s + +# CHECK: Section { +# CHECK: Index: 7 +# CHECK-NEXT: Name: .got +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x2030 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } + +## 0x1000 + 4144 = 0x2030 +# DISASM: 1000: {{.*}} movl $4144, %eax + +.section .foo,"ax",@progbits +foo: + movl $bar@got-., %eax # R_386_GOTPC + +.local bar +bar: diff --git a/test/ELF/mips64-eh-abs-reloc.s b/test/ELF/mips64-eh-abs-reloc.s new file mode 100644 index 000000000000..7bc500137992 --- /dev/null +++ b/test/ELF/mips64-eh-abs-reloc.s @@ -0,0 +1,38 @@ +# Having an R_MIPS_64 relocation in eh_frame would previously crash LLD +# REQUIRES: mips +# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %s -o %t.o +# RUN: llvm-readobj -r %t.o | FileCheck %s -check-prefix OBJ +# RUN: ld.lld --eh-frame-hdr -shared -z notext -o %t.so %t.o +# RUN: llvm-readobj -r %t.so | FileCheck %s -check-prefix PIC-RELOCS + +# Linking this as a PIE executable would also previously crash +# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %S/Inputs/archive2.s -o %t-foo.o +# -pie needs -z notext because of the R_MIPS_64 relocation +# RUN: ld.lld --eh-frame-hdr -Bdynamic -pie -z notext -o %t-pie-dynamic.exe %t.o %t-foo.o +# RUN: llvm-readobj -r %t-pie-dynamic.exe | FileCheck %s -check-prefix PIC-RELOCS + + +# OBJ: Section ({{.*}}) .rela.text { +# OBJ-NEXT: 0x0 R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 foo 0x0 +# OBJ-NEXT: } +# OBJ-NEXT: Section ({{.*}}) .rela.eh_frame { +# OBJ-NEXT: 0x1C R_MIPS_64/R_MIPS_NONE/R_MIPS_NONE .text 0x0 +# OBJ-NEXT: } + +# PIC-RELOCS: Relocations [ +# PIC-RELOCS-NEXT: Section (7) .rela.dyn { +# PIC-RELOCS-NEXT: {{0x.+}} R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE - 0x10000 +# PIC-RELOCS-NEXT: } +# PIC-RELOCS-NEXT:] + + +.globl foo + +bar: +.cfi_startproc +lui $11, %hi(%neg(%gp_rel(foo))) +.cfi_endproc + +.globl __start +__start: +b bar diff --git a/test/ELF/section-metadata-err.s b/test/ELF/section-metadata-err.s new file mode 100644 index 000000000000..f3b5842945cb --- /dev/null +++ b/test/ELF/section-metadata-err.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s + +# CHECK: error: Merge and .eh_frame sections are not supported with SHF_LINK_ORDER {{.*}}section-metadata-err.s.tmp.o:(.foo) + +.global _start +_start: +.quad .foo + +.section .foo,"aM",@progbits,8 +.quad 0 + +.section bar,"ao",@progbits,.foo |