ObjectFile.h revision 0fcab076f0358890e2f1b213f4303c780e05d99d
1//===- ObjectFile.h - File format independent object file -------*- 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 a file format independent ObjectFile class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_OBJECT_OBJECT_FILE_H
15#define LLVM_OBJECT_OBJECT_FILE_H
16
17#include "llvm/Object/Binary.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/Support/DataTypes.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/MemoryBuffer.h"
22#include <cstring>
23
24namespace llvm {
25namespace object {
26
27class ObjectFile;
28
29union DataRefImpl {
30  struct {
31    uint32_t a, b;
32  } d;
33  uintptr_t p;
34};
35
36static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) {
37  // Check bitwise identical. This is the only legal way to compare a union w/o
38  // knowing which member is in use.
39  return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
40}
41
42/// SymbolRef - This is a value type class that represents a single symbol in
43/// the list of symbols in the object file.
44class SymbolRef {
45  friend class SectionRef;
46  DataRefImpl SymbolPimpl;
47  const ObjectFile *OwningObject;
48
49public:
50  SymbolRef() : OwningObject(NULL) {
51    std::memset(&SymbolPimpl, 0, sizeof(SymbolPimpl));
52  }
53
54  SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
55
56  bool operator==(const SymbolRef &Other) const;
57
58  error_code getNext(SymbolRef &Result) const;
59
60  error_code getName(StringRef &Result) const;
61  error_code getAddress(uint64_t &Result) const;
62  error_code getSize(uint64_t &Result) const;
63
64  /// Returns the ascii char that should be displayed in a symbol table dump via
65  /// nm for this symbol.
66  error_code getNMTypeChar(char &Result) const;
67
68  /// Returns true for symbols that are internal to the object file format such
69  /// as section symbols.
70  error_code isInternal(bool &Result) const;
71};
72
73/// RelocationRef - This is a value type class that represents a single
74/// relocation in the list of relocations in the object file.
75class RelocationRef {
76  DataRefImpl RelocationPimpl;
77  const ObjectFile *OwningObject;
78
79public:
80  RelocationRef() : OwningObject(NULL) {
81    std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl));
82  }
83
84  RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
85
86  bool operator==(const RelocationRef &Other) const;
87
88  error_code getNext(RelocationRef &Result) const;
89
90  error_code getAddress(uint64_t &Result) const;
91  error_code getSymbol(SymbolRef &Result) const;
92  error_code getType(uint32_t &Result) const;
93  error_code getAdditionalInfo(int64_t &Result) const;
94};
95
96/// SectionRef - This is a value type class that represents a single section in
97/// the list of sections in the object file.
98class SectionRef {
99  friend class SymbolRef;
100  DataRefImpl SectionPimpl;
101  const ObjectFile *OwningObject;
102
103public:
104  SectionRef() : OwningObject(NULL) {
105    std::memset(&SectionPimpl, 0, sizeof(SectionPimpl));
106  }
107
108  SectionRef(DataRefImpl SectionP, const ObjectFile *Owner);
109
110  bool operator==(const SectionRef &Other) const;
111
112  error_code getNext(SectionRef &Result) const;
113
114  error_code getName(StringRef &Result) const;
115  error_code getAddress(uint64_t &Result) const;
116  error_code getSize(uint64_t &Result) const;
117  error_code getContents(StringRef &Result) const;
118
119  // FIXME: Move to the normalization layer when it's created.
120  error_code isText(bool &Result) const;
121
122  error_code containsSymbol(SymbolRef S, bool &Result) const;
123};
124
125const uint64_t UnknownAddressOrSize = ~0ULL;
126
127/// ObjectFile - This class is the base class for all object file types.
128/// Concrete instances of this object are created by createObjectFile, which
129/// figure out which type to create.
130class ObjectFile : public Binary {
131private:
132  ObjectFile(); // = delete
133  ObjectFile(const ObjectFile &other); // = delete
134
135protected:
136  ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec);
137
138  const uint8_t *base() const {
139    return reinterpret_cast<const uint8_t *>(Data->getBufferStart());
140  }
141
142  // These functions are for SymbolRef to call internally. The main goal of
143  // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol
144  // entry in the memory mapped object file. SymbolPimpl cannot contain any
145  // virtual functions because then it could not point into the memory mapped
146  // file.
147  //
148  // Implementations assume that the DataRefImpl is valid and has not been
149  // modified externally. It's UB otherwise.
150  friend class SymbolRef;
151  virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0;
152  virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0;
153  virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0;
154  virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0;
155  virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0;
156  virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const = 0;
157
158  // Same as above for SectionRef.
159  friend class SectionRef;
160  virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0;
161  virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0;
162  virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0;
163  virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0;
164  virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0;
165  virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0;
166  virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
167                                           bool &Result) const = 0;
168
169
170  // Same as above for RelocationRef.
171  friend class RelocationRef;
172  virtual error_code getRelocationNext(DataRefImpl Rel,
173                                       RelocationRef &Res) const = 0;
174  virtual error_code getRelocationAddress(DataRefImpl Rel,
175                                          uint64_t &Res) const =0;
176  virtual error_code getRelocationSymbol(DataRefImpl Rel,
177                                         SymbolRef &Res) const = 0;
178  virtual error_code getRelocationType(DataRefImpl Rel,
179                                       uint32_t &Res) const = 0;
180  virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
181                                                 int64_t &Res) const = 0;
182
183public:
184  template<class content_type>
185  class content_iterator {
186    content_type Current;
187  public:
188    content_iterator(content_type symb)
189      : Current(symb) {}
190
191    const content_type* operator->() const {
192      return &Current;
193    }
194
195    const content_type &operator*() const {
196      return Current;
197    }
198
199    bool operator==(const content_iterator &other) const {
200      return Current == other.Current;
201    }
202
203    bool operator!=(const content_iterator &other) const {
204      return !(*this == other);
205    }
206
207    content_iterator& increment(error_code &err) {
208      content_type next;
209      if (error_code ec = Current.getNext(next))
210        err = ec;
211      else
212        Current = next;
213      return *this;
214    }
215  };
216
217  typedef content_iterator<SymbolRef> symbol_iterator;
218  typedef content_iterator<SectionRef> section_iterator;
219  typedef content_iterator<RelocationRef> relocation_iterator;
220
221  virtual symbol_iterator begin_symbols() const = 0;
222  virtual symbol_iterator end_symbols() const = 0;
223
224  virtual section_iterator begin_sections() const = 0;
225  virtual section_iterator end_sections() const = 0;
226
227  virtual relocation_iterator begin_relocations() const = 0;
228  virtual relocation_iterator end_relocations() const = 0;
229
230  /// @brief The number of bytes used to represent an address in this object
231  ///        file format.
232  virtual uint8_t getBytesInAddress() const = 0;
233
234  virtual StringRef getFileFormatName() const = 0;
235  virtual /* Triple::ArchType */ unsigned getArch() const = 0;
236
237  /// @returns Pointer to ObjectFile subclass to handle this type of object.
238  /// @param ObjectPath The path to the object file. ObjectPath.isObject must
239  ///        return true.
240  /// @brief Create ObjectFile from path.
241  static ObjectFile *createObjectFile(StringRef ObjectPath);
242  static ObjectFile *createObjectFile(MemoryBuffer *Object);
243
244  static inline bool classof(const Binary *v) {
245    return v->getType() >= isObject &&
246           v->getType() < lastObject;
247  }
248  static inline bool classof(const ObjectFile *v) { return true; }
249
250public:
251  static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object);
252  static ObjectFile *createELFObjectFile(MemoryBuffer *Object);
253  static ObjectFile *createMachOObjectFile(MemoryBuffer *Object);
254};
255
256// Inline function definitions.
257inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner)
258  : SymbolPimpl(SymbolP)
259  , OwningObject(Owner) {}
260
261inline bool SymbolRef::operator==(const SymbolRef &Other) const {
262  return SymbolPimpl == Other.SymbolPimpl;
263}
264
265inline error_code SymbolRef::getNext(SymbolRef &Result) const {
266  return OwningObject->getSymbolNext(SymbolPimpl, Result);
267}
268
269inline error_code SymbolRef::getName(StringRef &Result) const {
270  return OwningObject->getSymbolName(SymbolPimpl, Result);
271}
272
273inline error_code SymbolRef::getAddress(uint64_t &Result) const {
274  return OwningObject->getSymbolAddress(SymbolPimpl, Result);
275}
276
277inline error_code SymbolRef::getSize(uint64_t &Result) const {
278  return OwningObject->getSymbolSize(SymbolPimpl, Result);
279}
280
281inline error_code SymbolRef::getNMTypeChar(char &Result) const {
282  return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result);
283}
284
285inline error_code SymbolRef::isInternal(bool &Result) const {
286  return OwningObject->isSymbolInternal(SymbolPimpl, Result);
287}
288
289
290/// SectionRef
291inline SectionRef::SectionRef(DataRefImpl SectionP,
292                              const ObjectFile *Owner)
293  : SectionPimpl(SectionP)
294  , OwningObject(Owner) {}
295
296inline bool SectionRef::operator==(const SectionRef &Other) const {
297  return SectionPimpl == Other.SectionPimpl;
298}
299
300inline error_code SectionRef::getNext(SectionRef &Result) const {
301  return OwningObject->getSectionNext(SectionPimpl, Result);
302}
303
304inline error_code SectionRef::getName(StringRef &Result) const {
305  return OwningObject->getSectionName(SectionPimpl, Result);
306}
307
308inline error_code SectionRef::getAddress(uint64_t &Result) const {
309  return OwningObject->getSectionAddress(SectionPimpl, Result);
310}
311
312inline error_code SectionRef::getSize(uint64_t &Result) const {
313  return OwningObject->getSectionSize(SectionPimpl, Result);
314}
315
316inline error_code SectionRef::getContents(StringRef &Result) const {
317  return OwningObject->getSectionContents(SectionPimpl, Result);
318}
319
320inline error_code SectionRef::isText(bool &Result) const {
321  return OwningObject->isSectionText(SectionPimpl, Result);
322}
323
324inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const {
325  return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl,
326                                             Result);
327}
328
329
330/// RelocationRef
331inline RelocationRef::RelocationRef(DataRefImpl RelocationP,
332                              const ObjectFile *Owner)
333  : RelocationPimpl(RelocationP)
334  , OwningObject(Owner) {}
335
336inline bool RelocationRef::operator==(const RelocationRef &Other) const {
337  return RelocationPimpl == Other.RelocationPimpl;
338}
339
340inline error_code RelocationRef::getNext(RelocationRef &Result) const {
341  return OwningObject->getRelocationNext(RelocationPimpl, Result);
342}
343
344inline error_code RelocationRef::getAddress(uint64_t &Result) const {
345  return OwningObject->getRelocationAddress(RelocationPimpl, Result);
346}
347
348inline error_code RelocationRef::getSymbol(SymbolRef &Result) const {
349  return OwningObject->getRelocationSymbol(RelocationPimpl, Result);
350}
351
352inline error_code RelocationRef::getType(uint32_t &Result) const {
353  return OwningObject->getRelocationType(RelocationPimpl, Result);
354}
355
356inline error_code RelocationRef::getAdditionalInfo(int64_t &Result) const {
357  return OwningObject->getRelocationAdditionalInfo(RelocationPimpl, Result);
358}
359
360} // end namespace object
361} // end namespace llvm
362
363#endif
364