• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //===- COFFObjectFile.cpp - COFF object file implementation -----*- 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 COFFObjectFile class.
11  //
12  //===----------------------------------------------------------------------===//
13  
14  #include "llvm/Object/COFF.h"
15  #include "llvm/ADT/ArrayRef.h"
16  #include "llvm/ADT/StringSwitch.h"
17  #include "llvm/ADT/Triple.h"
18  #include "llvm/ADT/iterator_range.h"
19  #include "llvm/Support/COFF.h"
20  #include "llvm/Support/Debug.h"
21  #include "llvm/Support/raw_ostream.h"
22  #include <cctype>
23  #include <limits>
24  
25  using namespace llvm;
26  using namespace object;
27  
28  using support::ulittle16_t;
29  using support::ulittle32_t;
30  using support::ulittle64_t;
31  using support::little16_t;
32  
33  // Returns false if size is greater than the buffer size. And sets ec.
checkSize(MemoryBufferRef M,std::error_code & EC,uint64_t Size)34  static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
35    if (M.getBufferSize() < Size) {
36      EC = object_error::unexpected_eof;
37      return false;
38    }
39    return true;
40  }
41  
checkOffset(MemoryBufferRef M,uintptr_t Addr,const uint64_t Size)42  static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
43                                     const uint64_t Size) {
44    if (Addr + Size < Addr || Addr + Size < Size ||
45        Addr + Size > uintptr_t(M.getBufferEnd()) ||
46        Addr < uintptr_t(M.getBufferStart())) {
47      return object_error::unexpected_eof;
48    }
49    return std::error_code();
50  }
51  
52  // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
53  // Returns unexpected_eof if error.
54  template <typename T>
getObject(const T * & Obj,MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (T))55  static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
56                                   const void *Ptr,
57                                   const uint64_t Size = sizeof(T)) {
58    uintptr_t Addr = uintptr_t(Ptr);
59    if (std::error_code EC = checkOffset(M, Addr, Size))
60      return EC;
61    Obj = reinterpret_cast<const T *>(Addr);
62    return std::error_code();
63  }
64  
65  // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
66  // prefixed slashes.
decodeBase64StringEntry(StringRef Str,uint32_t & Result)67  static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
68    assert(Str.size() <= 6 && "String too long, possible overflow.");
69    if (Str.size() > 6)
70      return true;
71  
72    uint64_t Value = 0;
73    while (!Str.empty()) {
74      unsigned CharVal;
75      if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
76        CharVal = Str[0] - 'A';
77      else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
78        CharVal = Str[0] - 'a' + 26;
79      else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
80        CharVal = Str[0] - '0' + 52;
81      else if (Str[0] == '+') // 62
82        CharVal = 62;
83      else if (Str[0] == '/') // 63
84        CharVal = 63;
85      else
86        return true;
87  
88      Value = (Value * 64) + CharVal;
89      Str = Str.substr(1);
90    }
91  
92    if (Value > std::numeric_limits<uint32_t>::max())
93      return true;
94  
95    Result = static_cast<uint32_t>(Value);
96    return false;
97  }
98  
99  template <typename coff_symbol_type>
toSymb(DataRefImpl Ref) const100  const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
101    const coff_symbol_type *Addr =
102        reinterpret_cast<const coff_symbol_type *>(Ref.p);
103  
104    assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
105  #ifndef NDEBUG
106    // Verify that the symbol points to a valid entry in the symbol table.
107    uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
108  
109    assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
110           "Symbol did not point to the beginning of a symbol");
111  #endif
112  
113    return Addr;
114  }
115  
toSec(DataRefImpl Ref) const116  const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
117    const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
118  
119  # ifndef NDEBUG
120    // Verify that the section points to a valid entry in the section table.
121    if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
122      report_fatal_error("Section was outside of section table.");
123  
124    uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
125    assert(Offset % sizeof(coff_section) == 0 &&
126           "Section did not point to the beginning of a section");
127  # endif
128  
129    return Addr;
130  }
131  
moveSymbolNext(DataRefImpl & Ref) const132  void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
133    auto End = reinterpret_cast<uintptr_t>(StringTable);
134    if (SymbolTable16) {
135      const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
136      Symb += 1 + Symb->NumberOfAuxSymbols;
137      Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
138    } else if (SymbolTable32) {
139      const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
140      Symb += 1 + Symb->NumberOfAuxSymbols;
141      Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
142    } else {
143      llvm_unreachable("no symbol table pointer!");
144    }
145  }
146  
getSymbolName(DataRefImpl Ref) const147  Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
148    COFFSymbolRef Symb = getCOFFSymbol(Ref);
149    StringRef Result;
150    std::error_code EC = getSymbolName(Symb, Result);
151    if (EC)
152      return errorCodeToError(EC);
153    return Result;
154  }
155  
getSymbolValueImpl(DataRefImpl Ref) const156  uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
157    return getCOFFSymbol(Ref).getValue();
158  }
159  
getSymbolAddress(DataRefImpl Ref) const160  Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
161    uint64_t Result = getSymbolValue(Ref);
162    COFFSymbolRef Symb = getCOFFSymbol(Ref);
163    int32_t SectionNumber = Symb.getSectionNumber();
164  
165    if (Symb.isAnyUndefined() || Symb.isCommon() ||
166        COFF::isReservedSectionNumber(SectionNumber))
167      return Result;
168  
169    const coff_section *Section = nullptr;
170    if (std::error_code EC = getSection(SectionNumber, Section))
171      return errorCodeToError(EC);
172    Result += Section->VirtualAddress;
173  
174    // The section VirtualAddress does not include ImageBase, and we want to
175    // return virtual addresses.
176    Result += getImageBase();
177  
178    return Result;
179  }
180  
getSymbolType(DataRefImpl Ref) const181  Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
182    COFFSymbolRef Symb = getCOFFSymbol(Ref);
183    int32_t SectionNumber = Symb.getSectionNumber();
184  
185    if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
186      return SymbolRef::ST_Function;
187    if (Symb.isAnyUndefined())
188      return SymbolRef::ST_Unknown;
189    if (Symb.isCommon())
190      return SymbolRef::ST_Data;
191    if (Symb.isFileRecord())
192      return SymbolRef::ST_File;
193  
194    // TODO: perhaps we need a new symbol type ST_Section.
195    if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
196      return SymbolRef::ST_Debug;
197  
198    if (!COFF::isReservedSectionNumber(SectionNumber))
199      return SymbolRef::ST_Data;
200  
201    return SymbolRef::ST_Other;
202  }
203  
getSymbolFlags(DataRefImpl Ref) const204  uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
205    COFFSymbolRef Symb = getCOFFSymbol(Ref);
206    uint32_t Result = SymbolRef::SF_None;
207  
208    if (Symb.isExternal() || Symb.isWeakExternal())
209      Result |= SymbolRef::SF_Global;
210  
211    if (Symb.isWeakExternal())
212      Result |= SymbolRef::SF_Weak;
213  
214    if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
215      Result |= SymbolRef::SF_Absolute;
216  
217    if (Symb.isFileRecord())
218      Result |= SymbolRef::SF_FormatSpecific;
219  
220    if (Symb.isSectionDefinition())
221      Result |= SymbolRef::SF_FormatSpecific;
222  
223    if (Symb.isCommon())
224      Result |= SymbolRef::SF_Common;
225  
226    if (Symb.isAnyUndefined())
227      Result |= SymbolRef::SF_Undefined;
228  
229    return Result;
230  }
231  
getCommonSymbolSizeImpl(DataRefImpl Ref) const232  uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
233    COFFSymbolRef Symb = getCOFFSymbol(Ref);
234    return Symb.getValue();
235  }
236  
237  Expected<section_iterator>
getSymbolSection(DataRefImpl Ref) const238  COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
239    COFFSymbolRef Symb = getCOFFSymbol(Ref);
240    if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
241      return section_end();
242    const coff_section *Sec = nullptr;
243    if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
244      return errorCodeToError(EC);
245    DataRefImpl Ret;
246    Ret.p = reinterpret_cast<uintptr_t>(Sec);
247    return section_iterator(SectionRef(Ret, this));
248  }
249  
getSymbolSectionID(SymbolRef Sym) const250  unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
251    COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
252    return Symb.getSectionNumber();
253  }
254  
moveSectionNext(DataRefImpl & Ref) const255  void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
256    const coff_section *Sec = toSec(Ref);
257    Sec += 1;
258    Ref.p = reinterpret_cast<uintptr_t>(Sec);
259  }
260  
getSectionName(DataRefImpl Ref,StringRef & Result) const261  std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
262                                                 StringRef &Result) const {
263    const coff_section *Sec = toSec(Ref);
264    return getSectionName(Sec, Result);
265  }
266  
getSectionAddress(DataRefImpl Ref) const267  uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
268    const coff_section *Sec = toSec(Ref);
269    uint64_t Result = Sec->VirtualAddress;
270  
271    // The section VirtualAddress does not include ImageBase, and we want to
272    // return virtual addresses.
273    Result += getImageBase();
274    return Result;
275  }
276  
getSectionSize(DataRefImpl Ref) const277  uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
278    return getSectionSize(toSec(Ref));
279  }
280  
getSectionContents(DataRefImpl Ref,StringRef & Result) const281  std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
282                                                     StringRef &Result) const {
283    const coff_section *Sec = toSec(Ref);
284    ArrayRef<uint8_t> Res;
285    std::error_code EC = getSectionContents(Sec, Res);
286    Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
287    return EC;
288  }
289  
getSectionAlignment(DataRefImpl Ref) const290  uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
291    const coff_section *Sec = toSec(Ref);
292    return Sec->getAlignment();
293  }
294  
isSectionCompressed(DataRefImpl Sec) const295  bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
296    return false;
297  }
298  
isSectionText(DataRefImpl Ref) const299  bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
300    const coff_section *Sec = toSec(Ref);
301    return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
302  }
303  
isSectionData(DataRefImpl Ref) const304  bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
305    const coff_section *Sec = toSec(Ref);
306    return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
307  }
308  
isSectionBSS(DataRefImpl Ref) const309  bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
310    const coff_section *Sec = toSec(Ref);
311    const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
312                              COFF::IMAGE_SCN_MEM_READ |
313                              COFF::IMAGE_SCN_MEM_WRITE;
314    return (Sec->Characteristics & BssFlags) == BssFlags;
315  }
316  
getSectionID(SectionRef Sec) const317  unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
318    uintptr_t Offset =
319        uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
320    assert((Offset % sizeof(coff_section)) == 0);
321    return (Offset / sizeof(coff_section)) + 1;
322  }
323  
isSectionVirtual(DataRefImpl Ref) const324  bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
325    const coff_section *Sec = toSec(Ref);
326    // In COFF, a virtual section won't have any in-file
327    // content, so the file pointer to the content will be zero.
328    return Sec->PointerToRawData == 0;
329  }
330  
getNumberOfRelocations(const coff_section * Sec,MemoryBufferRef M,const uint8_t * base)331  static uint32_t getNumberOfRelocations(const coff_section *Sec,
332                                         MemoryBufferRef M, const uint8_t *base) {
333    // The field for the number of relocations in COFF section table is only
334    // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
335    // NumberOfRelocations field, and the actual relocation count is stored in the
336    // VirtualAddress field in the first relocation entry.
337    if (Sec->hasExtendedRelocations()) {
338      const coff_relocation *FirstReloc;
339      if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
340          base + Sec->PointerToRelocations)))
341        return 0;
342      // -1 to exclude this first relocation entry.
343      return FirstReloc->VirtualAddress - 1;
344    }
345    return Sec->NumberOfRelocations;
346  }
347  
348  static const coff_relocation *
getFirstReloc(const coff_section * Sec,MemoryBufferRef M,const uint8_t * Base)349  getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
350    uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
351    if (!NumRelocs)
352      return nullptr;
353    auto begin = reinterpret_cast<const coff_relocation *>(
354        Base + Sec->PointerToRelocations);
355    if (Sec->hasExtendedRelocations()) {
356      // Skip the first relocation entry repurposed to store the number of
357      // relocations.
358      begin++;
359    }
360    if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
361      return nullptr;
362    return begin;
363  }
364  
section_rel_begin(DataRefImpl Ref) const365  relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
366    const coff_section *Sec = toSec(Ref);
367    const coff_relocation *begin = getFirstReloc(Sec, Data, base());
368    if (begin && Sec->VirtualAddress != 0)
369      report_fatal_error("Sections with relocations should have an address of 0");
370    DataRefImpl Ret;
371    Ret.p = reinterpret_cast<uintptr_t>(begin);
372    return relocation_iterator(RelocationRef(Ret, this));
373  }
374  
section_rel_end(DataRefImpl Ref) const375  relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
376    const coff_section *Sec = toSec(Ref);
377    const coff_relocation *I = getFirstReloc(Sec, Data, base());
378    if (I)
379      I += getNumberOfRelocations(Sec, Data, base());
380    DataRefImpl Ret;
381    Ret.p = reinterpret_cast<uintptr_t>(I);
382    return relocation_iterator(RelocationRef(Ret, this));
383  }
384  
385  // Initialize the pointer to the symbol table.
initSymbolTablePtr()386  std::error_code COFFObjectFile::initSymbolTablePtr() {
387    if (COFFHeader)
388      if (std::error_code EC = getObject(
389              SymbolTable16, Data, base() + getPointerToSymbolTable(),
390              (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
391        return EC;
392  
393    if (COFFBigObjHeader)
394      if (std::error_code EC = getObject(
395              SymbolTable32, Data, base() + getPointerToSymbolTable(),
396              (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
397        return EC;
398  
399    // Find string table. The first four byte of the string table contains the
400    // total size of the string table, including the size field itself. If the
401    // string table is empty, the value of the first four byte would be 4.
402    uint32_t StringTableOffset = getPointerToSymbolTable() +
403                                 getNumberOfSymbols() * getSymbolTableEntrySize();
404    const uint8_t *StringTableAddr = base() + StringTableOffset;
405    const ulittle32_t *StringTableSizePtr;
406    if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
407      return EC;
408    StringTableSize = *StringTableSizePtr;
409    if (std::error_code EC =
410            getObject(StringTable, Data, StringTableAddr, StringTableSize))
411      return EC;
412  
413    // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
414    // tools like cvtres write a size of 0 for an empty table instead of 4.
415    if (StringTableSize < 4)
416        StringTableSize = 4;
417  
418    // Check that the string table is null terminated if has any in it.
419    if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
420      return  object_error::parse_failed;
421    return std::error_code();
422  }
423  
getImageBase() const424  uint64_t COFFObjectFile::getImageBase() const {
425    if (PE32Header)
426      return PE32Header->ImageBase;
427    else if (PE32PlusHeader)
428      return PE32PlusHeader->ImageBase;
429    // This actually comes up in practice.
430    return 0;
431  }
432  
433  // Returns the file offset for the given VA.
getVaPtr(uint64_t Addr,uintptr_t & Res) const434  std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
435    uint64_t ImageBase = getImageBase();
436    uint64_t Rva = Addr - ImageBase;
437    assert(Rva <= UINT32_MAX);
438    return getRvaPtr((uint32_t)Rva, Res);
439  }
440  
441  // Returns the file offset for the given RVA.
getRvaPtr(uint32_t Addr,uintptr_t & Res) const442  std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
443    for (const SectionRef &S : sections()) {
444      const coff_section *Section = getCOFFSection(S);
445      uint32_t SectionStart = Section->VirtualAddress;
446      uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
447      if (SectionStart <= Addr && Addr < SectionEnd) {
448        uint32_t Offset = Addr - SectionStart;
449        Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
450        return std::error_code();
451      }
452    }
453    return object_error::parse_failed;
454  }
455  
456  std::error_code
getRvaAndSizeAsBytes(uint32_t RVA,uint32_t Size,ArrayRef<uint8_t> & Contents) const457  COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
458                                       ArrayRef<uint8_t> &Contents) const {
459    for (const SectionRef &S : sections()) {
460      const coff_section *Section = getCOFFSection(S);
461      uint32_t SectionStart = Section->VirtualAddress;
462      // Check if this RVA is within the section bounds. Be careful about integer
463      // overflow.
464      uint32_t OffsetIntoSection = RVA - SectionStart;
465      if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
466          Size <= Section->VirtualSize - OffsetIntoSection) {
467        uintptr_t Begin =
468            uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
469        Contents =
470            ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
471        return std::error_code();
472      }
473    }
474    return object_error::parse_failed;
475  }
476  
477  // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
478  // table entry.
getHintName(uint32_t Rva,uint16_t & Hint,StringRef & Name) const479  std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
480                                              StringRef &Name) const {
481    uintptr_t IntPtr = 0;
482    if (std::error_code EC = getRvaPtr(Rva, IntPtr))
483      return EC;
484    const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
485    Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
486    Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
487    return std::error_code();
488  }
489  
getDebugPDBInfo(const debug_directory * DebugDir,const debug_pdb_info * & PDBInfo,StringRef & PDBFileName) const490  std::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
491                                                  const debug_pdb_info *&PDBInfo,
492                                                  StringRef &PDBFileName) const {
493    ArrayRef<uint8_t> InfoBytes;
494    if (std::error_code EC = getRvaAndSizeAsBytes(
495            DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
496      return EC;
497    if (InfoBytes.size() < sizeof(debug_pdb_info) + 1)
498      return object_error::parse_failed;
499    PDBInfo = reinterpret_cast<const debug_pdb_info *>(InfoBytes.data());
500    InfoBytes = InfoBytes.drop_front(sizeof(debug_pdb_info));
501    PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
502                            InfoBytes.size());
503    // Truncate the name at the first null byte. Ignore any padding.
504    PDBFileName = PDBFileName.split('\0').first;
505    return std::error_code();
506  }
507  
getDebugPDBInfo(const debug_pdb_info * & PDBInfo,StringRef & PDBFileName) const508  std::error_code COFFObjectFile::getDebugPDBInfo(const debug_pdb_info *&PDBInfo,
509                                                  StringRef &PDBFileName) const {
510    for (const debug_directory &D : debug_directories())
511      if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
512        return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
513    // If we get here, there is no PDB info to return.
514    PDBInfo = nullptr;
515    PDBFileName = StringRef();
516    return std::error_code();
517  }
518  
519  // Find the import table.
initImportTablePtr()520  std::error_code COFFObjectFile::initImportTablePtr() {
521    // First, we get the RVA of the import table. If the file lacks a pointer to
522    // the import table, do nothing.
523    const data_directory *DataEntry;
524    if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
525      return std::error_code();
526  
527    // Do nothing if the pointer to import table is NULL.
528    if (DataEntry->RelativeVirtualAddress == 0)
529      return std::error_code();
530  
531    uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
532  
533    // Find the section that contains the RVA. This is needed because the RVA is
534    // the import table's memory address which is different from its file offset.
535    uintptr_t IntPtr = 0;
536    if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
537      return EC;
538    if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
539      return EC;
540    ImportDirectory = reinterpret_cast<
541        const import_directory_table_entry *>(IntPtr);
542    return std::error_code();
543  }
544  
545  // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
initDelayImportTablePtr()546  std::error_code COFFObjectFile::initDelayImportTablePtr() {
547    const data_directory *DataEntry;
548    if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
549      return std::error_code();
550    if (DataEntry->RelativeVirtualAddress == 0)
551      return std::error_code();
552  
553    uint32_t RVA = DataEntry->RelativeVirtualAddress;
554    NumberOfDelayImportDirectory = DataEntry->Size /
555        sizeof(delay_import_directory_table_entry) - 1;
556  
557    uintptr_t IntPtr = 0;
558    if (std::error_code EC = getRvaPtr(RVA, IntPtr))
559      return EC;
560    DelayImportDirectory = reinterpret_cast<
561        const delay_import_directory_table_entry *>(IntPtr);
562    return std::error_code();
563  }
564  
565  // Find the export table.
initExportTablePtr()566  std::error_code COFFObjectFile::initExportTablePtr() {
567    // First, we get the RVA of the export table. If the file lacks a pointer to
568    // the export table, do nothing.
569    const data_directory *DataEntry;
570    if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
571      return std::error_code();
572  
573    // Do nothing if the pointer to export table is NULL.
574    if (DataEntry->RelativeVirtualAddress == 0)
575      return std::error_code();
576  
577    uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
578    uintptr_t IntPtr = 0;
579    if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
580      return EC;
581    ExportDirectory =
582        reinterpret_cast<const export_directory_table_entry *>(IntPtr);
583    return std::error_code();
584  }
585  
initBaseRelocPtr()586  std::error_code COFFObjectFile::initBaseRelocPtr() {
587    const data_directory *DataEntry;
588    if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
589      return std::error_code();
590    if (DataEntry->RelativeVirtualAddress == 0)
591      return std::error_code();
592  
593    uintptr_t IntPtr = 0;
594    if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
595      return EC;
596    BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
597        IntPtr);
598    BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
599        IntPtr + DataEntry->Size);
600    return std::error_code();
601  }
602  
initDebugDirectoryPtr()603  std::error_code COFFObjectFile::initDebugDirectoryPtr() {
604    // Get the RVA of the debug directory. Do nothing if it does not exist.
605    const data_directory *DataEntry;
606    if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
607      return std::error_code();
608  
609    // Do nothing if the RVA is NULL.
610    if (DataEntry->RelativeVirtualAddress == 0)
611      return std::error_code();
612  
613    // Check that the size is a multiple of the entry size.
614    if (DataEntry->Size % sizeof(debug_directory) != 0)
615      return object_error::parse_failed;
616  
617    uintptr_t IntPtr = 0;
618    if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
619      return EC;
620    DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
621    if (std::error_code EC = getRvaPtr(
622            DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
623      return EC;
624    DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
625    return std::error_code();
626  }
627  
COFFObjectFile(MemoryBufferRef Object,std::error_code & EC)628  COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
629      : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
630        COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
631        DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
632        SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
633        ImportDirectory(nullptr),
634        DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
635        ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
636        DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
637    // Check that we at least have enough room for a header.
638    if (!checkSize(Data, EC, sizeof(coff_file_header)))
639      return;
640  
641    // The current location in the file where we are looking at.
642    uint64_t CurPtr = 0;
643  
644    // PE header is optional and is present only in executables. If it exists,
645    // it is placed right after COFF header.
646    bool HasPEHeader = false;
647  
648    // Check if this is a PE/COFF file.
649    if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
650      // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
651      // PE signature to find 'normal' COFF header.
652      const auto *DH = reinterpret_cast<const dos_header *>(base());
653      if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
654        CurPtr = DH->AddressOfNewExeHeader;
655        // Check the PE magic bytes. ("PE\0\0")
656        if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
657          EC = object_error::parse_failed;
658          return;
659        }
660        CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
661        HasPEHeader = true;
662      }
663    }
664  
665    if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
666      return;
667  
668    // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
669    // import libraries share a common prefix but bigobj is more restrictive.
670    if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
671        COFFHeader->NumberOfSections == uint16_t(0xffff) &&
672        checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
673      if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
674        return;
675  
676      // Verify that we are dealing with bigobj.
677      if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
678          std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
679                      sizeof(COFF::BigObjMagic)) == 0) {
680        COFFHeader = nullptr;
681        CurPtr += sizeof(coff_bigobj_file_header);
682      } else {
683        // It's not a bigobj.
684        COFFBigObjHeader = nullptr;
685      }
686    }
687    if (COFFHeader) {
688      // The prior checkSize call may have failed.  This isn't a hard error
689      // because we were just trying to sniff out bigobj.
690      EC = std::error_code();
691      CurPtr += sizeof(coff_file_header);
692  
693      if (COFFHeader->isImportLibrary())
694        return;
695    }
696  
697    if (HasPEHeader) {
698      const pe32_header *Header;
699      if ((EC = getObject(Header, Data, base() + CurPtr)))
700        return;
701  
702      const uint8_t *DataDirAddr;
703      uint64_t DataDirSize;
704      if (Header->Magic == COFF::PE32Header::PE32) {
705        PE32Header = Header;
706        DataDirAddr = base() + CurPtr + sizeof(pe32_header);
707        DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
708      } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
709        PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
710        DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
711        DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
712      } else {
713        // It's neither PE32 nor PE32+.
714        EC = object_error::parse_failed;
715        return;
716      }
717      if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
718        return;
719      CurPtr += COFFHeader->SizeOfOptionalHeader;
720    }
721  
722    if ((EC = getObject(SectionTable, Data, base() + CurPtr,
723                        (uint64_t)getNumberOfSections() * sizeof(coff_section))))
724      return;
725  
726    // Initialize the pointer to the symbol table.
727    if (getPointerToSymbolTable() != 0) {
728      if ((EC = initSymbolTablePtr()))
729        return;
730    } else {
731      // We had better not have any symbols if we don't have a symbol table.
732      if (getNumberOfSymbols() != 0) {
733        EC = object_error::parse_failed;
734        return;
735      }
736    }
737  
738    // Initialize the pointer to the beginning of the import table.
739    if ((EC = initImportTablePtr()))
740      return;
741    if ((EC = initDelayImportTablePtr()))
742      return;
743  
744    // Initialize the pointer to the export table.
745    if ((EC = initExportTablePtr()))
746      return;
747  
748    // Initialize the pointer to the base relocation table.
749    if ((EC = initBaseRelocPtr()))
750      return;
751  
752    // Initialize the pointer to the export table.
753    if ((EC = initDebugDirectoryPtr()))
754      return;
755  
756    EC = std::error_code();
757  }
758  
symbol_begin_impl() const759  basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const {
760    DataRefImpl Ret;
761    Ret.p = getSymbolTable();
762    return basic_symbol_iterator(SymbolRef(Ret, this));
763  }
764  
symbol_end_impl() const765  basic_symbol_iterator COFFObjectFile::symbol_end_impl() const {
766    // The symbol table ends where the string table begins.
767    DataRefImpl Ret;
768    Ret.p = reinterpret_cast<uintptr_t>(StringTable);
769    return basic_symbol_iterator(SymbolRef(Ret, this));
770  }
771  
import_directory_begin() const772  import_directory_iterator COFFObjectFile::import_directory_begin() const {
773    if (!ImportDirectory)
774      return import_directory_end();
775    if (ImportDirectory[0].ImportLookupTableRVA == 0)
776      return import_directory_end();
777    return import_directory_iterator(
778        ImportDirectoryEntryRef(ImportDirectory, 0, this));
779  }
780  
import_directory_end() const781  import_directory_iterator COFFObjectFile::import_directory_end() const {
782    return import_directory_iterator(
783        ImportDirectoryEntryRef(nullptr, -1, this));
784  }
785  
786  delay_import_directory_iterator
delay_import_directory_begin() const787  COFFObjectFile::delay_import_directory_begin() const {
788    return delay_import_directory_iterator(
789        DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
790  }
791  
792  delay_import_directory_iterator
delay_import_directory_end() const793  COFFObjectFile::delay_import_directory_end() const {
794    return delay_import_directory_iterator(
795        DelayImportDirectoryEntryRef(
796            DelayImportDirectory, NumberOfDelayImportDirectory, this));
797  }
798  
export_directory_begin() const799  export_directory_iterator COFFObjectFile::export_directory_begin() const {
800    return export_directory_iterator(
801        ExportDirectoryEntryRef(ExportDirectory, 0, this));
802  }
803  
export_directory_end() const804  export_directory_iterator COFFObjectFile::export_directory_end() const {
805    if (!ExportDirectory)
806      return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
807    ExportDirectoryEntryRef Ref(ExportDirectory,
808                                ExportDirectory->AddressTableEntries, this);
809    return export_directory_iterator(Ref);
810  }
811  
section_begin() const812  section_iterator COFFObjectFile::section_begin() const {
813    DataRefImpl Ret;
814    Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
815    return section_iterator(SectionRef(Ret, this));
816  }
817  
section_end() const818  section_iterator COFFObjectFile::section_end() const {
819    DataRefImpl Ret;
820    int NumSections =
821        COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
822    Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
823    return section_iterator(SectionRef(Ret, this));
824  }
825  
base_reloc_begin() const826  base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
827    return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
828  }
829  
base_reloc_end() const830  base_reloc_iterator COFFObjectFile::base_reloc_end() const {
831    return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
832  }
833  
getBytesInAddress() const834  uint8_t COFFObjectFile::getBytesInAddress() const {
835    return getArch() == Triple::x86_64 ? 8 : 4;
836  }
837  
getFileFormatName() const838  StringRef COFFObjectFile::getFileFormatName() const {
839    switch(getMachine()) {
840    case COFF::IMAGE_FILE_MACHINE_I386:
841      return "COFF-i386";
842    case COFF::IMAGE_FILE_MACHINE_AMD64:
843      return "COFF-x86-64";
844    case COFF::IMAGE_FILE_MACHINE_ARMNT:
845      return "COFF-ARM";
846    case COFF::IMAGE_FILE_MACHINE_ARM64:
847      return "COFF-ARM64";
848    default:
849      return "COFF-<unknown arch>";
850    }
851  }
852  
getArch() const853  unsigned COFFObjectFile::getArch() const {
854    switch (getMachine()) {
855    case COFF::IMAGE_FILE_MACHINE_I386:
856      return Triple::x86;
857    case COFF::IMAGE_FILE_MACHINE_AMD64:
858      return Triple::x86_64;
859    case COFF::IMAGE_FILE_MACHINE_ARMNT:
860      return Triple::thumb;
861    case COFF::IMAGE_FILE_MACHINE_ARM64:
862      return Triple::aarch64;
863    default:
864      return Triple::UnknownArch;
865    }
866  }
867  
868  iterator_range<import_directory_iterator>
import_directories() const869  COFFObjectFile::import_directories() const {
870    return make_range(import_directory_begin(), import_directory_end());
871  }
872  
873  iterator_range<delay_import_directory_iterator>
delay_import_directories() const874  COFFObjectFile::delay_import_directories() const {
875    return make_range(delay_import_directory_begin(),
876                      delay_import_directory_end());
877  }
878  
879  iterator_range<export_directory_iterator>
export_directories() const880  COFFObjectFile::export_directories() const {
881    return make_range(export_directory_begin(), export_directory_end());
882  }
883  
base_relocs() const884  iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
885    return make_range(base_reloc_begin(), base_reloc_end());
886  }
887  
getPE32Header(const pe32_header * & Res) const888  std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
889    Res = PE32Header;
890    return std::error_code();
891  }
892  
893  std::error_code
getPE32PlusHeader(const pe32plus_header * & Res) const894  COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
895    Res = PE32PlusHeader;
896    return std::error_code();
897  }
898  
899  std::error_code
getDataDirectory(uint32_t Index,const data_directory * & Res) const900  COFFObjectFile::getDataDirectory(uint32_t Index,
901                                   const data_directory *&Res) const {
902    // Error if if there's no data directory or the index is out of range.
903    if (!DataDirectory) {
904      Res = nullptr;
905      return object_error::parse_failed;
906    }
907    assert(PE32Header || PE32PlusHeader);
908    uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
909                                 : PE32PlusHeader->NumberOfRvaAndSize;
910    if (Index >= NumEnt) {
911      Res = nullptr;
912      return object_error::parse_failed;
913    }
914    Res = &DataDirectory[Index];
915    return std::error_code();
916  }
917  
getSection(int32_t Index,const coff_section * & Result) const918  std::error_code COFFObjectFile::getSection(int32_t Index,
919                                             const coff_section *&Result) const {
920    Result = nullptr;
921    if (COFF::isReservedSectionNumber(Index))
922      return std::error_code();
923    if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
924      // We already verified the section table data, so no need to check again.
925      Result = SectionTable + (Index - 1);
926      return std::error_code();
927    }
928    return object_error::parse_failed;
929  }
930  
getString(uint32_t Offset,StringRef & Result) const931  std::error_code COFFObjectFile::getString(uint32_t Offset,
932                                            StringRef &Result) const {
933    if (StringTableSize <= 4)
934      // Tried to get a string from an empty string table.
935      return object_error::parse_failed;
936    if (Offset >= StringTableSize)
937      return object_error::unexpected_eof;
938    Result = StringRef(StringTable + Offset);
939    return std::error_code();
940  }
941  
getSymbolName(COFFSymbolRef Symbol,StringRef & Res) const942  std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
943                                                StringRef &Res) const {
944    return getSymbolName(Symbol.getGeneric(), Res);
945  }
946  
getSymbolName(const coff_symbol_generic * Symbol,StringRef & Res) const947  std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
948                                                StringRef &Res) const {
949    // Check for string table entry. First 4 bytes are 0.
950    if (Symbol->Name.Offset.Zeroes == 0) {
951      if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
952        return EC;
953      return std::error_code();
954    }
955  
956    if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
957      // Null terminated, let ::strlen figure out the length.
958      Res = StringRef(Symbol->Name.ShortName);
959    else
960      // Not null terminated, use all 8 bytes.
961      Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
962    return std::error_code();
963  }
964  
965  ArrayRef<uint8_t>
getSymbolAuxData(COFFSymbolRef Symbol) const966  COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
967    const uint8_t *Aux = nullptr;
968  
969    size_t SymbolSize = getSymbolTableEntrySize();
970    if (Symbol.getNumberOfAuxSymbols() > 0) {
971      // AUX data comes immediately after the symbol in COFF
972      Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
973  # ifndef NDEBUG
974      // Verify that the Aux symbol points to a valid entry in the symbol table.
975      uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
976      if (Offset < getPointerToSymbolTable() ||
977          Offset >=
978              getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
979        report_fatal_error("Aux Symbol data was outside of symbol table.");
980  
981      assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
982             "Aux Symbol data did not point to the beginning of a symbol");
983  # endif
984    }
985    return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
986  }
987  
getSectionName(const coff_section * Sec,StringRef & Res) const988  std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
989                                                 StringRef &Res) const {
990    StringRef Name;
991    if (Sec->Name[COFF::NameSize - 1] == 0)
992      // Null terminated, let ::strlen figure out the length.
993      Name = Sec->Name;
994    else
995      // Not null terminated, use all 8 bytes.
996      Name = StringRef(Sec->Name, COFF::NameSize);
997  
998    // Check for string table entry. First byte is '/'.
999    if (Name.startswith("/")) {
1000      uint32_t Offset;
1001      if (Name.startswith("//")) {
1002        if (decodeBase64StringEntry(Name.substr(2), Offset))
1003          return object_error::parse_failed;
1004      } else {
1005        if (Name.substr(1).getAsInteger(10, Offset))
1006          return object_error::parse_failed;
1007      }
1008      if (std::error_code EC = getString(Offset, Name))
1009        return EC;
1010    }
1011  
1012    Res = Name;
1013    return std::error_code();
1014  }
1015  
getSectionSize(const coff_section * Sec) const1016  uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1017    // SizeOfRawData and VirtualSize change what they represent depending on
1018    // whether or not we have an executable image.
1019    //
1020    // For object files, SizeOfRawData contains the size of section's data;
1021    // VirtualSize should be zero but isn't due to buggy COFF writers.
1022    //
1023    // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1024    // actual section size is in VirtualSize.  It is possible for VirtualSize to
1025    // be greater than SizeOfRawData; the contents past that point should be
1026    // considered to be zero.
1027    if (getDOSHeader())
1028      return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1029    return Sec->SizeOfRawData;
1030  }
1031  
1032  std::error_code
getSectionContents(const coff_section * Sec,ArrayRef<uint8_t> & Res) const1033  COFFObjectFile::getSectionContents(const coff_section *Sec,
1034                                     ArrayRef<uint8_t> &Res) const {
1035    // In COFF, a virtual section won't have any in-file
1036    // content, so the file pointer to the content will be zero.
1037    if (Sec->PointerToRawData == 0)
1038      return object_error::parse_failed;
1039    // The only thing that we need to verify is that the contents is contained
1040    // within the file bounds. We don't need to make sure it doesn't cover other
1041    // data, as there's nothing that says that is not allowed.
1042    uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1043    uint32_t SectionSize = getSectionSize(Sec);
1044    if (checkOffset(Data, ConStart, SectionSize))
1045      return object_error::parse_failed;
1046    Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1047    return std::error_code();
1048  }
1049  
toRel(DataRefImpl Rel) const1050  const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1051    return reinterpret_cast<const coff_relocation*>(Rel.p);
1052  }
1053  
moveRelocationNext(DataRefImpl & Rel) const1054  void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1055    Rel.p = reinterpret_cast<uintptr_t>(
1056              reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1057  }
1058  
getRelocationOffset(DataRefImpl Rel) const1059  uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
1060    const coff_relocation *R = toRel(Rel);
1061    return R->VirtualAddress;
1062  }
1063  
getRelocationSymbol(DataRefImpl Rel) const1064  symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1065    const coff_relocation *R = toRel(Rel);
1066    DataRefImpl Ref;
1067    if (R->SymbolTableIndex >= getNumberOfSymbols())
1068      return symbol_end();
1069    if (SymbolTable16)
1070      Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
1071    else if (SymbolTable32)
1072      Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
1073    else
1074      llvm_unreachable("no symbol table pointer!");
1075    return symbol_iterator(SymbolRef(Ref, this));
1076  }
1077  
getRelocationType(DataRefImpl Rel) const1078  uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1079    const coff_relocation* R = toRel(Rel);
1080    return R->Type;
1081  }
1082  
1083  const coff_section *
getCOFFSection(const SectionRef & Section) const1084  COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
1085    return toSec(Section.getRawDataRefImpl());
1086  }
1087  
getCOFFSymbol(const DataRefImpl & Ref) const1088  COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
1089    if (SymbolTable16)
1090      return toSymb<coff_symbol16>(Ref);
1091    if (SymbolTable32)
1092      return toSymb<coff_symbol32>(Ref);
1093    llvm_unreachable("no symbol table pointer!");
1094  }
1095  
getCOFFSymbol(const SymbolRef & Symbol) const1096  COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
1097    return getCOFFSymbol(Symbol.getRawDataRefImpl());
1098  }
1099  
1100  const coff_relocation *
getCOFFRelocation(const RelocationRef & Reloc) const1101  COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
1102    return toRel(Reloc.getRawDataRefImpl());
1103  }
1104  
1105  iterator_range<const coff_relocation *>
getRelocations(const coff_section * Sec) const1106  COFFObjectFile::getRelocations(const coff_section *Sec) const {
1107    const coff_relocation *I = getFirstReloc(Sec, Data, base());
1108    const coff_relocation *E = I;
1109    if (I)
1110      E += getNumberOfRelocations(Sec, Data, base());
1111    return make_range(I, E);
1112  }
1113  
1114  #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
1115    case COFF::reloc_type:                                                       \
1116      Res = #reloc_type;                                                         \
1117      break;
1118  
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const1119  void COFFObjectFile::getRelocationTypeName(
1120      DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1121    const coff_relocation *Reloc = toRel(Rel);
1122    StringRef Res;
1123    switch (getMachine()) {
1124    case COFF::IMAGE_FILE_MACHINE_AMD64:
1125      switch (Reloc->Type) {
1126      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1127      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1128      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1129      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1130      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1131      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1132      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1133      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1134      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1135      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1136      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1137      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1138      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1139      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1140      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1141      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1142      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1143      default:
1144        Res = "Unknown";
1145      }
1146      break;
1147    case COFF::IMAGE_FILE_MACHINE_ARMNT:
1148      switch (Reloc->Type) {
1149      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
1150      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
1151      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
1152      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
1153      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
1154      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
1155      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
1156      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1157      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
1158      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
1159      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
1160      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
1161      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
1162      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
1163      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1164      default:
1165        Res = "Unknown";
1166      }
1167      break;
1168    case COFF::IMAGE_FILE_MACHINE_I386:
1169      switch (Reloc->Type) {
1170      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1171      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1172      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1173      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1174      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1175      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1176      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1177      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1178      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1179      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1180      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1181      default:
1182        Res = "Unknown";
1183      }
1184      break;
1185    default:
1186      Res = "Unknown";
1187    }
1188    Result.append(Res.begin(), Res.end());
1189  }
1190  
1191  #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1192  
isRelocatableObject() const1193  bool COFFObjectFile::isRelocatableObject() const {
1194    return !DataDirectory;
1195  }
1196  
1197  bool ImportDirectoryEntryRef::
operator ==(const ImportDirectoryEntryRef & Other) const1198  operator==(const ImportDirectoryEntryRef &Other) const {
1199    return ImportTable == Other.ImportTable && Index == Other.Index;
1200  }
1201  
moveNext()1202  void ImportDirectoryEntryRef::moveNext() {
1203    ++Index;
1204    if (ImportTable[Index].ImportLookupTableRVA == 0) {
1205      Index = -1;
1206      ImportTable = nullptr;
1207    }
1208  }
1209  
getImportTableEntry(const import_directory_table_entry * & Result) const1210  std::error_code ImportDirectoryEntryRef::getImportTableEntry(
1211      const import_directory_table_entry *&Result) const {
1212    return getObject(Result, OwningObject->Data, ImportTable + Index);
1213  }
1214  
1215  static imported_symbol_iterator
makeImportedSymbolIterator(const COFFObjectFile * Object,uintptr_t Ptr,int Index)1216  makeImportedSymbolIterator(const COFFObjectFile *Object,
1217                             uintptr_t Ptr, int Index) {
1218    if (Object->getBytesInAddress() == 4) {
1219      auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
1220      return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1221    }
1222    auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
1223    return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1224  }
1225  
1226  static imported_symbol_iterator
importedSymbolBegin(uint32_t RVA,const COFFObjectFile * Object)1227  importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1228    uintptr_t IntPtr = 0;
1229    Object->getRvaPtr(RVA, IntPtr);
1230    return makeImportedSymbolIterator(Object, IntPtr, 0);
1231  }
1232  
1233  static imported_symbol_iterator
importedSymbolEnd(uint32_t RVA,const COFFObjectFile * Object)1234  importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1235    uintptr_t IntPtr = 0;
1236    Object->getRvaPtr(RVA, IntPtr);
1237    // Forward the pointer to the last entry which is null.
1238    int Index = 0;
1239    if (Object->getBytesInAddress() == 4) {
1240      auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1241      while (*Entry++)
1242        ++Index;
1243    } else {
1244      auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1245      while (*Entry++)
1246        ++Index;
1247    }
1248    return makeImportedSymbolIterator(Object, IntPtr, Index);
1249  }
1250  
1251  imported_symbol_iterator
imported_symbol_begin() const1252  ImportDirectoryEntryRef::imported_symbol_begin() const {
1253    return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
1254                               OwningObject);
1255  }
1256  
1257  imported_symbol_iterator
imported_symbol_end() const1258  ImportDirectoryEntryRef::imported_symbol_end() const {
1259    return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
1260                             OwningObject);
1261  }
1262  
1263  iterator_range<imported_symbol_iterator>
imported_symbols() const1264  ImportDirectoryEntryRef::imported_symbols() const {
1265    return make_range(imported_symbol_begin(), imported_symbol_end());
1266  }
1267  
getName(StringRef & Result) const1268  std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1269    uintptr_t IntPtr = 0;
1270    if (std::error_code EC =
1271            OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1272      return EC;
1273    Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1274    return std::error_code();
1275  }
1276  
1277  std::error_code
getImportLookupTableRVA(uint32_t & Result) const1278  ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
1279    Result = ImportTable[Index].ImportLookupTableRVA;
1280    return std::error_code();
1281  }
1282  
1283  std::error_code
getImportAddressTableRVA(uint32_t & Result) const1284  ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
1285    Result = ImportTable[Index].ImportAddressTableRVA;
1286    return std::error_code();
1287  }
1288  
1289  bool DelayImportDirectoryEntryRef::
operator ==(const DelayImportDirectoryEntryRef & Other) const1290  operator==(const DelayImportDirectoryEntryRef &Other) const {
1291    return Table == Other.Table && Index == Other.Index;
1292  }
1293  
moveNext()1294  void DelayImportDirectoryEntryRef::moveNext() {
1295    ++Index;
1296  }
1297  
1298  imported_symbol_iterator
imported_symbol_begin() const1299  DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1300    return importedSymbolBegin(Table[Index].DelayImportNameTable,
1301                               OwningObject);
1302  }
1303  
1304  imported_symbol_iterator
imported_symbol_end() const1305  DelayImportDirectoryEntryRef::imported_symbol_end() const {
1306    return importedSymbolEnd(Table[Index].DelayImportNameTable,
1307                             OwningObject);
1308  }
1309  
1310  iterator_range<imported_symbol_iterator>
imported_symbols() const1311  DelayImportDirectoryEntryRef::imported_symbols() const {
1312    return make_range(imported_symbol_begin(), imported_symbol_end());
1313  }
1314  
getName(StringRef & Result) const1315  std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
1316    uintptr_t IntPtr = 0;
1317    if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
1318      return EC;
1319    Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1320    return std::error_code();
1321  }
1322  
1323  std::error_code DelayImportDirectoryEntryRef::
getDelayImportTable(const delay_import_directory_table_entry * & Result) const1324  getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
1325    Result = Table;
1326    return std::error_code();
1327  }
1328  
1329  std::error_code DelayImportDirectoryEntryRef::
getImportAddress(int AddrIndex,uint64_t & Result) const1330  getImportAddress(int AddrIndex, uint64_t &Result) const {
1331    uint32_t RVA = Table[Index].DelayImportAddressTable +
1332        AddrIndex * (OwningObject->is64() ? 8 : 4);
1333    uintptr_t IntPtr = 0;
1334    if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1335      return EC;
1336    if (OwningObject->is64())
1337      Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1338    else
1339      Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
1340    return std::error_code();
1341  }
1342  
1343  bool ExportDirectoryEntryRef::
operator ==(const ExportDirectoryEntryRef & Other) const1344  operator==(const ExportDirectoryEntryRef &Other) const {
1345    return ExportTable == Other.ExportTable && Index == Other.Index;
1346  }
1347  
moveNext()1348  void ExportDirectoryEntryRef::moveNext() {
1349    ++Index;
1350  }
1351  
1352  // Returns the name of the current export symbol. If the symbol is exported only
1353  // by ordinal, the empty string is set as a result.
getDllName(StringRef & Result) const1354  std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1355    uintptr_t IntPtr = 0;
1356    if (std::error_code EC =
1357            OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1358      return EC;
1359    Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1360    return std::error_code();
1361  }
1362  
1363  // Returns the starting ordinal number.
1364  std::error_code
getOrdinalBase(uint32_t & Result) const1365  ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1366    Result = ExportTable->OrdinalBase;
1367    return std::error_code();
1368  }
1369  
1370  // Returns the export ordinal of the current export symbol.
getOrdinal(uint32_t & Result) const1371  std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1372    Result = ExportTable->OrdinalBase + Index;
1373    return std::error_code();
1374  }
1375  
1376  // Returns the address of the current export symbol.
getExportRVA(uint32_t & Result) const1377  std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1378    uintptr_t IntPtr = 0;
1379    if (std::error_code EC =
1380            OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1381      return EC;
1382    const export_address_table_entry *entry =
1383        reinterpret_cast<const export_address_table_entry *>(IntPtr);
1384    Result = entry[Index].ExportRVA;
1385    return std::error_code();
1386  }
1387  
1388  // Returns the name of the current export symbol. If the symbol is exported only
1389  // by ordinal, the empty string is set as a result.
1390  std::error_code
getSymbolName(StringRef & Result) const1391  ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1392    uintptr_t IntPtr = 0;
1393    if (std::error_code EC =
1394            OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1395      return EC;
1396    const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1397  
1398    uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1399    int Offset = 0;
1400    for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1401         I < E; ++I, ++Offset) {
1402      if (*I != Index)
1403        continue;
1404      if (std::error_code EC =
1405              OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1406        return EC;
1407      const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1408      if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1409        return EC;
1410      Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1411      return std::error_code();
1412    }
1413    Result = "";
1414    return std::error_code();
1415  }
1416  
isForwarder(bool & Result) const1417  std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
1418    const data_directory *DataEntry;
1419    if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
1420      return EC;
1421    uint32_t RVA;
1422    if (auto EC = getExportRVA(RVA))
1423      return EC;
1424    uint32_t Begin = DataEntry->RelativeVirtualAddress;
1425    uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
1426    Result = (Begin <= RVA && RVA < End);
1427    return std::error_code();
1428  }
1429  
getForwardTo(StringRef & Result) const1430  std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
1431    uint32_t RVA;
1432    if (auto EC = getExportRVA(RVA))
1433      return EC;
1434    uintptr_t IntPtr = 0;
1435    if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
1436      return EC;
1437    Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1438    return std::error_code();
1439  }
1440  
1441  bool ImportedSymbolRef::
operator ==(const ImportedSymbolRef & Other) const1442  operator==(const ImportedSymbolRef &Other) const {
1443    return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1444        && Index == Other.Index;
1445  }
1446  
moveNext()1447  void ImportedSymbolRef::moveNext() {
1448    ++Index;
1449  }
1450  
1451  std::error_code
getSymbolName(StringRef & Result) const1452  ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1453    uint32_t RVA;
1454    if (Entry32) {
1455      // If a symbol is imported only by ordinal, it has no name.
1456      if (Entry32[Index].isOrdinal())
1457        return std::error_code();
1458      RVA = Entry32[Index].getHintNameRVA();
1459    } else {
1460      if (Entry64[Index].isOrdinal())
1461        return std::error_code();
1462      RVA = Entry64[Index].getHintNameRVA();
1463    }
1464    uintptr_t IntPtr = 0;
1465    if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1466      return EC;
1467    // +2 because the first two bytes is hint.
1468    Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
1469    return std::error_code();
1470  }
1471  
isOrdinal(bool & Result) const1472  std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1473    if (Entry32)
1474      Result = Entry32[Index].isOrdinal();
1475    else
1476      Result = Entry64[Index].isOrdinal();
1477    return std::error_code();
1478  }
1479  
getHintNameRVA(uint32_t & Result) const1480  std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1481    if (Entry32)
1482      Result = Entry32[Index].getHintNameRVA();
1483    else
1484      Result = Entry64[Index].getHintNameRVA();
1485    return std::error_code();
1486  }
1487  
getOrdinal(uint16_t & Result) const1488  std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1489    uint32_t RVA;
1490    if (Entry32) {
1491      if (Entry32[Index].isOrdinal()) {
1492        Result = Entry32[Index].getOrdinal();
1493        return std::error_code();
1494      }
1495      RVA = Entry32[Index].getHintNameRVA();
1496    } else {
1497      if (Entry64[Index].isOrdinal()) {
1498        Result = Entry64[Index].getOrdinal();
1499        return std::error_code();
1500      }
1501      RVA = Entry64[Index].getHintNameRVA();
1502    }
1503    uintptr_t IntPtr = 0;
1504    if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1505      return EC;
1506    Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
1507    return std::error_code();
1508  }
1509  
1510  ErrorOr<std::unique_ptr<COFFObjectFile>>
createCOFFObjectFile(MemoryBufferRef Object)1511  ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1512    std::error_code EC;
1513    std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1514    if (EC)
1515      return EC;
1516    return std::move(Ret);
1517  }
1518  
operator ==(const BaseRelocRef & Other) const1519  bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
1520    return Header == Other.Header && Index == Other.Index;
1521  }
1522  
moveNext()1523  void BaseRelocRef::moveNext() {
1524    // Header->BlockSize is the size of the current block, including the
1525    // size of the header itself.
1526    uint32_t Size = sizeof(*Header) +
1527        sizeof(coff_base_reloc_block_entry) * (Index + 1);
1528    if (Size == Header->BlockSize) {
1529      // .reloc contains a list of base relocation blocks. Each block
1530      // consists of the header followed by entries. The header contains
1531      // how many entories will follow. When we reach the end of the
1532      // current block, proceed to the next block.
1533      Header = reinterpret_cast<const coff_base_reloc_block_header *>(
1534          reinterpret_cast<const uint8_t *>(Header) + Size);
1535      Index = 0;
1536    } else {
1537      ++Index;
1538    }
1539  }
1540  
getType(uint8_t & Type) const1541  std::error_code BaseRelocRef::getType(uint8_t &Type) const {
1542    auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
1543    Type = Entry[Index].getType();
1544    return std::error_code();
1545  }
1546  
getRVA(uint32_t & Result) const1547  std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
1548    auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
1549    Result = Header->PageRVA + Entry[Index].getOffset();
1550    return std::error_code();
1551  }
1552