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/iterator_range.h" 17#include "llvm/BinaryFormat/Magic.h" 18#include "llvm/Object/Binary.h" 19#include "llvm/Support/Error.h" 20#include "llvm/Support/Format.h" 21#include "llvm/Support/MemoryBufferRef.h" 22#include <cinttypes> 23#include <cstdint> 24#include <cstring> 25#include <iterator> 26#include <memory> 27 28namespace llvm { 29 30class LLVMContext; 31class raw_ostream; 32 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> class content_iterator { 70 content_type Current; 71 72public: 73 using iterator_category = std::forward_iterator_tag; 74 using value_type = content_type; 75 using difference_type = std::ptrdiff_t; 76 using pointer = value_type *; 77 using reference = value_type &; 78 79 content_iterator(content_type symb) : Current(std::move(symb)) {} 80 81 const content_type *operator->() const { return &Current; } 82 83 const content_type &operator*() const { return Current; } 84 85 bool operator==(const content_iterator &other) const { 86 return Current == other.Current; 87 } 88 89 bool operator!=(const content_iterator &other) const { 90 return !(*this == other); 91 } 92 93 content_iterator &operator++() { // preincrement 94 Current.moveNext(); 95 return *this; 96 } 97}; 98 99class SymbolicFile; 100 101/// This is a value type class that represents a single symbol in the list of 102/// symbols in the object file. 103class BasicSymbolRef { 104 DataRefImpl SymbolPimpl; 105 const SymbolicFile *OwningObject = nullptr; 106 107public: 108 enum Flags : unsigned { 109 SF_None = 0, 110 SF_Undefined = 1U << 0, // Symbol is defined in another object file 111 SF_Global = 1U << 1, // Global symbol 112 SF_Weak = 1U << 2, // Weak symbol 113 SF_Absolute = 1U << 3, // Absolute symbol 114 SF_Common = 1U << 4, // Symbol has common linkage 115 SF_Indirect = 1U << 5, // Symbol is an alias to another symbol 116 SF_Exported = 1U << 6, // Symbol is visible to other DSOs 117 SF_FormatSpecific = 1U << 7, // Specific to the object file format 118 // (e.g. section symbols) 119 SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary 120 SF_Hidden = 1U << 9, // Symbol has hidden visibility 121 SF_Const = 1U << 10, // Symbol value is constant 122 SF_Executable = 1U << 11, // Symbol points to an executable section 123 // (IR only) 124 }; 125 126 BasicSymbolRef() = default; 127 BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); 128 129 bool operator==(const BasicSymbolRef &Other) const; 130 bool operator<(const BasicSymbolRef &Other) const; 131 132 void moveNext(); 133 134 Error printName(raw_ostream &OS) const; 135 136 /// Get symbol flags (bitwise OR of SymbolRef::Flags) 137 Expected<uint32_t> getFlags() const; 138 139 DataRefImpl getRawDataRefImpl() const; 140 const SymbolicFile *getObject() const; 141}; 142 143using basic_symbol_iterator = content_iterator<BasicSymbolRef>; 144 145class SymbolicFile : public Binary { 146public: 147 SymbolicFile(unsigned int Type, MemoryBufferRef Source); 148 ~SymbolicFile() override; 149 150 // virtual interface. 151 virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; 152 153 virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0; 154 155 virtual Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const = 0; 156 157 virtual basic_symbol_iterator symbol_begin() const = 0; 158 159 virtual basic_symbol_iterator symbol_end() const = 0; 160 161 virtual bool is64Bit() const = 0; 162 163 // convenience wrappers. 164 using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>; 165 basic_symbol_iterator_range symbols() const { 166 return basic_symbol_iterator_range(symbol_begin(), symbol_end()); 167 } 168 169 // construction aux. 170 static Expected<std::unique_ptr<SymbolicFile>> 171 createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, 172 LLVMContext *Context, bool InitContent = true); 173 174 static Expected<std::unique_ptr<SymbolicFile>> 175 createSymbolicFile(MemoryBufferRef Object) { 176 return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr); 177 } 178 179 static bool classof(const Binary *v) { 180 return v->isSymbolic(); 181 } 182 183 static bool isSymbolicFile(file_magic Type, const LLVMContext *Context); 184}; 185 186inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP, 187 const SymbolicFile *Owner) 188 : SymbolPimpl(SymbolP), OwningObject(Owner) {} 189 190inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const { 191 return SymbolPimpl == Other.SymbolPimpl; 192} 193 194inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const { 195 return SymbolPimpl < Other.SymbolPimpl; 196} 197 198inline void BasicSymbolRef::moveNext() { 199 return OwningObject->moveSymbolNext(SymbolPimpl); 200} 201 202inline Error BasicSymbolRef::printName(raw_ostream &OS) const { 203 return OwningObject->printSymbolName(OS, SymbolPimpl); 204} 205 206inline Expected<uint32_t> BasicSymbolRef::getFlags() const { 207 return OwningObject->getSymbolFlags(SymbolPimpl); 208} 209 210inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const { 211 return SymbolPimpl; 212} 213 214inline const SymbolicFile *BasicSymbolRef::getObject() const { 215 return OwningObject; 216} 217 218} // end namespace object 219} // end namespace llvm 220 221#endif // LLVM_OBJECT_SYMBOLICFILE_H 222