Home | History | Annotate | Download | only in Object
      1 //===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file declares the SymbolicFile interface.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_OBJECT_SYMBOLICFILE_H
     15 #define LLVM_OBJECT_SYMBOLICFILE_H
     16 
     17 #include "llvm/ADT/StringRef.h"
     18 #include "llvm/ADT/iterator_range.h"
     19 #include "llvm/BinaryFormat/Magic.h"
     20 #include "llvm/Object/Binary.h"
     21 #include "llvm/Support/Error.h"
     22 #include "llvm/Support/FileSystem.h"
     23 #include "llvm/Support/Format.h"
     24 #include "llvm/Support/MemoryBuffer.h"
     25 #include <cinttypes>
     26 #include <cstdint>
     27 #include <cstring>
     28 #include <iterator>
     29 #include <memory>
     30 #include <system_error>
     31 
     32 namespace llvm {
     33 namespace object {
     34 
     35 union DataRefImpl {
     36   // This entire union should probably be a
     37   // char[max(8, sizeof(uintptr_t))] and require the impl to cast.
     38   struct {
     39     uint32_t a, b;
     40   } d;
     41   uintptr_t p;
     42 
     43   DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); }
     44 };
     45 
     46 template <typename OStream>
     47 OStream& operator<<(OStream &OS, const DataRefImpl &D) {
     48   OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a)
     49      << ", " << format("0x%08x", D.d.b) << "))";
     50   return OS;
     51 }
     52 
     53 inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) {
     54   // Check bitwise identical. This is the only legal way to compare a union w/o
     55   // knowing which member is in use.
     56   return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
     57 }
     58 
     59 inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) {
     60   return !operator==(a, b);
     61 }
     62 
     63 inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) {
     64   // Check bitwise identical. This is the only legal way to compare a union w/o
     65   // knowing which member is in use.
     66   return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0;
     67 }
     68 
     69 template <class content_type>
     70 class content_iterator
     71     : public std::iterator<std::forward_iterator_tag, content_type> {
     72   content_type Current;
     73 
     74 public:
     75   content_iterator(content_type symb) : Current(std::move(symb)) {}
     76 
     77   const content_type *operator->() const { return &Current; }
     78 
     79   const content_type &operator*() const { return Current; }
     80 
     81   bool operator==(const content_iterator &other) const {
     82     return Current == other.Current;
     83   }
     84 
     85   bool operator!=(const content_iterator &other) const {
     86     return !(*this == other);
     87   }
     88 
     89   content_iterator &operator++() { // preincrement
     90     Current.moveNext();
     91     return *this;
     92   }
     93 };
     94 
     95 class SymbolicFile;
     96 
     97 /// This is a value type class that represents a single symbol in the list of
     98 /// symbols in the object file.
     99 class BasicSymbolRef {
    100   DataRefImpl SymbolPimpl;
    101   const SymbolicFile *OwningObject = nullptr;
    102 
    103 public:
    104   enum Flags : unsigned {
    105     SF_None = 0,
    106     SF_Undefined = 1U << 0,      // Symbol is defined in another object file
    107     SF_Global = 1U << 1,         // Global symbol
    108     SF_Weak = 1U << 2,           // Weak symbol
    109     SF_Absolute = 1U << 3,       // Absolute symbol
    110     SF_Common = 1U << 4,         // Symbol has common linkage
    111     SF_Indirect = 1U << 5,       // Symbol is an alias to another symbol
    112     SF_Exported = 1U << 6,       // Symbol is visible to other DSOs
    113     SF_FormatSpecific = 1U << 7, // Specific to the object file format
    114                                  // (e.g. section symbols)
    115     SF_Thumb = 1U << 8,          // Thumb symbol in a 32-bit ARM binary
    116     SF_Hidden = 1U << 9,         // Symbol has hidden visibility
    117     SF_Const = 1U << 10,         // Symbol value is constant
    118     SF_Executable = 1U << 11,    // Symbol points to an executable section
    119                                  // (IR only)
    120   };
    121 
    122   BasicSymbolRef() = default;
    123   BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner);
    124 
    125   bool operator==(const BasicSymbolRef &Other) const;
    126   bool operator<(const BasicSymbolRef &Other) const;
    127 
    128   void moveNext();
    129 
    130   std::error_code printName(raw_ostream &OS) const;
    131 
    132   /// Get symbol flags (bitwise OR of SymbolRef::Flags)
    133   uint32_t getFlags() const;
    134 
    135   DataRefImpl getRawDataRefImpl() const;
    136   const SymbolicFile *getObject() const;
    137 };
    138 
    139 using basic_symbol_iterator = content_iterator<BasicSymbolRef>;
    140 
    141 class SymbolicFile : public Binary {
    142 public:
    143   SymbolicFile(unsigned int Type, MemoryBufferRef Source);
    144   ~SymbolicFile() override;
    145 
    146   // virtual interface.
    147   virtual void moveSymbolNext(DataRefImpl &Symb) const = 0;
    148 
    149   virtual std::error_code printSymbolName(raw_ostream &OS,
    150                                           DataRefImpl Symb) const = 0;
    151 
    152   virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0;
    153 
    154   virtual basic_symbol_iterator symbol_begin() const = 0;
    155 
    156   virtual basic_symbol_iterator symbol_end() const = 0;
    157 
    158   // convenience wrappers.
    159   using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>;
    160   basic_symbol_iterator_range symbols() const {
    161     return basic_symbol_iterator_range(symbol_begin(), symbol_end());
    162   }
    163 
    164   // construction aux.
    165   static Expected<std::unique_ptr<SymbolicFile>>
    166   createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type,
    167                      LLVMContext *Context);
    168 
    169   static Expected<std::unique_ptr<SymbolicFile>>
    170   createSymbolicFile(MemoryBufferRef Object) {
    171     return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr);
    172   }
    173   static Expected<OwningBinary<SymbolicFile>>
    174   createSymbolicFile(StringRef ObjectPath);
    175 
    176   static bool classof(const Binary *v) {
    177     return v->isSymbolic();
    178   }
    179 };
    180 
    181 inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP,
    182                                       const SymbolicFile *Owner)
    183     : SymbolPimpl(SymbolP), OwningObject(Owner) {}
    184 
    185 inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const {
    186   return SymbolPimpl == Other.SymbolPimpl;
    187 }
    188 
    189 inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const {
    190   return SymbolPimpl < Other.SymbolPimpl;
    191 }
    192 
    193 inline void BasicSymbolRef::moveNext() {
    194   return OwningObject->moveSymbolNext(SymbolPimpl);
    195 }
    196 
    197 inline std::error_code BasicSymbolRef::printName(raw_ostream &OS) const {
    198   return OwningObject->printSymbolName(OS, SymbolPimpl);
    199 }
    200 
    201 inline uint32_t BasicSymbolRef::getFlags() const {
    202   return OwningObject->getSymbolFlags(SymbolPimpl);
    203 }
    204 
    205 inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const {
    206   return SymbolPimpl;
    207 }
    208 
    209 inline const SymbolicFile *BasicSymbolRef::getObject() const {
    210   return OwningObject;
    211 }
    212 
    213 } // end namespace object
    214 } // end namespace llvm
    215 
    216 #endif // LLVM_OBJECT_SYMBOLICFILE_H
    217