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);
}
template <class ELFT> uint8_t elf::getFdeEncoding(EhSectionPiece *P) {
return EhReader<ELFT>(P->Sec, P->data()).getFdeEncoding();
template <class ELFT>
uint8_t elf::getFdeEncoding(EhInputSection *Sec, EhSectionPiece *Piece) {
return EhReader<ELFT>(Sec, Piece->data(Sec)).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<ELF64BE>(InputSectionBase *S, size_t Off);
template uint8_t elf::getFdeEncoding<ELF32LE>(EhSectionPiece *P);
template uint8_t elf::getFdeEncoding<ELF32BE>(EhSectionPiece *P);
template uint8_t elf::getFdeEncoding<ELF64LE>(EhSectionPiece *P);
template uint8_t elf::getFdeEncoding<ELF64BE>(EhSectionPiece *P);
template uint8_t elf::getFdeEncoding<ELF32LE>(EhInputSection *,
EhSectionPiece *);
template uint8_t elf::getFdeEncoding<ELF32BE>(EhInputSection *,
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 elf {
class EhInputSection;
class InputSectionBase;
struct EhSectionPiece;
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 lld

View File

@ -870,7 +870,7 @@ void EhInputSection::split(ArrayRef<RelTy> Rels) {
unsigned RelI = 0;
for (size_t Off = 0, End = Data.size(); Off != End;) {
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.
if (Size == 4)
break;

View File

@ -25,6 +25,7 @@ namespace lld {
namespace elf {
class DefinedCommon;
class EhInputSection;
class SymbolBody;
struct SectionPiece;
@ -262,17 +263,16 @@ private:
};
struct EhSectionPiece {
EhSectionPiece(size_t Off, InputSectionBase *Sec, uint32_t Size,
unsigned FirstRelocation)
: InputOff(Off), Sec(Sec), Size(Size), FirstRelocation(FirstRelocation) {}
EhSectionPiece(size_t Off, uint32_t Size, unsigned FirstRelocation)
: InputOff(Off), Size(Size), FirstRelocation(FirstRelocation) {
assert(Off < UINT32_MAX && Size < UINT32_MAX);
}
ArrayRef<uint8_t> data() { return {Sec->Data.data() + this->InputOff, Size}; }
size_t InputOff;
ssize_t OutputOff = -1;
InputSectionBase *Sec;
ArrayRef<uint8_t> data(EhInputSection *Sec);
uint32_t InputOff;
int32_t OutputOff = -1;
uint32_t Size;
unsigned FirstRelocation;
uint32_t FirstRelocation;
};
// This corresponds to a .eh_frame section of an input file.
@ -292,6 +292,10 @@ public:
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
// instead of needing special combination via a synthetic section. This
// 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;
if (FirstRelI == (unsigned)-1)
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
// known to point to the personality function.
resolveReloc<ELFT>(EH, Rels[FirstRelI], Fn);

View File

@ -403,11 +403,11 @@ EhFrameSection<ELFT>::EhFrameSection()
// and where their relocations point to.
template <class ELFT>
template <class RelTy>
CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Cie,
CieRecord *EhFrameSection<ELFT>::addCie(EhInputSection *Sec,
EhSectionPiece &Cie,
ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection>(Cie.Sec);
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");
SymbolBody *Personality = nullptr;
@ -417,10 +417,11 @@ CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Cie,
&Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);
// 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 (Rec->Cie == nullptr) {
if (Rec->Sec == nullptr) {
Rec->Sec = Sec;
Rec->Cie = &Cie;
CieRecords.push_back(Rec);
}
@ -431,9 +432,8 @@ CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Cie,
// points to a live function.
template <class ELFT>
template <class RelTy>
bool EhFrameSection<ELFT>::isFdeLive(EhSectionPiece &Fde,
bool EhFrameSection<ELFT>::isFdeLive(EhInputSection *Sec, EhSectionPiece &Fde,
ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection>(Fde.Sec);
unsigned FirstRelI = Fde.FirstRelocation;
// An FDE should point to some function because FDEs are to describe
@ -469,9 +469,9 @@ void EhFrameSection<ELFT>::addSectionAux(EhInputSection *Sec,
return;
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) {
OffsetToCie[Offset] = addCie(Piece, Rels);
OffsetToCie[Offset] = addCie(Sec, Piece, Rels);
continue;
}
@ -480,7 +480,7 @@ void EhFrameSection<ELFT>::addSectionAux(EhInputSection *Sec,
if (!Rec)
fatal(toString(Sec) + ": invalid CIE reference");
if (!isFdeLive(Piece, Rels))
if (!isFdeLive(Sec, Piece, Rels))
continue;
Rec->Fdes.push_back(&Piece);
NumFdes++;
@ -586,11 +586,11 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
const endianness E = ELFT::TargetEndianness;
for (CieRecord *Rec : CieRecords) {
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) {
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.
// 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.
if (In<ELFT>::EhFrameHdr) {
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) {
uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
uint64_t FdeVA = getParent()->Addr + Fde->OutputOff;

View File

@ -59,6 +59,7 @@ public:
};
struct CieRecord {
EhInputSection *Sec = nullptr;
EhSectionPiece *Cie = nullptr;
std::vector<EhSectionPiece *> Fdes;
};
@ -93,10 +94,12 @@ private:
void addSectionAux(EhInputSection *S, llvm::ArrayRef<RelTy> Rels);
template <class RelTy>
CieRecord *addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels);
CieRecord *addCie(EhInputSection *Sec, EhSectionPiece &Piece,
ArrayRef<RelTy> Rels);
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);