From 966c1da7e6cc9e439be890129bc0f8fcfe9506ef Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sat, 4 May 2019 00:23:09 +0000 Subject: [PATCH] [JITLink] Add two useful Section operations: find by name, get address range. 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 --- .../llvm/ExecutionEngine/JITLink/JITLink.h | 71 +++++++++++++++++++ .../JITLink/EHFrameSupport.cpp | 11 +-- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/include/llvm/ExecutionEngine/JITLink/JITLink.h b/include/llvm/ExecutionEngine/JITLink/JITLink.h index 4bbb7d8b4b4..4e527f12c1f 100644 --- a/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -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>; @@ -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_atoms() { return make_range(ExternalAtoms.begin(), ExternalAtoms.end()); } diff --git a/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp index b54fd378aa5..67c37a5f9b1 100644 --- a/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp +++ b/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp @@ -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(); }; -- 2.40.0