1 //===- ObjectFile.h - File format independent object file -------*- 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 a file format independent ObjectFile class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_OBJECT_OBJECTFILE_H
14 #define LLVM_OBJECT_OBJECTFILE_H
15
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/Hashing.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/iterator_range.h"
20 #include "llvm/BinaryFormat/Magic.h"
21 #include "llvm/BinaryFormat/Swift.h"
22 #include "llvm/Object/Binary.h"
23 #include "llvm/Object/Error.h"
24 #include "llvm/Object/SymbolicFile.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/Compiler.h"
27 #include "llvm/Support/Error.h"
28 #include "llvm/Support/MemoryBufferRef.h"
29 #include "llvm/TargetParser/Triple.h"
30 #include <cassert>
31 #include <cstdint>
32 #include <memory>
33
34 namespace llvm {
35
36 class SubtargetFeatures;
37
38 namespace object {
39
40 class COFFObjectFile;
41 class MachOObjectFile;
42 class ObjectFile;
43 class SectionRef;
44 class SymbolRef;
45 class symbol_iterator;
46 class WasmObjectFile;
47
48 using section_iterator = content_iterator<SectionRef>;
49
50 typedef std::function<bool(const SectionRef &)> SectionFilterPredicate;
51 /// This is a value type class that represents a single relocation in the list
52 /// of relocations in the object file.
53 class RelocationRef {
54 DataRefImpl RelocationPimpl;
55 const ObjectFile *OwningObject = nullptr;
56
57 public:
58 RelocationRef() = default;
59 RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
60
61 bool operator==(const RelocationRef &Other) const;
62
63 void moveNext();
64
65 uint64_t getOffset() const;
66 symbol_iterator getSymbol() const;
67 uint64_t getType() const;
68
69 /// Get a string that represents the type of this relocation.
70 ///
71 /// This is for display purposes only.
72 void getTypeName(SmallVectorImpl<char> &Result) const;
73
74 DataRefImpl getRawDataRefImpl() const;
75 const ObjectFile *getObject() const;
76 };
77
78 using relocation_iterator = content_iterator<RelocationRef>;
79
80 /// This is a value type class that represents a single section in the list of
81 /// sections in the object file.
82 class SectionRef {
83 friend class SymbolRef;
84
85 DataRefImpl SectionPimpl;
86 const ObjectFile *OwningObject = nullptr;
87
88 public:
89 SectionRef() = default;
90 SectionRef(DataRefImpl SectionP, const ObjectFile *Owner);
91
92 bool operator==(const SectionRef &Other) const;
93 bool operator!=(const SectionRef &Other) const;
94 bool operator<(const SectionRef &Other) const;
95
96 void moveNext();
97
98 Expected<StringRef> getName() const;
99 uint64_t getAddress() const;
100 uint64_t getIndex() const;
101 uint64_t getSize() const;
102 Expected<StringRef> getContents() const;
103
104 /// Get the alignment of this section.
105 Align getAlignment() const;
106
107 bool isCompressed() const;
108 /// Whether this section contains instructions.
109 bool isText() const;
110 /// Whether this section contains data, not instructions.
111 bool isData() const;
112 /// Whether this section contains BSS uninitialized data.
113 bool isBSS() const;
114 bool isVirtual() const;
115 bool isBitcode() const;
116 bool isStripped() const;
117
118 /// Whether this section will be placed in the text segment, according to the
119 /// Berkeley size format. This is true if the section is allocatable, and
120 /// contains either code or readonly data.
121 bool isBerkeleyText() const;
122 /// Whether this section will be placed in the data segment, according to the
123 /// Berkeley size format. This is true if the section is allocatable and
124 /// contains data (e.g. PROGBITS), but is not text.
125 bool isBerkeleyData() const;
126
127 /// Whether this section is a debug section.
128 bool isDebugSection() const;
129
130 LLVM_ABI bool containsSymbol(SymbolRef S) const;
131
132 relocation_iterator relocation_begin() const;
133 relocation_iterator relocation_end() const;
relocations()134 iterator_range<relocation_iterator> relocations() const {
135 return make_range(relocation_begin(), relocation_end());
136 }
137
138 /// Returns the related section if this section contains relocations. The
139 /// returned section may or may not have applied its relocations.
140 Expected<section_iterator> getRelocatedSection() const;
141
142 DataRefImpl getRawDataRefImpl() const;
143 const ObjectFile *getObject() const;
144 };
145
146 struct SectionedAddress {
147 const static uint64_t UndefSection = UINT64_MAX;
148
149 uint64_t Address = 0;
150 uint64_t SectionIndex = UndefSection;
151 };
152
153 inline bool operator<(const SectionedAddress &LHS,
154 const SectionedAddress &RHS) {
155 return std::tie(LHS.SectionIndex, LHS.Address) <
156 std::tie(RHS.SectionIndex, RHS.Address);
157 }
158
159 inline bool operator==(const SectionedAddress &LHS,
160 const SectionedAddress &RHS) {
161 return std::tie(LHS.SectionIndex, LHS.Address) ==
162 std::tie(RHS.SectionIndex, RHS.Address);
163 }
164
165 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const SectionedAddress &Addr);
166
167 /// This is a value type class that represents a single symbol in the list of
168 /// symbols in the object file.
169 class SymbolRef : public BasicSymbolRef {
170 friend class SectionRef;
171
172 public:
173 enum Type {
174 ST_Unknown, // Type not specified
175 ST_Other,
176 ST_Data,
177 ST_Debug,
178 ST_File,
179 ST_Function,
180 };
181
182 SymbolRef() = default;
183 SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
SymbolRef(const BasicSymbolRef & B)184 SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) {
185 assert(isa<ObjectFile>(BasicSymbolRef::getObject()));
186 }
187
188 Expected<StringRef> getName() const;
189 /// Returns the symbol virtual address (i.e. address at which it will be
190 /// mapped).
191 Expected<uint64_t> getAddress() const;
192
193 /// Return the value of the symbol depending on the object this can be an
194 /// offset or a virtual address.
195 Expected<uint64_t> getValue() const;
196
197 /// Get the alignment of this symbol as the actual value (not log 2).
198 uint32_t getAlignment() const;
199 uint64_t getCommonSize() const;
200 Expected<SymbolRef::Type> getType() const;
201
202 /// Get section this symbol is defined in reference to. Result is
203 /// section_end() if it is undefined or is an absolute symbol.
204 Expected<section_iterator> getSection() const;
205
206 const ObjectFile *getObject() const;
207 };
208
209 class symbol_iterator : public basic_symbol_iterator {
210 public:
symbol_iterator(SymbolRef Sym)211 symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {}
symbol_iterator(const basic_symbol_iterator & B)212 symbol_iterator(const basic_symbol_iterator &B)
213 : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(),
214 cast<ObjectFile>(B->getObject()))) {}
215
216 const SymbolRef *operator->() const {
217 const BasicSymbolRef &P = basic_symbol_iterator::operator *();
218 return static_cast<const SymbolRef*>(&P);
219 }
220
221 const SymbolRef &operator*() const {
222 const BasicSymbolRef &P = basic_symbol_iterator::operator *();
223 return static_cast<const SymbolRef&>(P);
224 }
225 };
226
227 /// This class is the base class for all object file types. Concrete instances
228 /// of this object are created by createObjectFile, which figures out which type
229 /// to create.
230 class LLVM_ABI ObjectFile : public SymbolicFile {
231 virtual void anchor();
232
233 protected:
234 ObjectFile(unsigned int Type, MemoryBufferRef Source);
235
base()236 const uint8_t *base() const {
237 return reinterpret_cast<const uint8_t *>(Data.getBufferStart());
238 }
239
240 // These functions are for SymbolRef to call internally. The main goal of
241 // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol
242 // entry in the memory mapped object file. SymbolPimpl cannot contain any
243 // virtual functions because then it could not point into the memory mapped
244 // file.
245 //
246 // Implementations assume that the DataRefImpl is valid and has not been
247 // modified externally. It's UB otherwise.
248 friend class SymbolRef;
249
250 virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
251 Error printSymbolName(raw_ostream &OS,
252 DataRefImpl Symb) const override;
253 virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0;
254 virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0;
255 virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
256 virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0;
257 virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0;
258 virtual Expected<section_iterator>
259 getSymbolSection(DataRefImpl Symb) const = 0;
260
261 // Same as above for SectionRef.
262 friend class SectionRef;
263
264 virtual void moveSectionNext(DataRefImpl &Sec) const = 0;
265 virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const = 0;
266 virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0;
267 virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0;
268 virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0;
269 virtual Expected<ArrayRef<uint8_t>>
270 getSectionContents(DataRefImpl Sec) const = 0;
271 virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
272 virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
273 virtual bool isSectionText(DataRefImpl Sec) const = 0;
274 virtual bool isSectionData(DataRefImpl Sec) const = 0;
275 virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
276 // A section is 'virtual' if its contents aren't present in the object image.
277 virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
278 virtual bool isSectionBitcode(DataRefImpl Sec) const;
279 virtual bool isSectionStripped(DataRefImpl Sec) const;
280 virtual bool isBerkeleyText(DataRefImpl Sec) const;
281 virtual bool isBerkeleyData(DataRefImpl Sec) const;
282 virtual bool isDebugSection(DataRefImpl Sec) const;
283 virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
284 virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
285 virtual Expected<section_iterator> getRelocatedSection(DataRefImpl Sec) const;
286
287 // Same as above for RelocationRef.
288 friend class RelocationRef;
289 virtual void moveRelocationNext(DataRefImpl &Rel) const = 0;
290 virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0;
291 virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
292 virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0;
293 virtual void getRelocationTypeName(DataRefImpl Rel,
294 SmallVectorImpl<char> &Result) const = 0;
295
296 virtual llvm::binaryformat::Swift5ReflectionSectionKind
mapReflectionSectionNameToEnumValue(StringRef SectionName)297 mapReflectionSectionNameToEnumValue(StringRef SectionName) const {
298 return llvm::binaryformat::Swift5ReflectionSectionKind::unknown;
299 };
300
301 Expected<uint64_t> getSymbolValue(DataRefImpl Symb) const;
302
303 public:
304 ObjectFile() = delete;
305 ObjectFile(const ObjectFile &other) = delete;
306 ObjectFile &operator=(const ObjectFile &other) = delete;
307
getCommonSymbolSize(DataRefImpl Symb)308 uint64_t getCommonSymbolSize(DataRefImpl Symb) const {
309 Expected<uint32_t> SymbolFlagsOrErr = getSymbolFlags(Symb);
310 if (!SymbolFlagsOrErr)
311 // TODO: Actually report errors helpfully.
312 report_fatal_error(SymbolFlagsOrErr.takeError());
313 assert(*SymbolFlagsOrErr & SymbolRef::SF_Common);
314 return getCommonSymbolSizeImpl(Symb);
315 }
316
dynamic_relocation_sections()317 virtual std::vector<SectionRef> dynamic_relocation_sections() const {
318 return std::vector<SectionRef>();
319 }
320
321 using symbol_iterator_range = iterator_range<symbol_iterator>;
symbols()322 symbol_iterator_range symbols() const {
323 return symbol_iterator_range(symbol_begin(), symbol_end());
324 }
325
326 virtual section_iterator section_begin() const = 0;
327 virtual section_iterator section_end() const = 0;
328
329 using section_iterator_range = iterator_range<section_iterator>;
sections()330 section_iterator_range sections() const {
331 return section_iterator_range(section_begin(), section_end());
332 }
333
334 virtual bool hasDebugInfo() const;
335
336 /// The number of bytes used to represent an address in this object
337 /// file format.
338 virtual uint8_t getBytesInAddress() const = 0;
339
340 virtual StringRef getFileFormatName() const = 0;
341 virtual Triple::ArchType getArch() const = 0;
getOS()342 virtual Triple::OSType getOS() const { return Triple::UnknownOS; }
343 virtual Expected<SubtargetFeatures> getFeatures() const = 0;
tryGetCPUName()344 virtual std::optional<StringRef> tryGetCPUName() const {
345 return std::nullopt;
346 };
setARMSubArch(Triple & TheTriple)347 virtual void setARMSubArch(Triple &TheTriple) const { }
getStartAddress()348 virtual Expected<uint64_t> getStartAddress() const {
349 return errorCodeToError(object_error::parse_failed);
350 };
351
352 /// Create a triple from the data in this object file.
353 Triple makeTriple() const;
354
355 /// Maps a debug section name to a standard DWARF section name.
mapDebugSectionName(StringRef Name)356 virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; }
357
358 /// True if this is a relocatable object (.o/.obj).
359 virtual bool isRelocatableObject() const = 0;
360
361 /// True if the reflection section can be stripped by the linker.
362 bool isReflectionSectionStrippable(
363 llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)
364 const;
365
366 /// @returns Pointer to ObjectFile subclass to handle this type of object.
367 /// @param ObjectPath The path to the object file. ObjectPath.isObject must
368 /// return true.
369 /// Create ObjectFile from path.
370 static Expected<OwningBinary<ObjectFile>>
371 createObjectFile(StringRef ObjectPath);
372
373 static Expected<std::unique_ptr<ObjectFile>>
374 createObjectFile(MemoryBufferRef Object, llvm::file_magic Type,
375 bool InitContent = true);
376 static Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object)377 createObjectFile(MemoryBufferRef Object) {
378 return createObjectFile(Object, llvm::file_magic::unknown);
379 }
380
classof(const Binary * v)381 static bool classof(const Binary *v) {
382 return v->isObject();
383 }
384
385 static Expected<std::unique_ptr<COFFObjectFile>>
386 createCOFFObjectFile(MemoryBufferRef Object);
387
388 static Expected<std::unique_ptr<ObjectFile>>
389 createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
390
391 static Expected<std::unique_ptr<ObjectFile>>
392 createELFObjectFile(MemoryBufferRef Object, bool InitContent = true);
393
394 static Expected<std::unique_ptr<MachOObjectFile>>
395 createMachOObjectFile(MemoryBufferRef Object, uint32_t UniversalCputype = 0,
396 uint32_t UniversalIndex = 0,
397 size_t MachOFilesetEntryOffset = 0);
398
399 static Expected<std::unique_ptr<ObjectFile>>
400 createGOFFObjectFile(MemoryBufferRef Object);
401
402 static Expected<std::unique_ptr<WasmObjectFile>>
403 createWasmObjectFile(MemoryBufferRef Object);
404 };
405
406 /// A filtered iterator for SectionRefs that skips sections based on some given
407 /// predicate.
408 class SectionFilterIterator {
409 public:
SectionFilterIterator(SectionFilterPredicate Pred,const section_iterator & Begin,const section_iterator & End)410 SectionFilterIterator(SectionFilterPredicate Pred,
411 const section_iterator &Begin,
412 const section_iterator &End)
413 : Predicate(std::move(Pred)), Iterator(Begin), End(End) {
414 scanPredicate();
415 }
416 const SectionRef &operator*() const { return *Iterator; }
417 SectionFilterIterator &operator++() {
418 ++Iterator;
419 scanPredicate();
420 return *this;
421 }
422 bool operator!=(const SectionFilterIterator &Other) const {
423 return Iterator != Other.Iterator;
424 }
425
426 private:
scanPredicate()427 void scanPredicate() {
428 while (Iterator != End && !Predicate(*Iterator)) {
429 ++Iterator;
430 }
431 }
432 SectionFilterPredicate Predicate;
433 section_iterator Iterator;
434 section_iterator End;
435 };
436
437 /// Creates an iterator range of SectionFilterIterators for a given Object and
438 /// predicate.
439 class SectionFilter {
440 public:
SectionFilter(SectionFilterPredicate Pred,const ObjectFile & Obj)441 SectionFilter(SectionFilterPredicate Pred, const ObjectFile &Obj)
442 : Predicate(std::move(Pred)), Object(Obj) {}
begin()443 SectionFilterIterator begin() {
444 return SectionFilterIterator(Predicate, Object.section_begin(),
445 Object.section_end());
446 }
end()447 SectionFilterIterator end() {
448 return SectionFilterIterator(Predicate, Object.section_end(),
449 Object.section_end());
450 }
451
452 private:
453 SectionFilterPredicate Predicate;
454 const ObjectFile &Object;
455 };
456
457 // Inline function definitions.
SymbolRef(DataRefImpl SymbolP,const ObjectFile * Owner)458 inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner)
459 : BasicSymbolRef(SymbolP, Owner) {}
460
getName()461 inline Expected<StringRef> SymbolRef::getName() const {
462 return getObject()->getSymbolName(getRawDataRefImpl());
463 }
464
getAddress()465 inline Expected<uint64_t> SymbolRef::getAddress() const {
466 return getObject()->getSymbolAddress(getRawDataRefImpl());
467 }
468
getValue()469 inline Expected<uint64_t> SymbolRef::getValue() const {
470 return getObject()->getSymbolValue(getRawDataRefImpl());
471 }
472
getAlignment()473 inline uint32_t SymbolRef::getAlignment() const {
474 return getObject()->getSymbolAlignment(getRawDataRefImpl());
475 }
476
getCommonSize()477 inline uint64_t SymbolRef::getCommonSize() const {
478 return getObject()->getCommonSymbolSize(getRawDataRefImpl());
479 }
480
getSection()481 inline Expected<section_iterator> SymbolRef::getSection() const {
482 return getObject()->getSymbolSection(getRawDataRefImpl());
483 }
484
getType()485 inline Expected<SymbolRef::Type> SymbolRef::getType() const {
486 return getObject()->getSymbolType(getRawDataRefImpl());
487 }
488
getObject()489 inline const ObjectFile *SymbolRef::getObject() const {
490 const SymbolicFile *O = BasicSymbolRef::getObject();
491 return cast<ObjectFile>(O);
492 }
493
494 /// SectionRef
SectionRef(DataRefImpl SectionP,const ObjectFile * Owner)495 inline SectionRef::SectionRef(DataRefImpl SectionP,
496 const ObjectFile *Owner)
497 : SectionPimpl(SectionP)
498 , OwningObject(Owner) {}
499
500 inline bool SectionRef::operator==(const SectionRef &Other) const {
501 return OwningObject == Other.OwningObject &&
502 SectionPimpl == Other.SectionPimpl;
503 }
504
505 inline bool SectionRef::operator!=(const SectionRef &Other) const {
506 return !(*this == Other);
507 }
508
509 inline bool SectionRef::operator<(const SectionRef &Other) const {
510 assert(OwningObject == Other.OwningObject);
511 return SectionPimpl < Other.SectionPimpl;
512 }
513
moveNext()514 inline void SectionRef::moveNext() {
515 return OwningObject->moveSectionNext(SectionPimpl);
516 }
517
getName()518 inline Expected<StringRef> SectionRef::getName() const {
519 return OwningObject->getSectionName(SectionPimpl);
520 }
521
getAddress()522 inline uint64_t SectionRef::getAddress() const {
523 return OwningObject->getSectionAddress(SectionPimpl);
524 }
525
getIndex()526 inline uint64_t SectionRef::getIndex() const {
527 return OwningObject->getSectionIndex(SectionPimpl);
528 }
529
getSize()530 inline uint64_t SectionRef::getSize() const {
531 return OwningObject->getSectionSize(SectionPimpl);
532 }
533
getContents()534 inline Expected<StringRef> SectionRef::getContents() const {
535 Expected<ArrayRef<uint8_t>> Res =
536 OwningObject->getSectionContents(SectionPimpl);
537 if (!Res)
538 return Res.takeError();
539 return StringRef(reinterpret_cast<const char *>(Res->data()), Res->size());
540 }
541
getAlignment()542 inline Align SectionRef::getAlignment() const {
543 return MaybeAlign(OwningObject->getSectionAlignment(SectionPimpl))
544 .valueOrOne();
545 }
546
isCompressed()547 inline bool SectionRef::isCompressed() const {
548 return OwningObject->isSectionCompressed(SectionPimpl);
549 }
550
isText()551 inline bool SectionRef::isText() const {
552 return OwningObject->isSectionText(SectionPimpl);
553 }
554
isData()555 inline bool SectionRef::isData() const {
556 return OwningObject->isSectionData(SectionPimpl);
557 }
558
isBSS()559 inline bool SectionRef::isBSS() const {
560 return OwningObject->isSectionBSS(SectionPimpl);
561 }
562
isVirtual()563 inline bool SectionRef::isVirtual() const {
564 return OwningObject->isSectionVirtual(SectionPimpl);
565 }
566
isBitcode()567 inline bool SectionRef::isBitcode() const {
568 return OwningObject->isSectionBitcode(SectionPimpl);
569 }
570
isStripped()571 inline bool SectionRef::isStripped() const {
572 return OwningObject->isSectionStripped(SectionPimpl);
573 }
574
isBerkeleyText()575 inline bool SectionRef::isBerkeleyText() const {
576 return OwningObject->isBerkeleyText(SectionPimpl);
577 }
578
isBerkeleyData()579 inline bool SectionRef::isBerkeleyData() const {
580 return OwningObject->isBerkeleyData(SectionPimpl);
581 }
582
isDebugSection()583 inline bool SectionRef::isDebugSection() const {
584 return OwningObject->isDebugSection(SectionPimpl);
585 }
586
relocation_begin()587 inline relocation_iterator SectionRef::relocation_begin() const {
588 return OwningObject->section_rel_begin(SectionPimpl);
589 }
590
relocation_end()591 inline relocation_iterator SectionRef::relocation_end() const {
592 return OwningObject->section_rel_end(SectionPimpl);
593 }
594
getRelocatedSection()595 inline Expected<section_iterator> SectionRef::getRelocatedSection() const {
596 return OwningObject->getRelocatedSection(SectionPimpl);
597 }
598
getRawDataRefImpl()599 inline DataRefImpl SectionRef::getRawDataRefImpl() const {
600 return SectionPimpl;
601 }
602
getObject()603 inline const ObjectFile *SectionRef::getObject() const {
604 return OwningObject;
605 }
606
607 /// RelocationRef
RelocationRef(DataRefImpl RelocationP,const ObjectFile * Owner)608 inline RelocationRef::RelocationRef(DataRefImpl RelocationP,
609 const ObjectFile *Owner)
610 : RelocationPimpl(RelocationP)
611 , OwningObject(Owner) {}
612
613 inline bool RelocationRef::operator==(const RelocationRef &Other) const {
614 return RelocationPimpl == Other.RelocationPimpl;
615 }
616
moveNext()617 inline void RelocationRef::moveNext() {
618 return OwningObject->moveRelocationNext(RelocationPimpl);
619 }
620
getOffset()621 inline uint64_t RelocationRef::getOffset() const {
622 return OwningObject->getRelocationOffset(RelocationPimpl);
623 }
624
getSymbol()625 inline symbol_iterator RelocationRef::getSymbol() const {
626 return OwningObject->getRelocationSymbol(RelocationPimpl);
627 }
628
getType()629 inline uint64_t RelocationRef::getType() const {
630 return OwningObject->getRelocationType(RelocationPimpl);
631 }
632
getTypeName(SmallVectorImpl<char> & Result)633 inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const {
634 return OwningObject->getRelocationTypeName(RelocationPimpl, Result);
635 }
636
getRawDataRefImpl()637 inline DataRefImpl RelocationRef::getRawDataRefImpl() const {
638 return RelocationPimpl;
639 }
640
getObject()641 inline const ObjectFile *RelocationRef::getObject() const {
642 return OwningObject;
643 }
644
645 } // end namespace object
646
647 template <> struct DenseMapInfo<object::SectionRef> {
648 static bool isEqual(const object::SectionRef &A,
649 const object::SectionRef &B) {
650 return A == B;
651 }
652 static object::SectionRef getEmptyKey() {
653 return object::SectionRef({}, nullptr);
654 }
655 static object::SectionRef getTombstoneKey() {
656 object::DataRefImpl TS;
657 TS.p = (uintptr_t)-1;
658 return object::SectionRef(TS, nullptr);
659 }
660 static unsigned getHashValue(const object::SectionRef &Sec) {
661 object::DataRefImpl Raw = Sec.getRawDataRefImpl();
662 return hash_combine(Raw.p, Raw.d.a, Raw.d.b);
663 }
664 };
665
666 } // end namespace llvm
667
668 #endif // LLVM_OBJECT_OBJECTFILE_H
669