SymbolicFile.h 6.8 KB

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