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