[PATCH] D65367: [Object] Create MutableELFObject Class for Doing Mutations on ELFObjectFiles [Part 2]

Alex Brachet via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 26 23:01:06 PDT 2019


abrachet created this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Added support for segments


https://reviews.llvm.org/D65367

Files:
  llvm/include/llvm/Object/MutableELFObject.h


Index: llvm/include/llvm/Object/MutableELFObject.h
===================================================================
--- llvm/include/llvm/Object/MutableELFObject.h
+++ llvm/include/llvm/Object/MutableELFObject.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include <set>
 
 namespace llvm {
 namespace object {
@@ -78,6 +79,28 @@
   return Ref;
 }
 
+template <typename ELFT>
+static bool sectionWithinSegment(const Elf_Shdr_Impl<ELFT> &Sec,
+                                 const Elf_Phdr_Impl<ELFT> &Seg) {
+  uint64_t SecSize = Sec.sh_size ? Sec.sh_size : 1;
+
+  if (Sec.sh_type == ELF::SHT_NOBITS) {
+    if (!(Sec.sh_flags & ELF::SHF_ALLOC))
+      return false;
+
+    bool SectionIsTLS = Sec.sh_flags & ELF::SHF_TLS;
+    bool SegmentIsTLS = Seg.p_type == ELF::PT_TLS;
+    if (SectionIsTLS != SegmentIsTLS)
+      return false;
+
+    return Seg.p_vaddr <= Sec.sh_addr &&
+           Seg.p_vaddr + Seg.p_memsz >= Sec.sh_addr + SecSize;
+  }
+
+  return Seg.p_offset <= Sec.sh_offset &&
+         Seg.p_offset + Seg.p_filesz >= Sec.sh_offset + SecSize;
+}
+
 template <typename ELFT> struct MutableELFSection {
   Elf_Shdr_Impl<ELFT> Header;
   std::string Name;
@@ -95,10 +118,42 @@
   }
 };
 
+template <typename ELFT> class MutableELFSegment {
+  std::set<uint64_t> Sections;
+
+public:
+  Elf_Phdr_Impl<ELFT> Header;
+  ArrayRef<uint8_t> Contents;
+
+  MutableELFSegment(uint64_t ToCopy, const MutableELFObject<ELFT> *ObjFile) {
+    const Elf_Ehdr_Impl<ELFT> &EHeader =
+        *reinterpret_cast<const Elf_Ehdr_Impl<ELFT> *>(ObjFile->base());
+    assert(ToCopy < EHeader.e_phnum && "Copying segment that doesn't exist");
+    Header = reinterpret_cast<const Elf_Phdr_Impl<ELFT> *>(
+        ObjFile->base() + EHeader.e_phoff)[ToCopy];
+    Contents = ArrayRef<uint8_t>(
+        reinterpret_cast<const uint8_t *>(ObjFile->base() + Header.p_offset),
+        Header.p_filesz);
+
+    ArrayRef<Elf_Shdr_Impl<ELFT>> SecHeaders(
+        reinterpret_cast<const Elf_Shdr_Impl<ELFT> *>(ObjFile->base() +
+                                                      EHeader.e_shoff),
+        EHeader.e_shnum);
+    uint64_t Index = 0;
+    for (const auto &Sec : SecHeaders) {
+      if (sectionWithinSegment(Sec, Header))
+        Sections.insert(Index);
+      ++Index;
+    }
+  }
+};
+
 template <typename ELFT> class MutableELFObject : public ELFObjectFile<ELFT> {
   friend struct MutableELFSection<ELFT>;
+  friend class MutableELFSegment<ELFT>;
 
   MutableRange<MutableELFSection<ELFT>> Sections;
+  std::vector<MutableELFSegment<ELFT>> Segments;
 
 protected:
   using MappingType =
@@ -132,7 +187,12 @@
   MutableELFObject(ELFObjectFile<ELFT> &B)
       : ELFObjectFile<ELFT>(std::move(B)),
         Sections(B.section_begin(), B.section_end(),
-                 [&](SectionRef Ref) { return Ref.getRawDataRefImpl().p; }) {}
+                 [&](SectionRef Ref) { return Ref.getRawDataRefImpl().p; }) {
+    const Elf_Ehdr_Impl<ELFT> *Header =
+        reinterpret_cast<const Elf_Ehdr_Impl<ELFT> *>(this->base());
+    for (int I = 0; I < Header->e_phnum; ++I)
+      Segments.emplace_back(I, this);
+  }
 
   section_iterator section_begin() const override {
     return section_iterator(SectionRef(toDataRef(0), this));


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D65367.212046.patch
Type: text/x-patch
Size: 3290 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190727/e58340e9/attachment.bin>


More information about the llvm-commits mailing list