Skip to content

Commit

Permalink
[ELF] Simplify/optimize EhInputSection::split
Browse files Browse the repository at this point in the history
and change some `fatal` to `errorOrWarn`.

EhFrame.cpp is a helper file. We don't place all .eh_frame implementation there,
so the code move is fine.
  • Loading branch information
MaskRay committed Jan 19, 2022
1 parent b6a9396 commit eafd345
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 36 deletions.
23 changes: 0 additions & 23 deletions lld/ELF/EhFrame.cpp
Expand Up @@ -36,7 +36,6 @@ namespace {
class EhReader {
public:
EhReader(InputSectionBase *s, ArrayRef<uint8_t> d) : isec(s), d(d) {}
size_t readEhRecordSize();
uint8_t getFdeEncoding();
bool hasLSDA();

Expand All @@ -58,28 +57,6 @@ class EhReader {
};
}

size_t elf::readEhRecordSize(InputSectionBase *s, size_t off) {
return EhReader(s, s->data().slice(off)).readEhRecordSize();
}

// .eh_frame section is a sequence of records. Each record starts with
// a 4 byte length field. This function reads the length.
size_t EhReader::readEhRecordSize() {
if (d.size() < 4)
failOn(d.data(), "CIE/FDE too small");

// First 4 bytes of CIE/FDE is the size of the record.
// If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
// but we do not support that format yet.
uint64_t v = read32(d.data());
if (v == UINT32_MAX)
failOn(d.data(), "CIE/FDE too large");
uint64_t size = v + 4;
if (size > d.size())
failOn(d.data(), "CIE/FDE ends past the end of the section");
return size;
}

// Read a byte and advance D by one byte.
uint8_t EhReader::readByte() {
if (d.empty())
Expand Down
1 change: 0 additions & 1 deletion lld/ELF/EhFrame.h
Expand Up @@ -16,7 +16,6 @@ namespace elf {
class InputSectionBase;
struct EhSectionPiece;

size_t readEhRecordSize(InputSectionBase *s, size_t off);
uint8_t getFdeEncoding(EhSectionPiece *p);
bool hasLSDA(const EhSectionPiece &p);
} // namespace elf
Expand Down
46 changes: 34 additions & 12 deletions lld/ELF/InputSection.cpp
Expand Up @@ -1323,25 +1323,47 @@ static unsigned getReloc(IntTy begin, IntTy size, const ArrayRef<RelTy> &rels,
// This function splits an input section into records and returns them.
template <class ELFT> void EhInputSection::split() {
const RelsOrRelas<ELFT> rels = relsOrRelas<ELFT>();
if (rels.areRelocsRel())
split<ELFT>(rels.rels);
else
split<ELFT>(rels.relas);
// getReloc expects the relocations to be sorted by r_offset. See the comment
// in scanRelocs.
if (rels.areRelocsRel()) {
SmallVector<typename ELFT::Rel, 0> storage;
split<ELFT>(sortRels(rels.rels, storage));
} else {
SmallVector<typename ELFT::Rela, 0> storage;
split<ELFT>(sortRels(rels.relas, storage));
}
}

template <class ELFT, class RelTy>
void EhInputSection::split(ArrayRef<RelTy> rels) {
// getReloc expects the relocations to be sorted by r_offset. See the comment
// in scanRelocs.
SmallVector<RelTy, 0> storage;
rels = sortRels(rels, storage);

ArrayRef<uint8_t> d = rawData;
const char *msg = nullptr;
unsigned relI = 0;
for (size_t off = 0, end = data().size(); off != end;) {
size_t size = readEhRecordSize(this, off);
while (!d.empty()) {
if (d.size() < 4) {
msg = "CIE/FDE too small";
break;
}
uint64_t size = endian::read32<ELFT::TargetEndianness>(d.data());
// If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
// but we do not support that format yet.
if (size == UINT32_MAX) {
msg = "CIE/FDE too large";
break;
}
size += 4;
if (size > d.size()) {
msg = "CIE/FDE ends past the end of the section";
break;
}

uint64_t off = d.data() - rawData.data();
pieces.emplace_back(off, this, size, getReloc(off, size, rels, relI));
off += size;
d = d.slice(size);
}
if (msg)
errorOrWarn("corrupted .eh_frame: " + Twine(msg) + "\n>>> defined in " +
getObjMsg(d.data() - rawData.data()));
}

static size_t findNull(StringRef s, size_t entSize) {
Expand Down

0 comments on commit eafd345

Please sign in to comment.