1//===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the SymbolicFile interface.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_OBJECT_SYMBOLIC_FILE_H
15#define LLVM_OBJECT_SYMBOLIC_FILE_H
16
17#include "llvm/Object/Binary.h"
18
19namespace llvm {
20namespace object {
21
22union DataRefImpl {
23  // This entire union should probably be a
24  // char[max(8, sizeof(uintptr_t))] and require the impl to cast.
25  struct {
26    uint32_t a, b;
27  } d;
28  uintptr_t p;
29  DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); }
30};
31
32inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) {
33  // Check bitwise identical. This is the only legal way to compare a union w/o
34  // knowing which member is in use.
35  return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
36}
37
38inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) {
39  return !operator==(a, b);
40}
41
42inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) {
43  // Check bitwise identical. This is the only legal way to compare a union w/o
44  // knowing which member is in use.
45  return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0;
46}
47
48template <class content_type> class content_iterator {
49  content_type Current;
50
51public:
52  content_iterator(content_type symb) : Current(symb) {}
53
54  const content_type *operator->() const { return &Current; }
55
56  const content_type &operator*() const { return Current; }
57
58  bool operator==(const content_iterator &other) const {
59    return Current == other.Current;
60  }
61
62  bool operator!=(const content_iterator &other) const {
63    return !(*this == other);
64  }
65
66  content_iterator &operator++() { // preincrement
67    Current.moveNext();
68    return *this;
69  }
70};
71
72class SymbolicFile;
73
74/// This is a value type class that represents a single symbol in the list of
75/// symbols in the object file.
76class BasicSymbolRef {
77  DataRefImpl SymbolPimpl;
78  const SymbolicFile *OwningObject;
79
80public:
81  // FIXME: should we add a SF_Text?
82  enum Flags : unsigned {
83    SF_None = 0,
84    SF_Undefined = 1U << 0,      // Symbol is defined in another object file
85    SF_Global = 1U << 1,         // Global symbol
86    SF_Weak = 1U << 2,           // Weak symbol
87    SF_Absolute = 1U << 3,       // Absolute symbol
88    SF_Common = 1U << 4,         // Symbol has common linkage
89    SF_Indirect = 1U << 5,       // Symbol is an alias to another symbol
90    SF_FormatSpecific = 1U << 6  // Specific to the object file format
91                                 // (e.g. section symbols)
92  };
93
94  BasicSymbolRef() : OwningObject(nullptr) { }
95  BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner);
96
97  bool operator==(const BasicSymbolRef &Other) const;
98  bool operator<(const BasicSymbolRef &Other) const;
99
100  void moveNext();
101
102  std::error_code printName(raw_ostream &OS) const;
103
104  /// Get symbol flags (bitwise OR of SymbolRef::Flags)
105  uint32_t getFlags() const;
106
107  DataRefImpl getRawDataRefImpl() const;
108  const SymbolicFile *getObject() const;
109};
110
111typedef content_iterator<BasicSymbolRef> basic_symbol_iterator;
112
113const uint64_t UnknownAddressOrSize = ~0ULL;
114
115class SymbolicFile : public Binary {
116public:
117  virtual ~SymbolicFile();
118  SymbolicFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source);
119
120  // virtual interface.
121  virtual void moveSymbolNext(DataRefImpl &Symb) const = 0;
122
123  virtual std::error_code printSymbolName(raw_ostream &OS,
124                                          DataRefImpl Symb) const = 0;
125
126  virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0;
127
128  virtual basic_symbol_iterator symbol_begin_impl() const = 0;
129
130  virtual basic_symbol_iterator symbol_end_impl() const = 0;
131
132  // convenience wrappers.
133  basic_symbol_iterator symbol_begin() const {
134    return symbol_begin_impl();
135  }
136  basic_symbol_iterator symbol_end() const {
137    return symbol_end_impl();
138  }
139  typedef iterator_range<basic_symbol_iterator> basic_symbol_iterator_range;
140  basic_symbol_iterator_range symbols() const {
141    return basic_symbol_iterator_range(symbol_begin(), symbol_end());
142  }
143
144  // construction aux.
145  static ErrorOr<SymbolicFile *>
146  createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object,
147                     sys::fs::file_magic Type, LLVMContext *Context);
148
149  static ErrorOr<SymbolicFile *>
150  createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object) {
151    return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr);
152  }
153  static ErrorOr<SymbolicFile *> createSymbolicFile(StringRef ObjectPath);
154
155  static inline bool classof(const Binary *v) {
156    return v->isSymbolic();
157  }
158};
159
160inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP,
161                                      const SymbolicFile *Owner)
162    : SymbolPimpl(SymbolP), OwningObject(Owner) {}
163
164inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const {
165  return SymbolPimpl == Other.SymbolPimpl;
166}
167
168inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const {
169  return SymbolPimpl < Other.SymbolPimpl;
170}
171
172inline void BasicSymbolRef::moveNext() {
173  return OwningObject->moveSymbolNext(SymbolPimpl);
174}
175
176inline std::error_code BasicSymbolRef::printName(raw_ostream &OS) const {
177  return OwningObject->printSymbolName(OS, SymbolPimpl);
178}
179
180inline uint32_t BasicSymbolRef::getFlags() const {
181  return OwningObject->getSymbolFlags(SymbolPimpl);
182}
183
184inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const {
185  return SymbolPimpl;
186}
187
188inline const SymbolicFile *BasicSymbolRef::getObject() const {
189  return OwningObject;
190}
191
192}
193}
194
195#endif
196