Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lld/ELF/SyntheticSections.cpp
Show First 20 Lines • Show All 367 Lines • ▼ Show 20 Lines | CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) { | ||||
if (!rec) { | if (!rec) { | ||||
rec = make<CieRecord>(); | rec = make<CieRecord>(); | ||||
rec->cie = &cie; | rec->cie = &cie; | ||||
cieRecords.push_back(rec); | cieRecords.push_back(rec); | ||||
} | } | ||||
return rec; | return rec; | ||||
} | } | ||||
// There is one FDE per function. Returns a non-null pointer to the function | |||||
// symbol if the given FDE points to a live function. | |||||
template <class ELFT, class RelTy> | template <class ELFT, class RelTy> | ||||
Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { | Defined *elf::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { | ||||
auto *sec = cast<EhInputSection>(fde.sec); | 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 | ||||
// functions. That's however not always the case due to an issue of | // functions. That's however not always the case due to an issue of | ||||
// ld.gold with -r. ld.gold may discard only functions and leave their | // ld.gold with -r. ld.gold may discard only functions and leave their | ||||
// corresponding FDEs, which results in creating bad .eh_frame sections. | // corresponding FDEs, which results in creating bad .eh_frame sections. | ||||
// To deal with that, we ignore such FDEs. | // To deal with that, we ignore such FDEs. | ||||
if (firstRelI == (unsigned)-1) | if (firstRelI == (unsigned)-1) | ||||
return nullptr; | return nullptr; | ||||
const RelTy &rel = rels[firstRelI]; | const RelTy &rel = rels[firstRelI]; | ||||
Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel); | Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel); | ||||
// FDEs for garbage-collected or merged-by-ICF sections, or sections in | |||||
// another partition, are dead. | |||||
if (auto *d = dyn_cast<Defined>(&b)) | if (auto *d = dyn_cast<Defined>(&b)) | ||||
if (!d->folded && d->section && d->section->partition == partition) | // FDEs for garbage-collected or merged-by-ICF sections are dead. | ||||
if (!d->folded && d->section && d->section->partition) | |||||
return d; | |||||
return nullptr; | |||||
} | |||||
// There is one FDE per function. Returns a non-null pointer to the function | |||||
// symbol if the given FDE points to a live function. | |||||
template <class ELFT, class RelTy> | |||||
Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { | |||||
if (auto *d = elf::isFdeLive<ELFT>(fde, rels)) | |||||
// FDEs for sections in another partition are dead. | |||||
if (d->section->partition == partition) | |||||
return d; | return d; | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
// .eh_frame is a sequence of CIE or FDE records. In general, there | // .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 | // 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 | // a list of FDEs. This function searches an existing CIE or create a new | ||||
// one and associates FDEs to the CIE. | // one and associates FDEs to the CIE. | ||||
template <class ELFT, class RelTy> | template <class ELFT, class RelTy> | ||||
void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) { | void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) { | ||||
offsetToCie.clear(); | offsetToCie.clear(); | ||||
for (EhSectionPiece &cie : sec->cies) | for (EhSectionPiece &cie : sec->cies) { | ||||
if (!cie.live) | |||||
continue; | |||||
offsetToCie[cie.inputOff] = addCie<ELFT>(cie, rels); | offsetToCie[cie.inputOff] = addCie<ELFT>(cie, rels); | ||||
} | |||||
for (EhSectionPiece &fde : sec->fdes) { | for (EhSectionPiece &fde : sec->fdes) { | ||||
if (!fde.live) | |||||
continue; | |||||
uint32_t id = endian::read32<ELFT::TargetEndianness>(fde.data().data() + 4); | uint32_t id = endian::read32<ELFT::TargetEndianness>(fde.data().data() + 4); | ||||
CieRecord *rec = offsetToCie[fde.inputOff + 4 - id]; | CieRecord *rec = offsetToCie[fde.inputOff + 4 - id]; | ||||
if (!rec) | if (!rec) | ||||
fatal(toString(sec) + ": invalid CIE reference"); | fatal(toString(sec) + ": invalid CIE reference"); | ||||
if (!isFdeLive<ELFT>(fde, rels)) | if (!isFdeLive<ELFT>(fde, rels)) | ||||
continue; | continue; | ||||
rec->fdes.push_back(&fde); | rec->fdes.push_back(&fde); | ||||
▲ Show 20 Lines • Show All 3,540 Lines • ▼ Show 20 Lines | |||||
template class elf::PartitionElfHeaderSection<ELF32BE>; | template class elf::PartitionElfHeaderSection<ELF32BE>; | ||||
template class elf::PartitionElfHeaderSection<ELF64LE>; | template class elf::PartitionElfHeaderSection<ELF64LE>; | ||||
template class elf::PartitionElfHeaderSection<ELF64BE>; | template class elf::PartitionElfHeaderSection<ELF64BE>; | ||||
template class elf::PartitionProgramHeadersSection<ELF32LE>; | template class elf::PartitionProgramHeadersSection<ELF32LE>; | ||||
template class elf::PartitionProgramHeadersSection<ELF32BE>; | template class elf::PartitionProgramHeadersSection<ELF32BE>; | ||||
template class elf::PartitionProgramHeadersSection<ELF64LE>; | template class elf::PartitionProgramHeadersSection<ELF64LE>; | ||||
template class elf::PartitionProgramHeadersSection<ELF64BE>; | template class elf::PartitionProgramHeadersSection<ELF64BE>; | ||||
template Defined *elf::isFdeLive<ELF32LE, typename ELF32LE::Rel>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF32LE::Rel> rels); | |||||
template Defined *elf::isFdeLive<ELF32LE, typename ELF32LE::Rela>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF32LE::Rela> rels); | |||||
template Defined *elf::isFdeLive<ELF64LE, typename ELF64LE::Rel>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF64LE::Rel> rels); | |||||
template Defined *elf::isFdeLive<ELF64LE, typename ELF64LE::Rela>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF64LE::Rela> rels); | |||||
template Defined *elf::isFdeLive<ELF32BE, typename ELF32BE::Rel>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF32BE::Rel> rels); | |||||
template Defined *elf::isFdeLive<ELF32BE, typename ELF32BE::Rela>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF32BE::Rela> rels); | |||||
template Defined *elf::isFdeLive<ELF64BE, typename ELF64BE::Rel>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF64BE::Rel> rels); | |||||
template Defined *elf::isFdeLive<ELF64BE, typename ELF64BE::Rela>( | |||||
EhSectionPiece &fde, ArrayRef<typename ELF64BE::Rela> rels); |