Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:20

0001 //===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file declares the SymbolicFile interface.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_OBJECT_SYMBOLICFILE_H
0014 #define LLVM_OBJECT_SYMBOLICFILE_H
0015 
0016 #include "llvm/ADT/iterator_range.h"
0017 #include "llvm/BinaryFormat/Magic.h"
0018 #include "llvm/Object/Binary.h"
0019 #include "llvm/Support/Error.h"
0020 #include "llvm/Support/Format.h"
0021 #include "llvm/Support/MemoryBufferRef.h"
0022 #include <cinttypes>
0023 #include <cstdint>
0024 #include <cstring>
0025 #include <iterator>
0026 #include <memory>
0027 
0028 namespace llvm {
0029 
0030 class LLVMContext;
0031 class raw_ostream;
0032 
0033 namespace object {
0034 
0035 union DataRefImpl {
0036   // This entire union should probably be a
0037   // char[max(8, sizeof(uintptr_t))] and require the impl to cast.
0038   struct {
0039     uint32_t a, b;
0040   } d;
0041   uintptr_t p;
0042 
0043   DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); }
0044 };
0045 
0046 template <typename OStream>
0047 OStream& operator<<(OStream &OS, const DataRefImpl &D) {
0048   OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a)
0049      << ", " << format("0x%08x", D.d.b) << "))";
0050   return OS;
0051 }
0052 
0053 inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) {
0054   // Check bitwise identical. This is the only legal way to compare a union w/o
0055   // knowing which member is in use.
0056   return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
0057 }
0058 
0059 inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) {
0060   return !operator==(a, b);
0061 }
0062 
0063 inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) {
0064   // Check bitwise identical. This is the only legal way to compare a union w/o
0065   // knowing which member is in use.
0066   return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0;
0067 }
0068 
0069 template <class content_type> class content_iterator {
0070   content_type Current;
0071 
0072 public:
0073   using iterator_category = std::forward_iterator_tag;
0074   using value_type = const content_type;
0075   using difference_type = std::ptrdiff_t;
0076   using pointer = value_type *;
0077   using reference = value_type &;
0078 
0079   content_iterator(content_type symb) : Current(std::move(symb)) {}
0080 
0081   const content_type *operator->() const { return &Current; }
0082 
0083   const content_type &operator*() const { return Current; }
0084 
0085   bool operator==(const content_iterator &other) const {
0086     return Current == other.Current;
0087   }
0088 
0089   bool operator!=(const content_iterator &other) const {
0090     return !(*this == other);
0091   }
0092 
0093   content_iterator &operator++() { // preincrement
0094     Current.moveNext();
0095     return *this;
0096   }
0097 };
0098 
0099 class SymbolicFile;
0100 
0101 /// This is a value type class that represents a single symbol in the list of
0102 /// symbols in the object file.
0103 class BasicSymbolRef {
0104   DataRefImpl SymbolPimpl;
0105   const SymbolicFile *OwningObject = nullptr;
0106 
0107 public:
0108   enum Flags : unsigned {
0109     SF_None = 0,
0110     SF_Undefined = 1U << 0,      // Symbol is defined in another object file
0111     SF_Global = 1U << 1,         // Global symbol
0112     SF_Weak = 1U << 2,           // Weak symbol
0113     SF_Absolute = 1U << 3,       // Absolute symbol
0114     SF_Common = 1U << 4,         // Symbol has common linkage
0115     SF_Indirect = 1U << 5,       // Symbol is an alias to another symbol
0116     SF_Exported = 1U << 6,       // Symbol is visible to other DSOs
0117     SF_FormatSpecific = 1U << 7, // Specific to the object file format
0118                                  // (e.g. section symbols)
0119     SF_Thumb = 1U << 8,          // Thumb symbol in a 32-bit ARM binary
0120     SF_Hidden = 1U << 9,         // Symbol has hidden visibility
0121     SF_Const = 1U << 10,         // Symbol value is constant
0122     SF_Executable = 1U << 11,    // Symbol points to an executable section
0123                                  // (IR only)
0124   };
0125 
0126   BasicSymbolRef() = default;
0127   BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner);
0128 
0129   bool operator==(const BasicSymbolRef &Other) const;
0130   bool operator<(const BasicSymbolRef &Other) const;
0131 
0132   void moveNext();
0133 
0134   Error printName(raw_ostream &OS) const;
0135 
0136   /// Get symbol flags (bitwise OR of SymbolRef::Flags)
0137   Expected<uint32_t> getFlags() const;
0138 
0139   DataRefImpl getRawDataRefImpl() const;
0140   const SymbolicFile *getObject() const;
0141 };
0142 
0143 using basic_symbol_iterator = content_iterator<BasicSymbolRef>;
0144 
0145 class SymbolicFile : public Binary {
0146 public:
0147   SymbolicFile(unsigned int Type, MemoryBufferRef Source);
0148   ~SymbolicFile() override;
0149 
0150   // virtual interface.
0151   virtual void moveSymbolNext(DataRefImpl &Symb) const = 0;
0152 
0153   virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0;
0154 
0155   virtual Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const = 0;
0156 
0157   virtual basic_symbol_iterator symbol_begin() const = 0;
0158 
0159   virtual basic_symbol_iterator symbol_end() const = 0;
0160 
0161   virtual bool is64Bit() const = 0;
0162 
0163   // convenience wrappers.
0164   using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>;
0165   basic_symbol_iterator_range symbols() const {
0166     return basic_symbol_iterator_range(symbol_begin(), symbol_end());
0167   }
0168 
0169   // construction aux.
0170   static Expected<std::unique_ptr<SymbolicFile>>
0171   createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type,
0172                      LLVMContext *Context, bool InitContent = true);
0173 
0174   static Expected<std::unique_ptr<SymbolicFile>>
0175   createSymbolicFile(MemoryBufferRef Object) {
0176     return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr);
0177   }
0178 
0179   static bool classof(const Binary *v) {
0180     return v->isSymbolic();
0181   }
0182 
0183   static bool isSymbolicFile(file_magic Type, const LLVMContext *Context);
0184 };
0185 
0186 inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP,
0187                                       const SymbolicFile *Owner)
0188     : SymbolPimpl(SymbolP), OwningObject(Owner) {}
0189 
0190 inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const {
0191   return SymbolPimpl == Other.SymbolPimpl;
0192 }
0193 
0194 inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const {
0195   return SymbolPimpl < Other.SymbolPimpl;
0196 }
0197 
0198 inline void BasicSymbolRef::moveNext() {
0199   return OwningObject->moveSymbolNext(SymbolPimpl);
0200 }
0201 
0202 inline Error BasicSymbolRef::printName(raw_ostream &OS) const {
0203   return OwningObject->printSymbolName(OS, SymbolPimpl);
0204 }
0205 
0206 inline Expected<uint32_t> BasicSymbolRef::getFlags() const {
0207   return OwningObject->getSymbolFlags(SymbolPimpl);
0208 }
0209 
0210 inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const {
0211   return SymbolPimpl;
0212 }
0213 
0214 inline const SymbolicFile *BasicSymbolRef::getObject() const {
0215   return OwningObject;
0216 }
0217 
0218 } // end namespace object
0219 } // end namespace llvm
0220 
0221 #endif // LLVM_OBJECT_SYMBOLICFILE_H