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