]> granicus.if.org Git - llvm/commitdiff
[JITLink] Add two useful Section operations: find by name, get address range.
authorLang Hames <lhames@gmail.com>
Sat, 4 May 2019 00:23:09 +0000 (00:23 +0000)
committerLang Hames <lhames@gmail.com>
Sat, 4 May 2019 00:23:09 +0000 (00:23 +0000)
These operations were already used in eh-frame registration, and are likely to
be used in other runtime registrations, so this commit moves them into a header
where they can be re-used.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359950 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ExecutionEngine/JITLink/JITLink.h
lib/ExecutionEngine/JITLink/EHFrameSupport.cpp

index 4bbb7d8b4b4dfc5f81ba04c0af7337979c6a9e8d..4e527f12c1f01b5247edd244dfbb69a6f9458309 100644 (file)
@@ -296,6 +296,34 @@ raw_ostream &operator<<(raw_ostream &OS, const Atom &A);
 void printEdge(raw_ostream &OS, const Atom &FixupAtom, const Edge &E,
                StringRef EdgeKindName);
 
+/// Represents a section address range via a pair of DefinedAtom pointers to
+/// the first and last atoms in the section.
+class SectionRange {
+public:
+  SectionRange() = default;
+  SectionRange(DefinedAtom *First, DefinedAtom *Last)
+      : First(First), Last(Last) {}
+  DefinedAtom *getFirstAtom() const {
+    assert((!Last || First) && "First can not be null if end is non-null");
+    return First;
+  }
+  DefinedAtom *getLastAtom() const {
+    assert((First || !Last) && "Last can not be null if start is non-null");
+    return Last;
+  }
+  bool isEmpty() const {
+    assert((First || !Last) && "Last can not be null if start is non-null");
+    return !First;
+  }
+  JITTargetAddress getStart() const;
+  JITTargetAddress getEnd() const;
+  uint64_t getSize() const;
+
+private:
+  DefinedAtom *First = nullptr;
+  DefinedAtom *Last = nullptr;
+};
+
 /// Represents an object file section.
 class Section {
   friend class AtomGraph;
@@ -337,6 +365,17 @@ public:
   /// Return true if this section contains no atoms.
   bool atoms_empty() const { return DefinedAtoms.empty(); }
 
+  /// Returns the range of this section as the pair of atoms with the lowest
+  /// and highest target address. This operation is expensive, as it
+  /// must traverse all atoms in the section.
+  ///
+  /// Note: If the section is empty, both values will be null. The section
+  /// address will evaluate to null, and the size to zero. If the section
+  /// contains a single atom both values will point to it, the address will
+  /// evaluate to the address of that atom, and the size will be the size of
+  /// that atom.
+  SectionRange getRange() const;
+
 private:
   void addAtom(DefinedAtom &DA) {
     assert(!DefinedAtoms.count(&DA) && "Atom is already in this section");
@@ -458,6 +497,29 @@ private:
   uint32_t Alignment = 0;
 };
 
+inline JITTargetAddress SectionRange::getStart() const {
+  return First ? First->getAddress() : 0;
+}
+
+inline JITTargetAddress SectionRange::getEnd() const {
+  return Last ? Last->getAddress() + Last->getSize() : 0;
+}
+
+inline uint64_t SectionRange::getSize() const { return getEnd() - getStart(); }
+
+inline SectionRange Section::getRange() const {
+  if (atoms_empty())
+    return SectionRange();
+  DefinedAtom *First = *DefinedAtoms.begin(), *Last = *DefinedAtoms.end();
+  for (auto *DA : atoms()) {
+    if (DA->getAddress() < First->getAddress())
+      First = DA;
+    if (DA->getAddress() > Last->getAddress())
+      Last = DA;
+  }
+  return SectionRange(First, Last);
+}
+
 class AtomGraph {
 private:
   using SectionList = std::vector<std::unique_ptr<Section>>;
@@ -621,6 +683,15 @@ public:
                       section_iterator(Sections.end()));
   }
 
+  /// Returns the section with the given name if it exists, otherwise returns
+  /// null.
+  Section *findSectionByName(StringRef Name) {
+    for (auto &S : sections())
+      if (S.getName() == Name)
+        return &S;
+    return nullptr;
+  }
+
   iterator_range<external_atom_iterator> external_atoms() {
     return make_range(ExternalAtoms.begin(), ExternalAtoms.end());
   }
index b54fd378aa59a98dd8e5e5bdafdbd07f7469dae6..67c37a5f9b15600d7daadb005218557f19fe7053 100644 (file)
@@ -521,15 +521,8 @@ createEHFrameRecorderPass(const Triple &TT,
     // Search for a non-empty eh-frame and record the address of the first atom
     // in it.
     JITTargetAddress Addr = 0;
-    for (auto &S : G.sections())
-      if (S.getName() == EHFrameSectionName && !S.atoms_empty()) {
-        Addr = (*S.atoms().begin())->getAddress();
-        for (auto *DA : S.atoms())
-          if (DA->getAddress() < Addr)
-            Addr = DA->getAddress();
-        break;
-      }
-
+    if (auto *S = G.findSectionByName(EHFrameSectionName))
+      Addr = S->getRange().getStart();
     StoreFrameAddress(Addr);
     return Error::success();
   };