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