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