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