diff options
-rw-r--r-- | lld/ELF/OutputSections.cpp | 29 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 7 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 22 |
3 files changed, 28 insertions, 30 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index b57bd2c011b..29afbf3d8ae 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -739,7 +739,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, Sec->getVA() - this->getVA() - 4); + write32<E>(Buf + 4, Out<ELFT>::EhFrame->getVA() - this->getVA() - 4); write32<E>(Buf + 8, Fdes.size()); Buf += 12; @@ -752,14 +752,6 @@ template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) { } template <class ELFT> -void EhFrameHeader<ELFT>::add(EhOutputSection<ELFT> *Sec) { - assert((!this->Sec || this->Sec == Sec) && - "multiple .eh_frame sections not supported for .eh_frame_hdr"); - Live = Config->EhFrameHdr; - this->Sec = Sec; -} - -template <class ELFT> void EhFrameHeader<ELFT>::addFde(uint32_t Pc, uint32_t FdeVA) { Fdes.push_back({Pc, FdeVA}); } @@ -922,9 +914,7 @@ template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> EhOutputSection<ELFT>::EhOutputSection() - : OutputSectionBase<ELFT>(".eh_frame", SHT_PROGBITS, SHF_ALLOC) { - Out<ELFT>::EhFrameHdr->add(this); -} + : OutputSectionBase<ELFT>(".eh_frame", SHT_PROGBITS, SHF_ALLOC) {} template <class ELFT> void EhOutputSection<ELFT>::forEachInputSection( @@ -1118,7 +1108,8 @@ void EhOutputSection<ELFT>::addSectionAux(EHInputSection<ELFT> *Sec, if (!isFdeLive(FdePiece, Sec, Rels)) continue; Cie->FdePieces.push_back(&FdePiece); - Out<ELFT>::EhFrameHdr->reserveFde(); + if (Out<ELFT>::EhFrameHdr) + Out<ELFT>::EhFrameHdr->reserveFde(); } } @@ -1229,11 +1220,13 @@ template <class ELFT> void EhOutputSection<ELFT>::writeTo(uint8_t *Buf) { // Construct .eh_frame_hdr. .eh_frame_hdr is a binary search table // to get a FDE from an address to which FDE is applied to. So here // we obtain two addresses and pass them to EhFrameHdr object. - for (CieRecord *Cie : Cies) { - for (SectionPiece *Fde : Cie->FdePieces) { - uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Cie->FdeEncoding); - uintX_t FdeVA = this->getVA() + Fde->OutputOff; - Out<ELFT>::EhFrameHdr->addFde(Pc, FdeVA); + if (Out<ELFT>::EhFrameHdr) { + for (CieRecord *Cie : Cies) { + for (SectionPiece *Fde : Cie->FdePieces) { + uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Cie->FdeEncoding); + uintX_t FdeVA = this->getVA() + Fde->OutputOff; + Out<ELFT>::EhFrameHdr->addFde(Pc, FdeVA); + } } } } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index b5929aca805..8deba71ff1d 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -343,6 +343,7 @@ public: EhOutputSection(); void writeTo(uint8_t *Buf) override; void finalize() override; + bool empty() const { return Sections.empty(); } void forEachInputSection(std::function<void(InputSectionBase<ELFT> *)> F) override; @@ -543,10 +544,6 @@ public: void add(EhOutputSection<ELFT> *Sec); void reserveFde(); - bool Live = false; - - EhOutputSection<ELFT> *Sec = nullptr; - private: struct FdeData { uint32_t Pc; @@ -603,6 +600,7 @@ template <class ELFT> struct Out { static BuildIdSection<ELFT> *BuildId; static DynamicSection<ELFT> *Dynamic; static EhFrameHeader<ELFT> *EhFrameHdr; + static EhOutputSection<ELFT> *EhFrame; static GnuHashTableSection<ELFT> *GnuHashTab; static GotPltSection<ELFT> *GotPlt; static GotSection<ELFT> *Got; @@ -630,6 +628,7 @@ template <class ELFT> struct Out { template <class ELFT> BuildIdSection<ELFT> *Out<ELFT>::BuildId; template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic; template <class ELFT> EhFrameHeader<ELFT> *Out<ELFT>::EhFrameHdr; +template <class ELFT> EhOutputSection<ELFT> *Out<ELFT>::EhFrame; template <class ELFT> GnuHashTableSection<ELFT> *Out<ELFT>::GnuHashTab; template <class ELFT> GotPltSection<ELFT> *Out<ELFT>::GotPlt; template <class ELFT> GotSection<ELFT> *Out<ELFT>::Got; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index e985175f08b..8927ea7d0b6 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -130,7 +130,7 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) { // Create singleton output sections. DynamicSection<ELFT> Dynamic(*Symtab); - EhFrameHeader<ELFT> EhFrameHdr; + EhOutputSection<ELFT> EhFrame; GotSection<ELFT> Got; InterpSection<ELFT> Interp; PltSection<ELFT> Plt; @@ -149,6 +149,7 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) { // Instantiate optional output sections if they are needed. std::unique_ptr<BuildIdSection<ELFT>> BuildId; + std::unique_ptr<EhFrameHeader<ELFT>> EhFrameHdr; std::unique_ptr<GnuHashTableSection<ELFT>> GnuHashTab; std::unique_ptr<GotPltSection<ELFT>> GotPlt; std::unique_ptr<HashTableSection<ELFT>> HashTab; @@ -166,6 +167,9 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) { else if (Config->BuildId == BuildIdKind::Hexstring) BuildId.reset(new BuildIdHexstring<ELFT>); + if (Config->EhFrameHdr) + EhFrameHdr.reset(new EhFrameHeader<ELFT>); + if (Config->GnuHash) GnuHashTab.reset(new GnuHashTableSection<ELFT>); if (Config->SysvHash) @@ -192,7 +196,8 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) { Out<ELFT>::DynStrTab = &DynStrTab; Out<ELFT>::DynSymTab = &DynSymTab; Out<ELFT>::Dynamic = &Dynamic; - Out<ELFT>::EhFrameHdr = &EhFrameHdr; + Out<ELFT>::EhFrame = &EhFrame; + Out<ELFT>::EhFrameHdr = EhFrameHdr.get(); Out<ELFT>::GnuHashTab = GnuHashTab.get(); Out<ELFT>::Got = &Got; Out<ELFT>::GotPlt = GotPlt.get(); @@ -1174,8 +1179,7 @@ OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C, Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags); break; case InputSectionBase<ELFT>::EHFrame: - Sec = new EhOutputSection<ELFT>; - break; + return {Out<ELFT>::EhFrame, false}; case InputSectionBase<ELFT>::Merge: Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags, Key.Alignment); @@ -1368,8 +1372,10 @@ template <class ELFT> void Writer<ELFT>::createSections() { // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); - if (Out<ELFT>::EhFrameHdr->Sec) - Out<ELFT>::EhFrameHdr->Sec->finalize(); + if (!Out<ELFT>::EhFrame->empty()) { + OutputSections.push_back(Out<ELFT>::EhFrame); + Out<ELFT>::EhFrame->finalize(); + } // Scan relocations. This must be done after every symbol is declared so that // we can correctly decide if a dynamic relocation is needed. @@ -1515,7 +1521,7 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { Add(Out<ELFT>::GotPlt); if (!Out<ELFT>::Plt->empty()) Add(Out<ELFT>::Plt); - if (Out<ELFT>::EhFrameHdr->Live) + if (!Out<ELFT>::EhFrame->empty()) Add(Out<ELFT>::EhFrameHdr); } @@ -1662,7 +1668,7 @@ template <class ELFT> void Writer<ELFT>::createPhdrs() { Phdrs.push_back(std::move(RelRo)); // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. - if (Out<ELFT>::EhFrameHdr->Live) { + if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr) { Phdr &Hdr = *AddHdr(PT_GNU_EH_FRAME, toPhdrFlags(Out<ELFT>::EhFrameHdr->getFlags())); AddSec(Hdr, Out<ELFT>::EhFrameHdr); |