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