[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