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