diff options
Diffstat (limited to 'third_party/llvm-project/include/llvm/Object/SymbolicFile.h')
-rw-r--r-- | third_party/llvm-project/include/llvm/Object/SymbolicFile.h | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/third_party/llvm-project/include/llvm/Object/SymbolicFile.h b/third_party/llvm-project/include/llvm/Object/SymbolicFile.h new file mode 100644 index 000000000..1398fa134 --- /dev/null +++ b/third_party/llvm-project/include/llvm/Object/SymbolicFile.h @@ -0,0 +1,214 @@ +//===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the SymbolicFile interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_SYMBOLICFILE_H +#define LLVM_OBJECT_SYMBOLICFILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/Object/Binary.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cinttypes> +#include <cstdint> +#include <cstring> +#include <iterator> +#include <memory> +#include <system_error> + +namespace llvm { +namespace object { + +union DataRefImpl { + // This entire union should probably be a + // char[max(8, sizeof(uintptr_t))] and require the impl to cast. + struct { + uint32_t a, b; + } d; + uintptr_t p; + + DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); } +}; + +template <typename OStream> +OStream& operator<<(OStream &OS, const DataRefImpl &D) { + OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a) + << ", " << format("0x%08x", D.d.b) << "))"; + return OS; +} + +inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + +inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) { + return !operator==(a, b); +} + +inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; +} + +template <class content_type> +class content_iterator + : public std::iterator<std::forward_iterator_tag, content_type> { + content_type Current; + +public: + content_iterator(content_type symb) : Current(std::move(symb)) {} + + const content_type *operator->() const { return &Current; } + + const content_type &operator*() const { return Current; } + + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } + + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } + + content_iterator &operator++() { // preincrement + Current.moveNext(); + return *this; + } +}; + +class SymbolicFile; + +/// This is a value type class that represents a single symbol in the list of +/// symbols in the object file. +class BasicSymbolRef { + DataRefImpl SymbolPimpl; + const SymbolicFile *OwningObject = nullptr; + +public: + enum Flags : unsigned { + SF_None = 0, + SF_Undefined = 1U << 0, // Symbol is defined in another object file + SF_Global = 1U << 1, // Global symbol + SF_Weak = 1U << 2, // Weak symbol + SF_Absolute = 1U << 3, // Absolute symbol + SF_Common = 1U << 4, // Symbol has common linkage + SF_Indirect = 1U << 5, // Symbol is an alias to another symbol + SF_Exported = 1U << 6, // Symbol is visible to other DSOs + SF_FormatSpecific = 1U << 7, // Specific to the object file format + // (e.g. section symbols) + SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary + SF_Hidden = 1U << 9, // Symbol has hidden visibility + SF_Const = 1U << 10, // Symbol value is constant + SF_Executable = 1U << 11, // Symbol points to an executable section + // (IR only) + }; + + BasicSymbolRef() = default; + BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); + + bool operator==(const BasicSymbolRef &Other) const; + bool operator<(const BasicSymbolRef &Other) const; + + void moveNext(); + + Error printName(raw_ostream &OS) const; + + /// Get symbol flags (bitwise OR of SymbolRef::Flags) + uint32_t getFlags() const; + + DataRefImpl getRawDataRefImpl() const; + const SymbolicFile *getObject() const; +}; + +using basic_symbol_iterator = content_iterator<BasicSymbolRef>; + +class SymbolicFile : public Binary { +public: + SymbolicFile(unsigned int Type, MemoryBufferRef Source); + ~SymbolicFile() override; + + // virtual interface. + virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; + + virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0; + + virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; + + virtual basic_symbol_iterator symbol_begin() const = 0; + + virtual basic_symbol_iterator symbol_end() const = 0; + + // convenience wrappers. + using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>; + basic_symbol_iterator_range symbols() const { + return basic_symbol_iterator_range(symbol_begin(), symbol_end()); + } + + // construction aux. + static Expected<std::unique_ptr<SymbolicFile>> + createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, + LLVMContext *Context); + + static Expected<std::unique_ptr<SymbolicFile>> + createSymbolicFile(MemoryBufferRef Object) { + return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr); + } + static Expected<OwningBinary<SymbolicFile>> + createSymbolicFile(StringRef ObjectPath); + + static bool classof(const Binary *v) { + return v->isSymbolic(); + } +}; + +inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP, + const SymbolicFile *Owner) + : SymbolPimpl(SymbolP), OwningObject(Owner) {} + +inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const { + return SymbolPimpl == Other.SymbolPimpl; +} + +inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const { + return SymbolPimpl < Other.SymbolPimpl; +} + +inline void BasicSymbolRef::moveNext() { + return OwningObject->moveSymbolNext(SymbolPimpl); +} + +inline Error BasicSymbolRef::printName(raw_ostream &OS) const { + return OwningObject->printSymbolName(OS, SymbolPimpl); +} + +inline uint32_t BasicSymbolRef::getFlags() const { + return OwningObject->getSymbolFlags(SymbolPimpl); +} + +inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const { + return SymbolPimpl; +} + +inline const SymbolicFile *BasicSymbolRef::getObject() const { + return OwningObject; +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_SYMBOLICFILE_H |