[lld] eafd345 - [ELF] Simplify/optimize EhInputSection::split
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 18 17:03:28 PST 2022
Author: Fangrui Song
Date: 2022-01-18T17:03:23-08:00
New Revision: eafd34581f588d84c54cbc370c29e3625d6ad41d
URL: https://github.com/llvm/llvm-project/commit/eafd34581f588d84c54cbc370c29e3625d6ad41d
DIFF: https://github.com/llvm/llvm-project/commit/eafd34581f588d84c54cbc370c29e3625d6ad41d.diff
LOG: [ELF] Simplify/optimize EhInputSection::split
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.
Added:
Modified:
lld/ELF/EhFrame.cpp
lld/ELF/EhFrame.h
lld/ELF/InputSection.cpp
Removed:
################################################################################
diff --git a/lld/ELF/EhFrame.cpp b/lld/ELF/EhFrame.cpp
index 578c640f0214d..9ac2ed772073a 100644
--- a/lld/ELF/EhFrame.cpp
+++ b/lld/ELF/EhFrame.cpp
@@ -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();
@@ -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())
diff --git a/lld/ELF/EhFrame.h b/lld/ELF/EhFrame.h
index e44832317b3a3..3b144648cf8f8 100644
--- a/lld/ELF/EhFrame.h
+++ b/lld/ELF/EhFrame.h
@@ -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
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index db439c31bccec..006c7308c5821 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -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) {
More information about the llvm-commits
mailing list