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