Convert EhOutputSection to be a synthetic section.

With this we complete the transition out of special output sections,
and with the previous patches it should be possible to merge
OutputSectionBase and OuputSection.

llvm-svn: 296023
This commit is contained in:
Rafael Espindola 2017-02-23 22:06:28 +00:00
parent e199f285b0
commit 66b4e21534
9 changed files with 282 additions and 278 deletions

View File

@ -121,6 +121,8 @@ template <class ELFT>
OutputSectionBase *InputSectionBase::getOutputSection() const {
if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(this))
return MS->MergeSec ? MS->MergeSec->OutSec : nullptr;
if (auto *EH = dyn_cast<EhInputSection<ELFT>>(this))
return EH->EHSec->OutSec;
return OutSec;
}
@ -499,7 +501,7 @@ void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {
uint8_t *BufLoc = Buf + Offset;
uint32_t Type = Rel.Type;
uintX_t AddrLoc = OutSec->Addr + Offset;
uintX_t AddrLoc = getOutputSection<ELFT>()->Addr + Offset;
RelExpr Expr = Rel.Expr;
uint64_t TargetVA = SignExtend64<Bits>(
getRelocTargetVA<ELFT>(Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr));

View File

@ -28,6 +28,7 @@ class SymbolBody;
struct SectionPiece;
template <class ELFT> class DefinedRegular;
template <class ELFT> class EhFrameSection;
template <class ELFT> class MergeSyntheticSection;
template <class ELFT> class ObjectFile;
template <class ELFT> class OutputSection;
@ -244,6 +245,7 @@ public:
// Splittable sections are handled as a sequence of data
// rather than a single large blob of data.
std::vector<EhSectionPiece> Pieces;
EhFrameSection<ELFT> *EHSec = nullptr;
};
// This corresponds to a non SHF_MERGE section of an input file.

View File

@ -9,7 +9,6 @@
#include "OutputSections.h"
#include "Config.h"
#include "EhFrame.h"
#include "LinkerScript.h"
#include "Memory.h"
#include "Strings.h"
@ -269,217 +268,6 @@ template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
Script<ELFT>::X->writeDataBytes(this->Name, Buf);
}
template <class ELFT>
EhOutputSection<ELFT>::EhOutputSection()
: OutputSectionBase(".eh_frame", SHT_PROGBITS, SHF_ALLOC) {}
template <class ELFT>
void EhOutputSection<ELFT>::forEachInputSection(
std::function<void(InputSectionBase *)> F) {
for (EhInputSection<ELFT> *S : Sections)
F(S);
}
// Search for an existing CIE record or create a new one.
// CIE records from input object files are uniquified by their contents
// and where their relocations point to.
template <class ELFT>
template <class RelTy>
CieRecord *EhOutputSection<ELFT>::addCie(EhSectionPiece &Piece,
ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection<ELFT>>(Piece.ID);
const endianness E = ELFT::TargetEndianness;
if (read32<E>(Piece.data().data() + 4) != 0)
fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame");
SymbolBody *Personality = nullptr;
unsigned FirstRelI = Piece.FirstRelocation;
if (FirstRelI != (unsigned)-1)
Personality =
&Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);
// Search for an existing CIE by CIE contents/relocation target pair.
CieRecord *Cie = &CieMap[{Piece.data(), Personality}];
// If not found, create a new one.
if (Cie->Piece == nullptr) {
Cie->Piece = &Piece;
Cies.push_back(Cie);
}
return Cie;
}
// There is one FDE per function. Returns true if a given FDE
// points to a live function.
template <class ELFT>
template <class RelTy>
bool EhOutputSection<ELFT>::isFdeLive(EhSectionPiece &Piece,
ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection<ELFT>>(Piece.ID);
unsigned FirstRelI = Piece.FirstRelocation;
if (FirstRelI == (unsigned)-1)
return false;
const RelTy &Rel = Rels[FirstRelI];
SymbolBody &B = Sec->template getFile<ELFT>()->getRelocTargetSym(Rel);
auto *D = dyn_cast<DefinedRegular<ELFT>>(&B);
if (!D || !D->Section)
return false;
InputSectionBase *Target = D->Section->Repl;
return Target && Target->Live;
}
// .eh_frame is a sequence of CIE or FDE records. In general, there
// is one CIE record per input object file which is followed by
// a list of FDEs. This function searches an existing CIE or create a new
// one and associates FDEs to the CIE.
template <class ELFT>
template <class RelTy>
void EhOutputSection<ELFT>::addSectionAux(EhInputSection<ELFT> *Sec,
ArrayRef<RelTy> Rels) {
const endianness E = ELFT::TargetEndianness;
DenseMap<size_t, CieRecord *> OffsetToCie;
for (EhSectionPiece &Piece : Sec->Pieces) {
// The empty record is the end marker.
if (Piece.size() == 4)
return;
size_t Offset = Piece.InputOff;
uint32_t ID = read32<E>(Piece.data().data() + 4);
if (ID == 0) {
OffsetToCie[Offset] = addCie(Piece, Rels);
continue;
}
uint32_t CieOffset = Offset + 4 - ID;
CieRecord *Cie = OffsetToCie[CieOffset];
if (!Cie)
fatal(toString(Sec) + ": invalid CIE reference");
if (!isFdeLive(Piece, Rels))
continue;
Cie->FdePieces.push_back(&Piece);
NumFdes++;
}
}
template <class ELFT>
void EhOutputSection<ELFT>::addSection(InputSectionBase *C) {
auto *Sec = cast<EhInputSection<ELFT>>(C);
Sec->OutSec = this;
this->updateAlignment(Sec->Alignment);
Sections.push_back(Sec);
// .eh_frame is a sequence of CIE or FDE records. This function
// splits it into pieces so that we can call
// SplitInputSection::getSectionPiece on the section.
Sec->split();
if (Sec->Pieces.empty())
return;
if (Sec->NumRelocations) {
if (Sec->AreRelocsRela)
addSectionAux(Sec, Sec->template relas<ELFT>());
else
addSectionAux(Sec, Sec->template rels<ELFT>());
return;
}
addSectionAux(Sec, makeArrayRef<Elf_Rela>(nullptr, nullptr));
}
template <class ELFT>
static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
memcpy(Buf, D.data(), D.size());
// Fix the size field. -4 since size does not include the size field itself.
const endianness E = ELFT::TargetEndianness;
write32<E>(Buf, alignTo(D.size(), sizeof(typename ELFT::uint)) - 4);
}
template <class ELFT> void EhOutputSection<ELFT>::finalize() {
if (this->Size)
return; // Already finalized.
size_t Off = 0;
for (CieRecord *Cie : Cies) {
Cie->Piece->OutputOff = Off;
Off += alignTo(Cie->Piece->size(), sizeof(uintX_t));
for (EhSectionPiece *Fde : Cie->FdePieces) {
Fde->OutputOff = Off;
Off += alignTo(Fde->size(), sizeof(uintX_t));
}
}
this->Size = Off;
}
template <class ELFT> static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
const endianness E = ELFT::TargetEndianness;
switch (Size) {
case DW_EH_PE_udata2:
return read16<E>(Buf);
case DW_EH_PE_udata4:
return read32<E>(Buf);
case DW_EH_PE_udata8:
return read64<E>(Buf);
case DW_EH_PE_absptr:
if (ELFT::Is64Bits)
return read64<E>(Buf);
return read32<E>(Buf);
}
fatal("unknown FDE size encoding");
}
// Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to.
// We need it to create .eh_frame_hdr section.
template <class ELFT>
typename ELFT::uint EhOutputSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff,
uint8_t Enc) {
// The starting address to which this FDE applies is
// stored at FDE + 8 byte.
size_t Off = FdeOff + 8;
uint64_t Addr = readFdeAddr<ELFT>(Buf + Off, Enc & 0x7);
if ((Enc & 0x70) == DW_EH_PE_absptr)
return Addr;
if ((Enc & 0x70) == DW_EH_PE_pcrel)
return Addr + this->Addr + Off;
fatal("unknown FDE size relative encoding");
}
template <class ELFT> void EhOutputSection<ELFT>::writeTo(uint8_t *Buf) {
const endianness E = ELFT::TargetEndianness;
for (CieRecord *Cie : Cies) {
size_t CieOffset = Cie->Piece->OutputOff;
writeCieFde<ELFT>(Buf + CieOffset, Cie->Piece->data());
for (EhSectionPiece *Fde : Cie->FdePieces) {
size_t Off = Fde->OutputOff;
writeCieFde<ELFT>(Buf + Off, Fde->data());
// FDE's second word should have the offset to an associated CIE.
// Write it.
write32<E>(Buf + Off + 4, Off + 4 - CieOffset);
}
}
for (EhInputSection<ELFT> *S : Sections)
S->template relocate<ELFT>(Buf, nullptr);
// Construct .eh_frame_hdr. .eh_frame_hdr is a binary search table
// to get a FDE from an address to which FDE is applied. So here
// we obtain two addresses and pass them to EhFrameHdr object.
if (In<ELFT>::EhFrameHdr) {
for (CieRecord *Cie : Cies) {
uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece);
for (SectionPiece *Fde : Cie->FdePieces) {
uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
uintX_t FdeVA = this->Addr + Fde->OutputOff;
In<ELFT>::EhFrameHdr->addFde(Pc, FdeVA);
}
}
}
}
template <class ELFT>
static typename ELFT::uint getOutFlags(InputSectionBase *S) {
return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
@ -596,7 +384,7 @@ void OutputSectionFactory<ELFT>::addInputSec(InputSectionBase *IS,
} else {
uint32_t Type = IS->Type;
if (IS->kind() == InputSectionBase::EHFrame) {
Out<ELFT>::EhFrame->addSection(IS);
In<ELFT>::EhFrame->addSection(IS);
return;
}
Sec = make<OutputSection<ELFT>>(Key.Name, Type, Flags);
@ -639,11 +427,6 @@ template class OutputSection<ELF32BE>;
template class OutputSection<ELF64LE>;
template class OutputSection<ELF64BE>;
template class EhOutputSection<ELF32LE>;
template class EhOutputSection<ELF32BE>;
template class EhOutputSection<ELF64LE>;
template class EhOutputSection<ELF64BE>;
template class OutputSectionFactory<ELF32LE>;
template class OutputSectionFactory<ELF32BE>;
template class OutputSectionFactory<ELF64LE>;

View File

@ -129,52 +129,6 @@ public:
uint8_t *Loc = nullptr;
};
struct CieRecord {
EhSectionPiece *Piece = nullptr;
std::vector<EhSectionPiece *> FdePieces;
};
// Output section for .eh_frame.
template <class ELFT> class EhOutputSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
typedef typename ELFT::Shdr Elf_Shdr;
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Rela Elf_Rela;
public:
EhOutputSection();
void writeTo(uint8_t *Buf) override;
void finalize() override;
bool empty() const { return Sections.empty(); }
void forEachInputSection(std::function<void(InputSectionBase *)> F) override;
void addSection(InputSectionBase *S) override;
Kind getKind() const override { return EHFrame; }
static bool classof(const OutputSectionBase *B) {
return B->getKind() == EHFrame;
}
size_t NumFdes = 0;
private:
template <class RelTy>
void addSectionAux(EhInputSection<ELFT> *S, llvm::ArrayRef<RelTy> Rels);
template <class RelTy>
CieRecord *addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels);
template <class RelTy>
bool isFdeLive(EhSectionPiece &Piece, ArrayRef<RelTy> Rels);
uintX_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc);
std::vector<EhInputSection<ELFT> *> Sections;
std::vector<CieRecord *> Cies;
// CIE records are uniquified by their contents and personality functions.
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
};
// All output sections that are hadnled by the linker specially are
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
@ -183,7 +137,6 @@ template <class ELFT> struct Out {
typedef typename ELFT::Phdr Elf_Phdr;
static uint8_t First;
static EhOutputSection<ELFT> *EhFrame;
static OutputSection<ELFT> *Bss;
static OutputSection<ELFT> *BssRelRo;
static OutputSectionBase *Opd;
@ -241,7 +194,6 @@ template <class ELFT> uint64_t getHeaderSize() {
}
template <class ELFT> uint8_t Out<ELFT>::First;
template <class ELFT> EhOutputSection<ELFT> *Out<ELFT>::EhFrame;
template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss;
template <class ELFT> OutputSection<ELFT> *Out<ELFT>::BssRelRo;
template <class ELFT> OutputSectionBase *Out<ELFT>::Opd;

View File

@ -15,7 +15,6 @@
namespace lld {
namespace elf {
class SymbolBody;
class InputSectionData;
class InputSection;
class InputSectionBase;
class OutputSectionBase;

View File

@ -400,6 +400,210 @@ void BuildIdSection<ELFT>::writeBuildId(ArrayRef<uint8_t> Buf) {
}
}
template <class ELFT>
EhFrameSection<ELFT>::EhFrameSection()
: SyntheticSection<ELFT>(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame") {}
// Search for an existing CIE record or create a new one.
// CIE records from input object files are uniquified by their contents
// and where their relocations point to.
template <class ELFT>
template <class RelTy>
CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Piece,
ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection<ELFT>>(Piece.ID);
const endianness E = ELFT::TargetEndianness;
if (read32<E>(Piece.data().data() + 4) != 0)
fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame");
SymbolBody *Personality = nullptr;
unsigned FirstRelI = Piece.FirstRelocation;
if (FirstRelI != (unsigned)-1)
Personality =
&Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);
// Search for an existing CIE by CIE contents/relocation target pair.
CieRecord *Cie = &CieMap[{Piece.data(), Personality}];
// If not found, create a new one.
if (Cie->Piece == nullptr) {
Cie->Piece = &Piece;
Cies.push_back(Cie);
}
return Cie;
}
// There is one FDE per function. Returns true if a given FDE
// points to a live function.
template <class ELFT>
template <class RelTy>
bool EhFrameSection<ELFT>::isFdeLive(EhSectionPiece &Piece,
ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection<ELFT>>(Piece.ID);
unsigned FirstRelI = Piece.FirstRelocation;
if (FirstRelI == (unsigned)-1)
return false;
const RelTy &Rel = Rels[FirstRelI];
SymbolBody &B = Sec->template getFile<ELFT>()->getRelocTargetSym(Rel);
auto *D = dyn_cast<DefinedRegular<ELFT>>(&B);
if (!D || !D->Section)
return false;
InputSectionBase *Target = D->Section->Repl;
return Target && Target->Live;
}
// .eh_frame is a sequence of CIE or FDE records. In general, there
// is one CIE record per input object file which is followed by
// a list of FDEs. This function searches an existing CIE or create a new
// one and associates FDEs to the CIE.
template <class ELFT>
template <class RelTy>
void EhFrameSection<ELFT>::addSectionAux(EhInputSection<ELFT> *Sec,
ArrayRef<RelTy> Rels) {
const endianness E = ELFT::TargetEndianness;
DenseMap<size_t, CieRecord *> OffsetToCie;
for (EhSectionPiece &Piece : Sec->Pieces) {
// The empty record is the end marker.
if (Piece.size() == 4)
return;
size_t Offset = Piece.InputOff;
uint32_t ID = read32<E>(Piece.data().data() + 4);
if (ID == 0) {
OffsetToCie[Offset] = addCie(Piece, Rels);
continue;
}
uint32_t CieOffset = Offset + 4 - ID;
CieRecord *Cie = OffsetToCie[CieOffset];
if (!Cie)
fatal(toString(Sec) + ": invalid CIE reference");
if (!isFdeLive(Piece, Rels))
continue;
Cie->FdePieces.push_back(&Piece);
NumFdes++;
}
}
template <class ELFT>
void EhFrameSection<ELFT>::addSection(InputSectionBase *C) {
auto *Sec = cast<EhInputSection<ELFT>>(C);
Sec->EHSec = this;
updateAlignment(Sec->Alignment);
Sections.push_back(Sec);
// .eh_frame is a sequence of CIE or FDE records. This function
// splits it into pieces so that we can call
// SplitInputSection::getSectionPiece on the section.
Sec->split();
if (Sec->Pieces.empty())
return;
if (Sec->NumRelocations) {
if (Sec->AreRelocsRela)
addSectionAux(Sec, Sec->template relas<ELFT>());
else
addSectionAux(Sec, Sec->template rels<ELFT>());
return;
}
addSectionAux(Sec, makeArrayRef<Elf_Rela>(nullptr, nullptr));
}
template <class ELFT>
static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
memcpy(Buf, D.data(), D.size());
// Fix the size field. -4 since size does not include the size field itself.
const endianness E = ELFT::TargetEndianness;
write32<E>(Buf, alignTo(D.size(), sizeof(typename ELFT::uint)) - 4);
}
template <class ELFT> void EhFrameSection<ELFT>::finalize() {
if (this->Size)
return; // Already finalized.
size_t Off = 0;
for (CieRecord *Cie : Cies) {
Cie->Piece->OutputOff = Off;
Off += alignTo(Cie->Piece->size(), sizeof(uintX_t));
for (EhSectionPiece *Fde : Cie->FdePieces) {
Fde->OutputOff = Off;
Off += alignTo(Fde->size(), sizeof(uintX_t));
}
}
this->Size = Off;
}
template <class ELFT> static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
const endianness E = ELFT::TargetEndianness;
switch (Size) {
case DW_EH_PE_udata2:
return read16<E>(Buf);
case DW_EH_PE_udata4:
return read32<E>(Buf);
case DW_EH_PE_udata8:
return read64<E>(Buf);
case DW_EH_PE_absptr:
if (ELFT::Is64Bits)
return read64<E>(Buf);
return read32<E>(Buf);
}
fatal("unknown FDE size encoding");
}
// Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to.
// We need it to create .eh_frame_hdr section.
template <class ELFT>
typename ELFT::uint EhFrameSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff,
uint8_t Enc) {
// The starting address to which this FDE applies is
// stored at FDE + 8 byte.
size_t Off = FdeOff + 8;
uint64_t Addr = readFdeAddr<ELFT>(Buf + Off, Enc & 0x7);
if ((Enc & 0x70) == DW_EH_PE_absptr)
return Addr;
if ((Enc & 0x70) == DW_EH_PE_pcrel)
return Addr + this->OutSec->Addr + Off;
fatal("unknown FDE size relative encoding");
}
template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
const endianness E = ELFT::TargetEndianness;
for (CieRecord *Cie : Cies) {
size_t CieOffset = Cie->Piece->OutputOff;
writeCieFde<ELFT>(Buf + CieOffset, Cie->Piece->data());
for (EhSectionPiece *Fde : Cie->FdePieces) {
size_t Off = Fde->OutputOff;
writeCieFde<ELFT>(Buf + Off, Fde->data());
// FDE's second word should have the offset to an associated CIE.
// Write it.
write32<E>(Buf + Off + 4, Off + 4 - CieOffset);
}
}
for (EhInputSection<ELFT> *S : Sections)
S->template relocate<ELFT>(Buf, nullptr);
// Construct .eh_frame_hdr. .eh_frame_hdr is a binary search table
// to get a FDE from an address to which FDE is applied. So here
// we obtain two addresses and pass them to EhFrameHdr object.
if (In<ELFT>::EhFrameHdr) {
for (CieRecord *Cie : Cies) {
uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece);
for (SectionPiece *Fde : Cie->FdePieces) {
uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
uintX_t FdeVA = this->OutSec->Addr + Fde->OutputOff;
In<ELFT>::EhFrameHdr->addFde(Pc, FdeVA);
}
}
}
}
template <class ELFT>
GotSection<ELFT>::GotSection()
: SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
@ -1675,7 +1879,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, Out<ELFT>::EhFrame->Addr - this->getVA() - 4);
write32<E>(Buf + 4, In<ELFT>::EhFrame->OutSec->Addr - this->getVA() - 4);
write32<E>(Buf + 8, Fdes.size());
Buf += 12;
@ -1689,7 +1893,7 @@ template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) {
template <class ELFT> size_t EhFrameHeader<ELFT>::getSize() const {
// .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
return 12 + Out<ELFT>::EhFrame->NumFdes * 8;
return 12 + In<ELFT>::EhFrame->NumFdes * 8;
}
template <class ELFT>
@ -1698,7 +1902,7 @@ void EhFrameHeader<ELFT>::addFde(uint32_t Pc, uint32_t FdeVA) {
}
template <class ELFT> bool EhFrameHeader<ELFT>::empty() const {
return Out<ELFT>::EhFrame->empty();
return In<ELFT>::EhFrame->empty();
}
template <class ELFT>
@ -2158,3 +2362,8 @@ template class elf::ThunkSection<ELF32LE>;
template class elf::ThunkSection<ELF32BE>;
template class elf::ThunkSection<ELF64LE>;
template class elf::ThunkSection<ELF64BE>;
template class elf::EhFrameSection<ELF32LE>;
template class elf::EhFrameSection<ELF32BE>;
template class elf::EhFrameSection<ELF64LE>;
template class elf::EhFrameSection<ELF64BE>;

View File

@ -25,6 +25,7 @@
#ifndef LLD_ELF_SYNTHETIC_SECTION_H
#define LLD_ELF_SYNTHETIC_SECTION_H
#include "EhFrame.h"
#include "GdbIndex.h"
#include "InputSection.h"
#include "llvm/ADT/MapVector.h"
@ -59,6 +60,55 @@ public:
}
};
struct CieRecord {
EhSectionPiece *Piece = nullptr;
std::vector<EhSectionPiece *> FdePieces;
};
// Section for .eh_frame.
template <class ELFT>
class EhFrameSection final : public SyntheticSection<ELFT> {
typedef typename ELFT::uint uintX_t;
typedef typename ELFT::Shdr Elf_Shdr;
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Rela Elf_Rela;
void updateAlignment(uint64_t Val) {
if (Val > this->Alignment)
this->Alignment = Val;
}
public:
EhFrameSection();
void writeTo(uint8_t *Buf) override;
void finalize() override;
bool empty() const override { return Sections.empty(); }
size_t getSize() const override { return Size; }
void addSection(InputSectionBase *S);
size_t NumFdes = 0;
private:
uint64_t Size = 0;
template <class RelTy>
void addSectionAux(EhInputSection<ELFT> *S, llvm::ArrayRef<RelTy> Rels);
template <class RelTy>
CieRecord *addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels);
template <class RelTy>
bool isFdeLive(EhSectionPiece &Piece, ArrayRef<RelTy> Rels);
uintX_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc);
std::vector<EhInputSection<ELFT> *> Sections;
std::vector<CieRecord *> Cies;
// CIE records are uniquified by their contents and personality functions.
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
};
template <class ELFT> class GotSection final : public SyntheticSection<ELFT> {
typedef typename ELFT::uint uintX_t;
@ -762,6 +812,7 @@ template <class ELFT> struct In {
static GnuHashTableSection<ELFT> *GnuHashTab;
static GdbIndexSection<ELFT> *GdbIndex;
static GotSection<ELFT> *Got;
static EhFrameSection<ELFT> *EhFrame;
static MipsGotSection<ELFT> *MipsGot;
static GotPltSection<ELFT> *GotPlt;
static IgotPltSection<ELFT> *IgotPlt;
@ -791,6 +842,7 @@ template <class ELFT> EhFrameHeader<ELFT> *In<ELFT>::EhFrameHdr;
template <class ELFT> GdbIndexSection<ELFT> *In<ELFT>::GdbIndex;
template <class ELFT> GnuHashTableSection<ELFT> *In<ELFT>::GnuHashTab;
template <class ELFT> GotSection<ELFT> *In<ELFT>::Got;
template <class ELFT> EhFrameSection<ELFT> *In<ELFT>::EhFrame;
template <class ELFT> MipsGotSection<ELFT> *In<ELFT>::MipsGot;
template <class ELFT> GotPltSection<ELFT> *In<ELFT>::GotPlt;
template <class ELFT> IgotPltSection<ELFT> *In<ELFT>::IgotPlt;

View File

@ -318,7 +318,6 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
SHF_ALLOC | SHF_WRITE);
In<ELFT>::DynStrTab = make<StringTableSection<ELFT>>(".dynstr", true);
In<ELFT>::Dynamic = make<DynamicSection<ELFT>>();
Out<ELFT>::EhFrame = make<EhOutputSection<ELFT>>();
In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>(
Config->Rela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
In<ELFT>::ShStrTab = make<StringTableSection<ELFT>>(".shstrtab", false);
@ -444,6 +443,11 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(In<ELFT>::EhFrameHdr);
}
if (!Config->Relocatable) {
In<ELFT>::EhFrame = make<EhFrameSection<ELFT>>();
Add(In<ELFT>::EhFrame);
}
if (In<ELFT>::SymTab)
Add(In<ELFT>::SymTab);
Add(In<ELFT>::ShStrTab);
@ -1088,10 +1092,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
if (!Out<ELFT>::EhFrame->empty()) {
OutputSections.push_back(Out<ELFT>::EhFrame);
Out<ELFT>::EhFrame->finalize();
}
// This responsible for splitting up .eh_frame section into
// pieces. The relocation scan uses those peaces, so this has to be
// earlier.
finalizeSynthetic<ELFT>({In<ELFT>::EhFrame});
// Scan relocations. This must be done after every symbol is declared so that
// we can correctly decide if a dynamic relocation is needed.
@ -1323,7 +1327,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
Ret.push_back(std::move(RelRo));
// PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
if (!Out<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr)
if (!In<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr)
AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->OutSec->getPhdrFlags())
->add(In<ELFT>::EhFrameHdr->OutSec);
@ -1827,7 +1831,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 (!Out<ELFT>::EhFrame->empty() && EhFrameHdr)
if (EhFrameHdr)
EhFrameHdr->writeTo(Buf + EhFrameHdr->Offset);
}

View File

@ -28,6 +28,7 @@ local:
// CHECK: Address Size Align Out In File Symbol
// CHECK-NEXT: 0000000000200158 0000000000000030 8 .eh_frame
// CHECK-NEXT: 0000000000200158 0000000000000030 8 .eh_frame
// CHECK-NEXT: 0000000000201000 0000000000000015 4 .text
// CHECK-NEXT: 0000000000201000 000000000000000e 4 .text
// CHECK-NEXT: 0000000000201000 000000000000000e 4 {{.*}}{{/|\\}}map-file.s.tmp1.o