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