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