Compact EhSectionPiece from 32 bytes to 16 bytes.

EhSectionPiece used to have a pointer to a section, but that pointer was
mostly redundant because we almost always know what the section is without
using that pointer. This patch removes the pointer from the struct.

This patch also use uint32_t/int32_t instead of size_t to represent
offsets that are hardly be larger than 4 GiB. At the moment, I think it is
OK even if we cannot handle .eh_frame sections larger than 4 GiB.

Differential Revision: https://reviews.llvm.org/D38012

llvm-svn: 313697
This commit is contained in:
Rui Ueyama 2017-09-19 23:36:48 +00:00
parent d652aeb144
commit 014b0f24ae
7 changed files with 47 additions and 33 deletions

View File

@ -153,8 +153,9 @@ template <class ELFT> void EhReader<ELFT>::skipAugP() {
D = D.slice(Size); D = D.slice(Size);
} }
template <class ELFT> uint8_t elf::getFdeEncoding(EhSectionPiece *P) { template <class ELFT>
return EhReader<ELFT>(P->Sec, P->data()).getFdeEncoding(); uint8_t elf::getFdeEncoding(EhInputSection *Sec, EhSectionPiece *Piece) {
return EhReader<ELFT>(Sec, Piece->data(Sec)).getFdeEncoding();
} }
template <class ELFT> uint8_t EhReader<ELFT>::getFdeEncoding() { template <class ELFT> uint8_t EhReader<ELFT>::getFdeEncoding() {
@ -205,7 +206,11 @@ template size_t elf::readEhRecordSize<ELF32BE>(InputSectionBase *S, size_t Off);
template size_t elf::readEhRecordSize<ELF64LE>(InputSectionBase *S, size_t Off); template size_t elf::readEhRecordSize<ELF64LE>(InputSectionBase *S, size_t Off);
template size_t elf::readEhRecordSize<ELF64BE>(InputSectionBase *S, size_t Off); template size_t elf::readEhRecordSize<ELF64BE>(InputSectionBase *S, size_t Off);
template uint8_t elf::getFdeEncoding<ELF32LE>(EhSectionPiece *P); template uint8_t elf::getFdeEncoding<ELF32LE>(EhInputSection *,
template uint8_t elf::getFdeEncoding<ELF32BE>(EhSectionPiece *P); EhSectionPiece *);
template uint8_t elf::getFdeEncoding<ELF64LE>(EhSectionPiece *P); template uint8_t elf::getFdeEncoding<ELF32BE>(EhInputSection *,
template uint8_t elf::getFdeEncoding<ELF64BE>(EhSectionPiece *P); EhSectionPiece *);
template uint8_t elf::getFdeEncoding<ELF64LE>(EhInputSection *,
EhSectionPiece *);
template uint8_t elf::getFdeEncoding<ELF64BE>(EhInputSection *,
EhSectionPiece *);

View File

@ -14,11 +14,13 @@
namespace lld { namespace lld {
namespace elf { namespace elf {
class EhInputSection;
class InputSectionBase; class InputSectionBase;
struct EhSectionPiece; struct EhSectionPiece;
template <class ELFT> size_t readEhRecordSize(InputSectionBase *S, size_t Off); template <class ELFT> size_t readEhRecordSize(InputSectionBase *S, size_t Off);
template <class ELFT> uint8_t getFdeEncoding(EhSectionPiece *P); template <class ELFT>
uint8_t getFdeEncoding(EhInputSection *, EhSectionPiece *);
} // namespace elf } // namespace elf
} // namespace lld } // namespace lld

View File

@ -870,7 +870,7 @@ void EhInputSection::split(ArrayRef<RelTy> Rels) {
unsigned RelI = 0; unsigned RelI = 0;
for (size_t Off = 0, End = Data.size(); Off != End;) { for (size_t Off = 0, End = Data.size(); Off != End;) {
size_t Size = readEhRecordSize<ELFT>(this, Off); size_t Size = readEhRecordSize<ELFT>(this, Off);
this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); this->Pieces.emplace_back(Off, Size, getReloc(Off, Size, Rels, RelI));
// The empty record is the end marker. // The empty record is the end marker.
if (Size == 4) if (Size == 4)
break; break;

View File

@ -25,6 +25,7 @@ namespace lld {
namespace elf { namespace elf {
class DefinedCommon; class DefinedCommon;
class EhInputSection;
class SymbolBody; class SymbolBody;
struct SectionPiece; struct SectionPiece;
@ -262,17 +263,16 @@ private:
}; };
struct EhSectionPiece { struct EhSectionPiece {
EhSectionPiece(size_t Off, InputSectionBase *Sec, uint32_t Size, EhSectionPiece(size_t Off, uint32_t Size, unsigned FirstRelocation)
unsigned FirstRelocation) : InputOff(Off), Size(Size), FirstRelocation(FirstRelocation) {
: InputOff(Off), Sec(Sec), Size(Size), FirstRelocation(FirstRelocation) {} assert(Off < UINT32_MAX && Size < UINT32_MAX);
}
ArrayRef<uint8_t> data() { return {Sec->Data.data() + this->InputOff, Size}; } ArrayRef<uint8_t> data(EhInputSection *Sec);
uint32_t InputOff;
size_t InputOff; int32_t OutputOff = -1;
ssize_t OutputOff = -1;
InputSectionBase *Sec;
uint32_t Size; uint32_t Size;
unsigned FirstRelocation; uint32_t FirstRelocation;
}; };
// This corresponds to a .eh_frame section of an input file. // This corresponds to a .eh_frame section of an input file.
@ -292,6 +292,10 @@ public:
SyntheticSection *getParent() const; SyntheticSection *getParent() const;
}; };
inline ArrayRef<uint8_t> EhSectionPiece::data(EhInputSection *Sec) {
return {Sec->Data.data() + InputOff, Size};
}
// This is a section that is added directly to an output section // This is a section that is added directly to an output section
// instead of needing special combination via a synthetic section. This // instead of needing special combination via a synthetic section. This
// includes all input sections with the exceptions of SHF_MERGE and // includes all input sections with the exceptions of SHF_MERGE and

View File

@ -126,7 +126,7 @@ scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels,
unsigned FirstRelI = Piece.FirstRelocation; unsigned FirstRelI = Piece.FirstRelocation;
if (FirstRelI == (unsigned)-1) if (FirstRelI == (unsigned)-1)
continue; continue;
if (read32<E>(Piece.data().data() + 4) == 0) { if (read32<E>(Piece.data(&EH).data() + 4) == 0) {
// This is a CIE, we only need to worry about the first relocation. It is // This is a CIE, we only need to worry about the first relocation. It is
// known to point to the personality function. // known to point to the personality function.
resolveReloc<ELFT>(EH, Rels[FirstRelI], Fn); resolveReloc<ELFT>(EH, Rels[FirstRelI], Fn);

View File

@ -403,11 +403,11 @@ EhFrameSection<ELFT>::EhFrameSection()
// and where their relocations point to. // and where their relocations point to.
template <class ELFT> template <class ELFT>
template <class RelTy> template <class RelTy>
CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Cie, CieRecord *EhFrameSection<ELFT>::addCie(EhInputSection *Sec,
EhSectionPiece &Cie,
ArrayRef<RelTy> Rels) { ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection>(Cie.Sec);
const endianness E = ELFT::TargetEndianness; const endianness E = ELFT::TargetEndianness;
if (read32<E>(Cie.data().data() + 4) != 0) if (read32<E>(Cie.data(Sec).data() + 4) != 0)
fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame"); fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame");
SymbolBody *Personality = nullptr; SymbolBody *Personality = nullptr;
@ -417,10 +417,11 @@ CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Cie,
&Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]); &Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);
// Search for an existing CIE by CIE contents/relocation target pair. // Search for an existing CIE by CIE contents/relocation target pair.
CieRecord *Rec = &CieMap[{Cie.data(), Personality}]; CieRecord *Rec = &CieMap[{Cie.data(Sec), Personality}];
// If not found, create a new one. // If not found, create a new one.
if (Rec->Cie == nullptr) { if (Rec->Sec == nullptr) {
Rec->Sec = Sec;
Rec->Cie = &Cie; Rec->Cie = &Cie;
CieRecords.push_back(Rec); CieRecords.push_back(Rec);
} }
@ -431,9 +432,8 @@ CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Cie,
// points to a live function. // points to a live function.
template <class ELFT> template <class ELFT>
template <class RelTy> template <class RelTy>
bool EhFrameSection<ELFT>::isFdeLive(EhSectionPiece &Fde, bool EhFrameSection<ELFT>::isFdeLive(EhInputSection *Sec, EhSectionPiece &Fde,
ArrayRef<RelTy> Rels) { ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection>(Fde.Sec);
unsigned FirstRelI = Fde.FirstRelocation; unsigned FirstRelI = Fde.FirstRelocation;
// An FDE should point to some function because FDEs are to describe // An FDE should point to some function because FDEs are to describe
@ -469,9 +469,9 @@ void EhFrameSection<ELFT>::addSectionAux(EhInputSection *Sec,
return; return;
size_t Offset = Piece.InputOff; size_t Offset = Piece.InputOff;
uint32_t ID = read32<E>(Piece.data().data() + 4); uint32_t ID = read32<E>(Piece.data(Sec).data() + 4);
if (ID == 0) { if (ID == 0) {
OffsetToCie[Offset] = addCie(Piece, Rels); OffsetToCie[Offset] = addCie(Sec, Piece, Rels);
continue; continue;
} }
@ -480,7 +480,7 @@ void EhFrameSection<ELFT>::addSectionAux(EhInputSection *Sec,
if (!Rec) if (!Rec)
fatal(toString(Sec) + ": invalid CIE reference"); fatal(toString(Sec) + ": invalid CIE reference");
if (!isFdeLive(Piece, Rels)) if (!isFdeLive(Sec, Piece, Rels))
continue; continue;
Rec->Fdes.push_back(&Piece); Rec->Fdes.push_back(&Piece);
NumFdes++; NumFdes++;
@ -586,11 +586,11 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
const endianness E = ELFT::TargetEndianness; const endianness E = ELFT::TargetEndianness;
for (CieRecord *Rec : CieRecords) { for (CieRecord *Rec : CieRecords) {
size_t CieOffset = Rec->Cie->OutputOff; size_t CieOffset = Rec->Cie->OutputOff;
writeCieFde<ELFT>(Buf + CieOffset, Rec->Cie->data()); writeCieFde<ELFT>(Buf + CieOffset, Rec->Cie->data(Rec->Sec));
for (EhSectionPiece *Fde : Rec->Fdes) { for (EhSectionPiece *Fde : Rec->Fdes) {
size_t Off = Fde->OutputOff; size_t Off = Fde->OutputOff;
writeCieFde<ELFT>(Buf + Off, Fde->data()); writeCieFde<ELFT>(Buf + Off, Fde->data(Rec->Sec));
// FDE's second word should have the offset to an associated CIE. // FDE's second word should have the offset to an associated CIE.
// Write it. // Write it.
@ -606,7 +606,7 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
// we obtain two addresses and pass them to EhFrameHdr object. // we obtain two addresses and pass them to EhFrameHdr object.
if (In<ELFT>::EhFrameHdr) { if (In<ELFT>::EhFrameHdr) {
for (CieRecord *Rec : CieRecords) { for (CieRecord *Rec : CieRecords) {
uint8_t Enc = getFdeEncoding<ELFT>(Rec->Cie); uint8_t Enc = getFdeEncoding<ELFT>(Rec->Sec, Rec->Cie);
for (EhSectionPiece *Fde : Rec->Fdes) { for (EhSectionPiece *Fde : Rec->Fdes) {
uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
uint64_t FdeVA = getParent()->Addr + Fde->OutputOff; uint64_t FdeVA = getParent()->Addr + Fde->OutputOff;

View File

@ -59,6 +59,7 @@ public:
}; };
struct CieRecord { struct CieRecord {
EhInputSection *Sec = nullptr;
EhSectionPiece *Cie = nullptr; EhSectionPiece *Cie = nullptr;
std::vector<EhSectionPiece *> Fdes; std::vector<EhSectionPiece *> Fdes;
}; };
@ -93,10 +94,12 @@ private:
void addSectionAux(EhInputSection *S, llvm::ArrayRef<RelTy> Rels); void addSectionAux(EhInputSection *S, llvm::ArrayRef<RelTy> Rels);
template <class RelTy> template <class RelTy>
CieRecord *addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels); CieRecord *addCie(EhInputSection *Sec, EhSectionPiece &Piece,
ArrayRef<RelTy> Rels);
template <class RelTy> template <class RelTy>
bool isFdeLive(EhSectionPiece &Piece, ArrayRef<RelTy> Rels); bool isFdeLive(EhInputSection *Sec, EhSectionPiece &Piece,
ArrayRef<RelTy> Rels);
uint64_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc); uint64_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc);