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_OBJECTFILE_H
15#define LLVM_OBJECT_OBJECTFILE_H
16
17#include "llvm/ADT/StringRef.h"
18#include "llvm/MC/SubtargetFeature.h"
19#include "llvm/Object/SymbolicFile.h"
20#include "llvm/Support/DataTypes.h"
21#include "llvm/Support/ErrorHandling.h"
22#include "llvm/Support/FileSystem.h"
23#include "llvm/Support/MemoryBuffer.h"
24#include <cstring>
25
26namespace llvm {
27namespace object {
28
29class ObjectFile;
30class COFFObjectFile;
31class MachOObjectFile;
32
33class SymbolRef;
34class symbol_iterator;
35class SectionRef;
36typedef content_iterator<SectionRef> section_iterator;
37
38/// This is a value type class that represents a single relocation in the list
39/// of relocations in the object file.
40class RelocationRef {
41  DataRefImpl RelocationPimpl;
42  const ObjectFile *OwningObject;
43
44public:
45  RelocationRef() : OwningObject(nullptr) { }
46
47  RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
48
49  bool operator==(const RelocationRef &Other) const;
50
51  void moveNext();
52
53  uint64_t getOffset() const;
54  symbol_iterator getSymbol() const;
55  uint64_t getType() const;
56
57  /// @brief Get a string that represents the type of this relocation.
58  ///
59  /// This is for display purposes only.
60  void getTypeName(SmallVectorImpl<char> &Result) const;
61
62  DataRefImpl getRawDataRefImpl() const;
63  const ObjectFile *getObject() const;
64};
65typedef content_iterator<RelocationRef> relocation_iterator;
66
67/// This is a value type class that represents a single section in the list of
68/// sections in the object file.
69class SectionRef {
70  friend class SymbolRef;
71  DataRefImpl SectionPimpl;
72  const ObjectFile *OwningObject;
73
74public:
75  SectionRef() : OwningObject(nullptr) { }
76
77  SectionRef(DataRefImpl SectionP, const ObjectFile *Owner);
78
79  bool operator==(const SectionRef &Other) const;
80  bool operator!=(const SectionRef &Other) const;
81  bool operator<(const SectionRef &Other) const;
82
83  void moveNext();
84
85  std::error_code getName(StringRef &Result) const;
86  uint64_t getAddress() const;
87  uint64_t getSize() const;
88  std::error_code getContents(StringRef &Result) const;
89
90  /// @brief Get the alignment of this section as the actual value (not log 2).
91  uint64_t getAlignment() const;
92
93  bool isCompressed() const;
94  bool isText() const;
95  bool isData() const;
96  bool isBSS() const;
97  bool isVirtual() const;
98  bool isBitcode() const;
99
100  bool containsSymbol(SymbolRef S) const;
101
102  relocation_iterator relocation_begin() const;
103  relocation_iterator relocation_end() const;
104  iterator_range<relocation_iterator> relocations() const {
105    return make_range(relocation_begin(), relocation_end());
106  }
107  section_iterator getRelocatedSection() const;
108
109  DataRefImpl getRawDataRefImpl() const;
110  const ObjectFile *getObject() const;
111};
112
113/// This is a value type class that represents a single symbol in the list of
114/// symbols in the object file.
115class SymbolRef : public BasicSymbolRef {
116  friend class SectionRef;
117
118public:
119  SymbolRef() : BasicSymbolRef() {}
120
121  enum Type {
122    ST_Unknown, // Type not specified
123    ST_Data,
124    ST_Debug,
125    ST_File,
126    ST_Function,
127    ST_Other
128  };
129
130  SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
131  SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) {
132    assert(isa<ObjectFile>(BasicSymbolRef::getObject()));
133  }
134
135  Expected<StringRef> getName() const;
136  /// Returns the symbol virtual address (i.e. address at which it will be
137  /// mapped).
138  Expected<uint64_t> getAddress() const;
139
140  /// Return the value of the symbol depending on the object this can be an
141  /// offset or a virtual address.
142  uint64_t getValue() const;
143
144  /// @brief Get the alignment of this symbol as the actual value (not log 2).
145  uint32_t getAlignment() const;
146  uint64_t getCommonSize() const;
147  Expected<SymbolRef::Type> getType() const;
148
149  /// @brief Get section this symbol is defined in reference to. Result is
150  /// end_sections() if it is undefined or is an absolute symbol.
151  Expected<section_iterator> getSection() const;
152
153  const ObjectFile *getObject() const;
154};
155
156class symbol_iterator : public basic_symbol_iterator {
157public:
158  symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {}
159  symbol_iterator(const basic_symbol_iterator &B)
160      : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(),
161                                        cast<ObjectFile>(B->getObject()))) {}
162
163  const SymbolRef *operator->() const {
164    const BasicSymbolRef &P = basic_symbol_iterator::operator *();
165    return static_cast<const SymbolRef*>(&P);
166  }
167
168  const SymbolRef &operator*() const {
169    const BasicSymbolRef &P = basic_symbol_iterator::operator *();
170    return static_cast<const SymbolRef&>(P);
171  }
172};
173
174/// This class is the base class for all object file types. Concrete instances
175/// of this object are created by createObjectFile, which figures out which type
176/// to create.
177class ObjectFile : public SymbolicFile {
178  virtual void anchor();
179  ObjectFile() = delete;
180  ObjectFile(const ObjectFile &other) = delete;
181
182protected:
183  ObjectFile(unsigned int Type, MemoryBufferRef Source);
184
185  const uint8_t *base() const {
186    return reinterpret_cast<const uint8_t *>(Data.getBufferStart());
187  }
188
189  // These functions are for SymbolRef to call internally. The main goal of
190  // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol
191  // entry in the memory mapped object file. SymbolPimpl cannot contain any
192  // virtual functions because then it could not point into the memory mapped
193  // file.
194  //
195  // Implementations assume that the DataRefImpl is valid and has not been
196  // modified externally. It's UB otherwise.
197  friend class SymbolRef;
198  virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
199  std::error_code printSymbolName(raw_ostream &OS,
200                                  DataRefImpl Symb) const override;
201  virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0;
202  virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0;
203  virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
204  virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0;
205  virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0;
206  virtual Expected<section_iterator>
207  getSymbolSection(DataRefImpl Symb) const = 0;
208
209  // Same as above for SectionRef.
210  friend class SectionRef;
211  virtual void moveSectionNext(DataRefImpl &Sec) const = 0;
212  virtual std::error_code getSectionName(DataRefImpl Sec,
213                                         StringRef &Res) const = 0;
214  virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0;
215  virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0;
216  virtual std::error_code getSectionContents(DataRefImpl Sec,
217                                             StringRef &Res) const = 0;
218  virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
219  virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
220  virtual bool isSectionText(DataRefImpl Sec) const = 0;
221  virtual bool isSectionData(DataRefImpl Sec) const = 0;
222  virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
223  // A section is 'virtual' if its contents aren't present in the object image.
224  virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
225  virtual bool isSectionBitcode(DataRefImpl Sec) const;
226  virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
227  virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
228  virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
229
230  // Same as above for RelocationRef.
231  friend class RelocationRef;
232  virtual void moveRelocationNext(DataRefImpl &Rel) const = 0;
233  virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0;
234  virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
235  virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0;
236  virtual void getRelocationTypeName(DataRefImpl Rel,
237                                     SmallVectorImpl<char> &Result) const = 0;
238
239  uint64_t getSymbolValue(DataRefImpl Symb) const;
240
241public:
242  uint64_t getCommonSymbolSize(DataRefImpl Symb) const {
243    assert(getSymbolFlags(Symb) & SymbolRef::SF_Common);
244    return getCommonSymbolSizeImpl(Symb);
245  }
246
247  typedef iterator_range<symbol_iterator> symbol_iterator_range;
248  symbol_iterator_range symbols() const {
249    return symbol_iterator_range(symbol_begin(), symbol_end());
250  }
251
252  virtual section_iterator section_begin() const = 0;
253  virtual section_iterator section_end() const = 0;
254
255  typedef iterator_range<section_iterator> section_iterator_range;
256  section_iterator_range sections() const {
257    return section_iterator_range(section_begin(), section_end());
258  }
259
260  /// @brief The number of bytes used to represent an address in this object
261  ///        file format.
262  virtual uint8_t getBytesInAddress() const = 0;
263
264  virtual StringRef getFileFormatName() const = 0;
265  virtual /* Triple::ArchType */ unsigned getArch() const = 0;
266  virtual SubtargetFeatures getFeatures() const = 0;
267
268  /// Returns platform-specific object flags, if any.
269  virtual std::error_code getPlatformFlags(unsigned &Result) const {
270    Result = 0;
271    return object_error::invalid_file_type;
272  }
273
274  /// True if this is a relocatable object (.o/.obj).
275  virtual bool isRelocatableObject() const = 0;
276
277  /// @returns Pointer to ObjectFile subclass to handle this type of object.
278  /// @param ObjectPath The path to the object file. ObjectPath.isObject must
279  ///        return true.
280  /// @brief Create ObjectFile from path.
281  static Expected<OwningBinary<ObjectFile>>
282  createObjectFile(StringRef ObjectPath);
283
284  static Expected<std::unique_ptr<ObjectFile>>
285  createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type);
286  static Expected<std::unique_ptr<ObjectFile>>
287  createObjectFile(MemoryBufferRef Object) {
288    return createObjectFile(Object, sys::fs::file_magic::unknown);
289  }
290
291
292  static inline bool classof(const Binary *v) {
293    return v->isObject();
294  }
295
296  static ErrorOr<std::unique_ptr<COFFObjectFile>>
297  createCOFFObjectFile(MemoryBufferRef Object);
298
299  static ErrorOr<std::unique_ptr<ObjectFile>>
300  createELFObjectFile(MemoryBufferRef Object);
301
302  static Expected<std::unique_ptr<MachOObjectFile>>
303  createMachOObjectFile(MemoryBufferRef Object);
304
305};
306
307// Inline function definitions.
308inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner)
309    : BasicSymbolRef(SymbolP, Owner) {}
310
311inline Expected<StringRef> SymbolRef::getName() const {
312  return getObject()->getSymbolName(getRawDataRefImpl());
313}
314
315inline Expected<uint64_t> SymbolRef::getAddress() const {
316  return getObject()->getSymbolAddress(getRawDataRefImpl());
317}
318
319inline uint64_t SymbolRef::getValue() const {
320  return getObject()->getSymbolValue(getRawDataRefImpl());
321}
322
323inline uint32_t SymbolRef::getAlignment() const {
324  return getObject()->getSymbolAlignment(getRawDataRefImpl());
325}
326
327inline uint64_t SymbolRef::getCommonSize() const {
328  return getObject()->getCommonSymbolSize(getRawDataRefImpl());
329}
330
331inline Expected<section_iterator> SymbolRef::getSection() const {
332  return getObject()->getSymbolSection(getRawDataRefImpl());
333}
334
335inline Expected<SymbolRef::Type> SymbolRef::getType() const {
336  return getObject()->getSymbolType(getRawDataRefImpl());
337}
338
339inline const ObjectFile *SymbolRef::getObject() const {
340  const SymbolicFile *O = BasicSymbolRef::getObject();
341  return cast<ObjectFile>(O);
342}
343
344
345/// SectionRef
346inline SectionRef::SectionRef(DataRefImpl SectionP,
347                              const ObjectFile *Owner)
348  : SectionPimpl(SectionP)
349  , OwningObject(Owner) {}
350
351inline bool SectionRef::operator==(const SectionRef &Other) const {
352  return SectionPimpl == Other.SectionPimpl;
353}
354
355inline bool SectionRef::operator!=(const SectionRef &Other) const {
356  return SectionPimpl != Other.SectionPimpl;
357}
358
359inline bool SectionRef::operator<(const SectionRef &Other) const {
360  return SectionPimpl < Other.SectionPimpl;
361}
362
363inline void SectionRef::moveNext() {
364  return OwningObject->moveSectionNext(SectionPimpl);
365}
366
367inline std::error_code SectionRef::getName(StringRef &Result) const {
368  return OwningObject->getSectionName(SectionPimpl, Result);
369}
370
371inline uint64_t SectionRef::getAddress() const {
372  return OwningObject->getSectionAddress(SectionPimpl);
373}
374
375inline uint64_t SectionRef::getSize() const {
376  return OwningObject->getSectionSize(SectionPimpl);
377}
378
379inline std::error_code SectionRef::getContents(StringRef &Result) const {
380  return OwningObject->getSectionContents(SectionPimpl, Result);
381}
382
383inline uint64_t SectionRef::getAlignment() const {
384  return OwningObject->getSectionAlignment(SectionPimpl);
385}
386
387inline bool SectionRef::isCompressed() const {
388  return OwningObject->isSectionCompressed(SectionPimpl);
389}
390
391inline bool SectionRef::isText() const {
392  return OwningObject->isSectionText(SectionPimpl);
393}
394
395inline bool SectionRef::isData() const {
396  return OwningObject->isSectionData(SectionPimpl);
397}
398
399inline bool SectionRef::isBSS() const {
400  return OwningObject->isSectionBSS(SectionPimpl);
401}
402
403inline bool SectionRef::isVirtual() const {
404  return OwningObject->isSectionVirtual(SectionPimpl);
405}
406
407inline bool SectionRef::isBitcode() const {
408  return OwningObject->isSectionBitcode(SectionPimpl);
409}
410
411inline relocation_iterator SectionRef::relocation_begin() const {
412  return OwningObject->section_rel_begin(SectionPimpl);
413}
414
415inline relocation_iterator SectionRef::relocation_end() const {
416  return OwningObject->section_rel_end(SectionPimpl);
417}
418
419inline section_iterator SectionRef::getRelocatedSection() const {
420  return OwningObject->getRelocatedSection(SectionPimpl);
421}
422
423inline DataRefImpl SectionRef::getRawDataRefImpl() const {
424  return SectionPimpl;
425}
426
427inline const ObjectFile *SectionRef::getObject() const {
428  return OwningObject;
429}
430
431/// RelocationRef
432inline RelocationRef::RelocationRef(DataRefImpl RelocationP,
433                              const ObjectFile *Owner)
434  : RelocationPimpl(RelocationP)
435  , OwningObject(Owner) {}
436
437inline bool RelocationRef::operator==(const RelocationRef &Other) const {
438  return RelocationPimpl == Other.RelocationPimpl;
439}
440
441inline void RelocationRef::moveNext() {
442  return OwningObject->moveRelocationNext(RelocationPimpl);
443}
444
445inline uint64_t RelocationRef::getOffset() const {
446  return OwningObject->getRelocationOffset(RelocationPimpl);
447}
448
449inline symbol_iterator RelocationRef::getSymbol() const {
450  return OwningObject->getRelocationSymbol(RelocationPimpl);
451}
452
453inline uint64_t RelocationRef::getType() const {
454  return OwningObject->getRelocationType(RelocationPimpl);
455}
456
457inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const {
458  return OwningObject->getRelocationTypeName(RelocationPimpl, Result);
459}
460
461inline DataRefImpl RelocationRef::getRawDataRefImpl() const {
462  return RelocationPimpl;
463}
464
465inline const ObjectFile *RelocationRef::getObject() const {
466  return OwningObject;
467}
468
469
470} // end namespace object
471} // end namespace llvm
472
473#endif
474