1224133Sdim//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===//
2224133Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6224133Sdim//
7224133Sdim//===----------------------------------------------------------------------===//
8224133Sdim//
9224133Sdim// This file declares the COFFObjectFile class.
10224133Sdim//
11224133Sdim//===----------------------------------------------------------------------===//
12224133Sdim
13224133Sdim#ifndef LLVM_OBJECT_COFF_H
14224133Sdim#define LLVM_OBJECT_COFF_H
15224133Sdim
16321369Sdim#include "llvm/ADT/iterator_range.h"
17321369Sdim#include "llvm/BinaryFormat/COFF.h"
18321369Sdim#include "llvm/MC/SubtargetFeature.h"
19321369Sdim#include "llvm/Object/Binary.h"
20341825Sdim#include "llvm/Object/CVDebugRecord.h"
21321369Sdim#include "llvm/Object/Error.h"
22224133Sdim#include "llvm/Object/ObjectFile.h"
23321369Sdim#include "llvm/Support/BinaryByteStream.h"
24321369Sdim#include "llvm/Support/ConvertUTF.h"
25224133Sdim#include "llvm/Support/Endian.h"
26321369Sdim#include "llvm/Support/ErrorHandling.h"
27321369Sdim#include <cassert>
28321369Sdim#include <cstddef>
29321369Sdim#include <cstdint>
30321369Sdim#include <system_error>
31224133Sdim
32224133Sdimnamespace llvm {
33321369Sdim
34276479Sdimtemplate <typename T> class ArrayRef;
35234353Sdim
36224133Sdimnamespace object {
37321369Sdim
38321369Sdimclass BaseRelocRef;
39280031Sdimclass DelayImportDirectoryEntryRef;
40276479Sdimclass ExportDirectoryEntryRef;
41321369Sdimclass ImportDirectoryEntryRef;
42280031Sdimclass ImportedSymbolRef;
43321369Sdimclass ResourceSectionRef;
44224133Sdim
45321369Sdimusing import_directory_iterator = content_iterator<ImportDirectoryEntryRef>;
46321369Sdimusing delay_import_directory_iterator =
47321369Sdim    content_iterator<DelayImportDirectoryEntryRef>;
48321369Sdimusing export_directory_iterator = content_iterator<ExportDirectoryEntryRef>;
49321369Sdimusing imported_symbol_iterator = content_iterator<ImportedSymbolRef>;
50321369Sdimusing base_reloc_iterator = content_iterator<BaseRelocRef>;
51321369Sdim
52261991Sdim/// The DOS compatible header at the front of all PE/COFF executables.
53261991Sdimstruct dos_header {
54280031Sdim  char                 Magic[2];
55261991Sdim  support::ulittle16_t UsedBytesInTheLastPage;
56261991Sdim  support::ulittle16_t FileSizeInPages;
57261991Sdim  support::ulittle16_t NumberOfRelocationItems;
58261991Sdim  support::ulittle16_t HeaderSizeInParagraphs;
59261991Sdim  support::ulittle16_t MinimumExtraParagraphs;
60261991Sdim  support::ulittle16_t MaximumExtraParagraphs;
61261991Sdim  support::ulittle16_t InitialRelativeSS;
62261991Sdim  support::ulittle16_t InitialSP;
63261991Sdim  support::ulittle16_t Checksum;
64261991Sdim  support::ulittle16_t InitialIP;
65261991Sdim  support::ulittle16_t InitialRelativeCS;
66261991Sdim  support::ulittle16_t AddressOfRelocationTable;
67261991Sdim  support::ulittle16_t OverlayNumber;
68261991Sdim  support::ulittle16_t Reserved[4];
69261991Sdim  support::ulittle16_t OEMid;
70261991Sdim  support::ulittle16_t OEMinfo;
71261991Sdim  support::ulittle16_t Reserved2[10];
72261991Sdim  support::ulittle32_t AddressOfNewExeHeader;
73261991Sdim};
74261991Sdim
75224133Sdimstruct coff_file_header {
76224133Sdim  support::ulittle16_t Machine;
77224133Sdim  support::ulittle16_t NumberOfSections;
78224133Sdim  support::ulittle32_t TimeDateStamp;
79224133Sdim  support::ulittle32_t PointerToSymbolTable;
80224133Sdim  support::ulittle32_t NumberOfSymbols;
81224133Sdim  support::ulittle16_t SizeOfOptionalHeader;
82224133Sdim  support::ulittle16_t Characteristics;
83261991Sdim
84261991Sdim  bool isImportLibrary() const { return NumberOfSections == 0xffff; }
85224133Sdim};
86224133Sdim
87280031Sdimstruct coff_bigobj_file_header {
88280031Sdim  support::ulittle16_t Sig1;
89280031Sdim  support::ulittle16_t Sig2;
90280031Sdim  support::ulittle16_t Version;
91280031Sdim  support::ulittle16_t Machine;
92280031Sdim  support::ulittle32_t TimeDateStamp;
93280031Sdim  uint8_t              UUID[16];
94280031Sdim  support::ulittle32_t unused1;
95280031Sdim  support::ulittle32_t unused2;
96280031Sdim  support::ulittle32_t unused3;
97280031Sdim  support::ulittle32_t unused4;
98280031Sdim  support::ulittle32_t NumberOfSections;
99280031Sdim  support::ulittle32_t PointerToSymbolTable;
100280031Sdim  support::ulittle32_t NumberOfSymbols;
101280031Sdim};
102280031Sdim
103261991Sdim/// The 32-bit PE header that follows the COFF header.
104261991Sdimstruct pe32_header {
105261991Sdim  support::ulittle16_t Magic;
106276479Sdim  uint8_t MajorLinkerVersion;
107276479Sdim  uint8_t MinorLinkerVersion;
108261991Sdim  support::ulittle32_t SizeOfCode;
109261991Sdim  support::ulittle32_t SizeOfInitializedData;
110261991Sdim  support::ulittle32_t SizeOfUninitializedData;
111261991Sdim  support::ulittle32_t AddressOfEntryPoint;
112261991Sdim  support::ulittle32_t BaseOfCode;
113261991Sdim  support::ulittle32_t BaseOfData;
114261991Sdim  support::ulittle32_t ImageBase;
115261991Sdim  support::ulittle32_t SectionAlignment;
116261991Sdim  support::ulittle32_t FileAlignment;
117261991Sdim  support::ulittle16_t MajorOperatingSystemVersion;
118261991Sdim  support::ulittle16_t MinorOperatingSystemVersion;
119261991Sdim  support::ulittle16_t MajorImageVersion;
120261991Sdim  support::ulittle16_t MinorImageVersion;
121261991Sdim  support::ulittle16_t MajorSubsystemVersion;
122261991Sdim  support::ulittle16_t MinorSubsystemVersion;
123261991Sdim  support::ulittle32_t Win32VersionValue;
124261991Sdim  support::ulittle32_t SizeOfImage;
125261991Sdim  support::ulittle32_t SizeOfHeaders;
126261991Sdim  support::ulittle32_t CheckSum;
127261991Sdim  support::ulittle16_t Subsystem;
128280031Sdim  // FIXME: This should be DllCharacteristics.
129261991Sdim  support::ulittle16_t DLLCharacteristics;
130261991Sdim  support::ulittle32_t SizeOfStackReserve;
131261991Sdim  support::ulittle32_t SizeOfStackCommit;
132261991Sdim  support::ulittle32_t SizeOfHeapReserve;
133261991Sdim  support::ulittle32_t SizeOfHeapCommit;
134261991Sdim  support::ulittle32_t LoaderFlags;
135280031Sdim  // FIXME: This should be NumberOfRvaAndSizes.
136261991Sdim  support::ulittle32_t NumberOfRvaAndSize;
137261991Sdim};
138261991Sdim
139261991Sdim/// The 64-bit PE header that follows the COFF header.
140261991Sdimstruct pe32plus_header {
141261991Sdim  support::ulittle16_t Magic;
142276479Sdim  uint8_t MajorLinkerVersion;
143276479Sdim  uint8_t MinorLinkerVersion;
144261991Sdim  support::ulittle32_t SizeOfCode;
145261991Sdim  support::ulittle32_t SizeOfInitializedData;
146261991Sdim  support::ulittle32_t SizeOfUninitializedData;
147261991Sdim  support::ulittle32_t AddressOfEntryPoint;
148261991Sdim  support::ulittle32_t BaseOfCode;
149261991Sdim  support::ulittle64_t ImageBase;
150261991Sdim  support::ulittle32_t SectionAlignment;
151261991Sdim  support::ulittle32_t FileAlignment;
152261991Sdim  support::ulittle16_t MajorOperatingSystemVersion;
153261991Sdim  support::ulittle16_t MinorOperatingSystemVersion;
154261991Sdim  support::ulittle16_t MajorImageVersion;
155261991Sdim  support::ulittle16_t MinorImageVersion;
156261991Sdim  support::ulittle16_t MajorSubsystemVersion;
157261991Sdim  support::ulittle16_t MinorSubsystemVersion;
158261991Sdim  support::ulittle32_t Win32VersionValue;
159261991Sdim  support::ulittle32_t SizeOfImage;
160261991Sdim  support::ulittle32_t SizeOfHeaders;
161261991Sdim  support::ulittle32_t CheckSum;
162261991Sdim  support::ulittle16_t Subsystem;
163261991Sdim  support::ulittle16_t DLLCharacteristics;
164261991Sdim  support::ulittle64_t SizeOfStackReserve;
165261991Sdim  support::ulittle64_t SizeOfStackCommit;
166261991Sdim  support::ulittle64_t SizeOfHeapReserve;
167261991Sdim  support::ulittle64_t SizeOfHeapCommit;
168261991Sdim  support::ulittle32_t LoaderFlags;
169261991Sdim  support::ulittle32_t NumberOfRvaAndSize;
170261991Sdim};
171261991Sdim
172261991Sdimstruct data_directory {
173261991Sdim  support::ulittle32_t RelativeVirtualAddress;
174261991Sdim  support::ulittle32_t Size;
175261991Sdim};
176261991Sdim
177309124Sdimstruct debug_directory {
178309124Sdim  support::ulittle32_t Characteristics;
179309124Sdim  support::ulittle32_t TimeDateStamp;
180309124Sdim  support::ulittle16_t MajorVersion;
181309124Sdim  support::ulittle16_t MinorVersion;
182309124Sdim  support::ulittle32_t Type;
183309124Sdim  support::ulittle32_t SizeOfData;
184309124Sdim  support::ulittle32_t AddressOfRawData;
185309124Sdim  support::ulittle32_t PointerToRawData;
186309124Sdim};
187309124Sdim
188280031Sdimtemplate <typename IntTy>
189280031Sdimstruct import_lookup_table_entry {
190280031Sdim  IntTy Data;
191261991Sdim
192280031Sdim  bool isOrdinal() const { return Data < 0; }
193261991Sdim
194261991Sdim  uint16_t getOrdinal() const {
195261991Sdim    assert(isOrdinal() && "ILT entry is not an ordinal!");
196280031Sdim    return Data & 0xFFFF;
197261991Sdim  }
198261991Sdim
199261991Sdim  uint32_t getHintNameRVA() const {
200261991Sdim    assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
201280031Sdim    return Data & 0xFFFFFFFF;
202261991Sdim  }
203261991Sdim};
204261991Sdim
205321369Sdimusing import_lookup_table_entry32 =
206321369Sdim    import_lookup_table_entry<support::little32_t>;
207321369Sdimusing import_lookup_table_entry64 =
208321369Sdim    import_lookup_table_entry<support::little64_t>;
209280031Sdim
210280031Sdimstruct delay_import_directory_table_entry {
211280031Sdim  // dumpbin reports this field as "Characteristics" instead of "Attributes".
212280031Sdim  support::ulittle32_t Attributes;
213280031Sdim  support::ulittle32_t Name;
214280031Sdim  support::ulittle32_t ModuleHandle;
215280031Sdim  support::ulittle32_t DelayImportAddressTable;
216280031Sdim  support::ulittle32_t DelayImportNameTable;
217280031Sdim  support::ulittle32_t BoundDelayImportTable;
218280031Sdim  support::ulittle32_t UnloadDelayImportTable;
219280031Sdim  support::ulittle32_t TimeStamp;
220280031Sdim};
221280031Sdim
222276479Sdimstruct export_directory_table_entry {
223276479Sdim  support::ulittle32_t ExportFlags;
224276479Sdim  support::ulittle32_t TimeDateStamp;
225276479Sdim  support::ulittle16_t MajorVersion;
226276479Sdim  support::ulittle16_t MinorVersion;
227276479Sdim  support::ulittle32_t NameRVA;
228276479Sdim  support::ulittle32_t OrdinalBase;
229276479Sdim  support::ulittle32_t AddressTableEntries;
230276479Sdim  support::ulittle32_t NumberOfNamePointers;
231276479Sdim  support::ulittle32_t ExportAddressTableRVA;
232276479Sdim  support::ulittle32_t NamePointerRVA;
233276479Sdim  support::ulittle32_t OrdinalTableRVA;
234276479Sdim};
235276479Sdim
236276479Sdimunion export_address_table_entry {
237276479Sdim  support::ulittle32_t ExportRVA;
238276479Sdim  support::ulittle32_t ForwarderRVA;
239276479Sdim};
240276479Sdim
241321369Sdimusing export_name_pointer_table_entry = support::ulittle32_t;
242321369Sdimusing export_ordinal_table_entry = support::ulittle16_t;
243276479Sdim
244280031Sdimstruct StringTableOffset {
245280031Sdim  support::ulittle32_t Zeroes;
246280031Sdim  support::ulittle32_t Offset;
247280031Sdim};
248280031Sdim
249280031Sdimtemplate <typename SectionNumberType>
250224133Sdimstruct coff_symbol {
251224133Sdim  union {
252280031Sdim    char ShortName[COFF::NameSize];
253224133Sdim    StringTableOffset Offset;
254224133Sdim  } Name;
255224133Sdim
256224133Sdim  support::ulittle32_t Value;
257280031Sdim  SectionNumberType SectionNumber;
258224133Sdim
259234353Sdim  support::ulittle16_t Type;
260224133Sdim
261280031Sdim  uint8_t StorageClass;
262280031Sdim  uint8_t NumberOfAuxSymbols;
263280031Sdim};
264234353Sdim
265321369Sdimusing coff_symbol16 = coff_symbol<support::ulittle16_t>;
266321369Sdimusing coff_symbol32 = coff_symbol<support::ulittle32_t>;
267276479Sdim
268288943Sdim// Contains only common parts of coff_symbol16 and coff_symbol32.
269288943Sdimstruct coff_symbol_generic {
270288943Sdim  union {
271288943Sdim    char ShortName[COFF::NameSize];
272288943Sdim    StringTableOffset Offset;
273288943Sdim  } Name;
274288943Sdim  support::ulittle32_t Value;
275288943Sdim};
276288943Sdim
277327952Sdimstruct coff_aux_section_definition;
278341825Sdimstruct coff_aux_weak_external;
279327952Sdim
280280031Sdimclass COFFSymbolRef {
281280031Sdimpublic:
282321369Sdim  COFFSymbolRef() = default;
283321369Sdim  COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {}
284321369Sdim  COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {}
285276479Sdim
286280031Sdim  const void *getRawPtr() const {
287280031Sdim    return CS16 ? static_cast<const void *>(CS16) : CS32;
288280031Sdim  }
289280031Sdim
290288943Sdim  const coff_symbol_generic *getGeneric() const {
291288943Sdim    if (CS16)
292288943Sdim      return reinterpret_cast<const coff_symbol_generic *>(CS16);
293288943Sdim    return reinterpret_cast<const coff_symbol_generic *>(CS32);
294288943Sdim  }
295288943Sdim
296280031Sdim  friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) {
297280031Sdim    return A.getRawPtr() < B.getRawPtr();
298280031Sdim  }
299280031Sdim
300280031Sdim  bool isBigObj() const {
301280031Sdim    if (CS16)
302280031Sdim      return false;
303280031Sdim    if (CS32)
304280031Sdim      return true;
305280031Sdim    llvm_unreachable("COFFSymbolRef points to nothing!");
306280031Sdim  }
307280031Sdim
308280031Sdim  const char *getShortName() const {
309280031Sdim    return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName;
310280031Sdim  }
311280031Sdim
312280031Sdim  const StringTableOffset &getStringTableOffset() const {
313280031Sdim    assert(isSet() && "COFFSymbolRef points to nothing!");
314280031Sdim    return CS16 ? CS16->Name.Offset : CS32->Name.Offset;
315280031Sdim  }
316280031Sdim
317360784Sdim  uint32_t getValue() const {
318360784Sdim    assert(isSet() && "COFFSymbolRef points to nothing!");
319360784Sdim    return CS16 ? CS16->Value : CS32->Value;
320360784Sdim  }
321280031Sdim
322280031Sdim  int32_t getSectionNumber() const {
323280031Sdim    assert(isSet() && "COFFSymbolRef points to nothing!");
324280031Sdim    if (CS16) {
325280031Sdim      // Reserved sections are returned as negative numbers.
326280031Sdim      if (CS16->SectionNumber <= COFF::MaxNumberOfSections16)
327280031Sdim        return CS16->SectionNumber;
328280031Sdim      return static_cast<int16_t>(CS16->SectionNumber);
329280031Sdim    }
330280031Sdim    return static_cast<int32_t>(CS32->SectionNumber);
331280031Sdim  }
332280031Sdim
333280031Sdim  uint16_t getType() const {
334280031Sdim    assert(isSet() && "COFFSymbolRef points to nothing!");
335280031Sdim    return CS16 ? CS16->Type : CS32->Type;
336280031Sdim  }
337280031Sdim
338280031Sdim  uint8_t getStorageClass() const {
339280031Sdim    assert(isSet() && "COFFSymbolRef points to nothing!");
340280031Sdim    return CS16 ? CS16->StorageClass : CS32->StorageClass;
341280031Sdim  }
342280031Sdim
343280031Sdim  uint8_t getNumberOfAuxSymbols() const {
344280031Sdim    assert(isSet() && "COFFSymbolRef points to nothing!");
345280031Sdim    return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols;
346280031Sdim  }
347280031Sdim
348280031Sdim  uint8_t getBaseType() const { return getType() & 0x0F; }
349280031Sdim
350280031Sdim  uint8_t getComplexType() const {
351280031Sdim    return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT;
352280031Sdim  }
353280031Sdim
354327952Sdim  template <typename T> const T *getAux() const {
355327952Sdim    return CS16 ? reinterpret_cast<const T *>(CS16 + 1)
356327952Sdim                : reinterpret_cast<const T *>(CS32 + 1);
357327952Sdim  }
358327952Sdim
359327952Sdim  const coff_aux_section_definition *getSectionDefinition() const {
360327952Sdim    if (!getNumberOfAuxSymbols() ||
361327952Sdim        getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC)
362327952Sdim      return nullptr;
363327952Sdim    return getAux<coff_aux_section_definition>();
364327952Sdim  }
365327952Sdim
366341825Sdim  const coff_aux_weak_external *getWeakExternal() const {
367341825Sdim    if (!getNumberOfAuxSymbols() ||
368341825Sdim        getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
369341825Sdim      return nullptr;
370341825Sdim    return getAux<coff_aux_weak_external>();
371341825Sdim  }
372341825Sdim
373288943Sdim  bool isAbsolute() const {
374288943Sdim    return getSectionNumber() == -1;
375288943Sdim  }
376288943Sdim
377280031Sdim  bool isExternal() const {
378280031Sdim    return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL;
379280031Sdim  }
380280031Sdim
381280031Sdim  bool isCommon() const {
382280031Sdim    return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
383280031Sdim           getValue() != 0;
384280031Sdim  }
385280031Sdim
386280031Sdim  bool isUndefined() const {
387280031Sdim    return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
388280031Sdim           getValue() == 0;
389280031Sdim  }
390280031Sdim
391280031Sdim  bool isWeakExternal() const {
392280031Sdim    return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
393280031Sdim  }
394280031Sdim
395276479Sdim  bool isFunctionDefinition() const {
396280031Sdim    return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
397276479Sdim           getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
398280031Sdim           !COFF::isReservedSectionNumber(getSectionNumber());
399234353Sdim  }
400234353Sdim
401276479Sdim  bool isFunctionLineInfo() const {
402280031Sdim    return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION;
403234353Sdim  }
404276479Sdim
405280031Sdim  bool isAnyUndefined() const {
406280031Sdim    return isUndefined() || isWeakExternal();
407276479Sdim  }
408276479Sdim
409276479Sdim  bool isFileRecord() const {
410280031Sdim    return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
411276479Sdim  }
412276479Sdim
413288943Sdim  bool isSection() const {
414288943Sdim    return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION;
415288943Sdim  }
416288943Sdim
417276479Sdim  bool isSectionDefinition() const {
418276479Sdim    // C++/CLI creates external ABS symbols for non-const appdomain globals.
419276479Sdim    // These are also followed by an auxiliary section definition.
420280031Sdim    bool isAppdomainGlobal =
421280031Sdim        getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
422280031Sdim        getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE;
423280031Sdim    bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC;
424280031Sdim    if (!getNumberOfAuxSymbols())
425280031Sdim      return false;
426276479Sdim    return isAppdomainGlobal || isOrdinarySection;
427276479Sdim  }
428276479Sdim
429276479Sdim  bool isCLRToken() const {
430280031Sdim    return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN;
431276479Sdim  }
432280031Sdim
433280031Sdimprivate:
434280031Sdim  bool isSet() const { return CS16 || CS32; }
435280031Sdim
436321369Sdim  const coff_symbol16 *CS16 = nullptr;
437321369Sdim  const coff_symbol32 *CS32 = nullptr;
438224133Sdim};
439224133Sdim
440224133Sdimstruct coff_section {
441280031Sdim  char Name[COFF::NameSize];
442224133Sdim  support::ulittle32_t VirtualSize;
443224133Sdim  support::ulittle32_t VirtualAddress;
444224133Sdim  support::ulittle32_t SizeOfRawData;
445224133Sdim  support::ulittle32_t PointerToRawData;
446224133Sdim  support::ulittle32_t PointerToRelocations;
447224133Sdim  support::ulittle32_t PointerToLinenumbers;
448224133Sdim  support::ulittle16_t NumberOfRelocations;
449224133Sdim  support::ulittle16_t NumberOfLinenumbers;
450224133Sdim  support::ulittle32_t Characteristics;
451276479Sdim
452276479Sdim  // Returns true if the actual number of relocations is stored in
453276479Sdim  // VirtualAddress field of the first relocation table entry.
454276479Sdim  bool hasExtendedRelocations() const {
455280031Sdim    return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) &&
456280031Sdim           NumberOfRelocations == UINT16_MAX;
457280031Sdim  }
458321369Sdim
459309124Sdim  uint32_t getAlignment() const {
460309124Sdim    // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to
461309124Sdim    // IMAGE_SCN_ALIGN_1BYTES.
462309124Sdim    if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD)
463309124Sdim      return 1;
464309124Sdim
465341825Sdim    // Bit [20:24] contains section alignment. 0 means use a default alignment
466341825Sdim    // of 16.
467309124Sdim    uint32_t Shift = (Characteristics >> 20) & 0xF;
468309124Sdim    if (Shift > 0)
469309124Sdim      return 1U << (Shift - 1);
470341825Sdim    return 16;
471309124Sdim  }
472224133Sdim};
473224133Sdim
474226633Sdimstruct coff_relocation {
475226633Sdim  support::ulittle32_t VirtualAddress;
476226633Sdim  support::ulittle32_t SymbolTableIndex;
477226633Sdim  support::ulittle16_t Type;
478226633Sdim};
479226633Sdim
480276479Sdimstruct coff_aux_function_definition {
481276479Sdim  support::ulittle32_t TagIndex;
482276479Sdim  support::ulittle32_t TotalSize;
483276479Sdim  support::ulittle32_t PointerToLinenumber;
484276479Sdim  support::ulittle32_t PointerToNextFunction;
485309124Sdim  char Unused1[2];
486276479Sdim};
487276479Sdim
488309124Sdimstatic_assert(sizeof(coff_aux_function_definition) == 18,
489309124Sdim              "auxiliary entry must be 18 bytes");
490309124Sdim
491276479Sdimstruct coff_aux_bf_and_ef_symbol {
492276479Sdim  char Unused1[4];
493276479Sdim  support::ulittle16_t Linenumber;
494276479Sdim  char Unused2[6];
495276479Sdim  support::ulittle32_t PointerToNextFunction;
496309124Sdim  char Unused3[2];
497276479Sdim};
498276479Sdim
499309124Sdimstatic_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18,
500309124Sdim              "auxiliary entry must be 18 bytes");
501309124Sdim
502261991Sdimstruct coff_aux_weak_external {
503261991Sdim  support::ulittle32_t TagIndex;
504261991Sdim  support::ulittle32_t Characteristics;
505309124Sdim  char Unused1[10];
506261991Sdim};
507261991Sdim
508309124Sdimstatic_assert(sizeof(coff_aux_weak_external) == 18,
509309124Sdim              "auxiliary entry must be 18 bytes");
510309124Sdim
511234353Sdimstruct coff_aux_section_definition {
512234353Sdim  support::ulittle32_t Length;
513234353Sdim  support::ulittle16_t NumberOfRelocations;
514234353Sdim  support::ulittle16_t NumberOfLinenumbers;
515234353Sdim  support::ulittle32_t CheckSum;
516280031Sdim  support::ulittle16_t NumberLowPart;
517280031Sdim  uint8_t              Selection;
518280031Sdim  uint8_t              Unused;
519280031Sdim  support::ulittle16_t NumberHighPart;
520280031Sdim  int32_t getNumber(bool IsBigObj) const {
521280031Sdim    uint32_t Number = static_cast<uint32_t>(NumberLowPart);
522280031Sdim    if (IsBigObj)
523280031Sdim      Number |= static_cast<uint32_t>(NumberHighPart) << 16;
524280031Sdim    return static_cast<int32_t>(Number);
525280031Sdim  }
526234353Sdim};
527234353Sdim
528309124Sdimstatic_assert(sizeof(coff_aux_section_definition) == 18,
529309124Sdim              "auxiliary entry must be 18 bytes");
530309124Sdim
531276479Sdimstruct coff_aux_clr_token {
532280031Sdim  uint8_t              AuxType;
533280031Sdim  uint8_t              Reserved;
534276479Sdim  support::ulittle32_t SymbolTableIndex;
535309124Sdim  char                 MBZ[12];
536276479Sdim};
537276479Sdim
538309124Sdimstatic_assert(sizeof(coff_aux_clr_token) == 18,
539309124Sdim              "auxiliary entry must be 18 bytes");
540309124Sdim
541288943Sdimstruct coff_import_header {
542288943Sdim  support::ulittle16_t Sig1;
543288943Sdim  support::ulittle16_t Sig2;
544288943Sdim  support::ulittle16_t Version;
545288943Sdim  support::ulittle16_t Machine;
546288943Sdim  support::ulittle32_t TimeDateStamp;
547288943Sdim  support::ulittle32_t SizeOfData;
548288943Sdim  support::ulittle16_t OrdinalHint;
549288943Sdim  support::ulittle16_t TypeInfo;
550321369Sdim
551288943Sdim  int getType() const { return TypeInfo & 0x3; }
552288943Sdim  int getNameType() const { return (TypeInfo >> 2) & 0x7; }
553288943Sdim};
554288943Sdim
555288943Sdimstruct coff_import_directory_table_entry {
556288943Sdim  support::ulittle32_t ImportLookupTableRVA;
557288943Sdim  support::ulittle32_t TimeDateStamp;
558288943Sdim  support::ulittle32_t ForwarderChain;
559288943Sdim  support::ulittle32_t NameRVA;
560288943Sdim  support::ulittle32_t ImportAddressTableRVA;
561321369Sdim
562314564Sdim  bool isNull() const {
563314564Sdim    return ImportLookupTableRVA == 0 && TimeDateStamp == 0 &&
564314564Sdim           ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0;
565314564Sdim  }
566288943Sdim};
567288943Sdim
568309124Sdimtemplate <typename IntTy>
569309124Sdimstruct coff_tls_directory {
570309124Sdim  IntTy StartAddressOfRawData;
571309124Sdim  IntTy EndAddressOfRawData;
572309124Sdim  IntTy AddressOfIndex;
573309124Sdim  IntTy AddressOfCallBacks;
574309124Sdim  support::ulittle32_t SizeOfZeroFill;
575309124Sdim  support::ulittle32_t Characteristics;
576321369Sdim
577309124Sdim  uint32_t getAlignment() const {
578309124Sdim    // Bit [20:24] contains section alignment.
579309124Sdim    uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
580309124Sdim    if (Shift > 0)
581309124Sdim      return 1U << (Shift - 1);
582309124Sdim    return 0;
583309124Sdim  }
584309124Sdim};
585309124Sdim
586321369Sdimusing coff_tls_directory32 = coff_tls_directory<support::little32_t>;
587321369Sdimusing coff_tls_directory64 = coff_tls_directory<support::little64_t>;
588309124Sdim
589321369Sdim/// Bits in control flow guard flags as we understand them.
590321369Sdimenum class coff_guard_flags : uint32_t {
591321369Sdim  CFInstrumented = 0x00000100,
592321369Sdim  HasFidTable = 0x00000400,
593321369Sdim  ProtectDelayLoadIAT = 0x00001000,
594321369Sdim  DelayLoadIATSection = 0x00002000, // Delay load in separate section
595321369Sdim  HasLongJmpTable = 0x00010000,
596321369Sdim  FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes
597321369Sdim};
598321369Sdim
599344779Sdimenum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 };
600344779Sdim
601321369Sdimstruct coff_load_config_code_integrity {
602321369Sdim  support::ulittle16_t Flags;
603321369Sdim  support::ulittle16_t Catalog;
604321369Sdim  support::ulittle32_t CatalogOffset;
605321369Sdim  support::ulittle32_t Reserved;
606321369Sdim};
607321369Sdim
608321369Sdim/// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32)
609276479Sdimstruct coff_load_configuration32 {
610321369Sdim  support::ulittle32_t Size;
611276479Sdim  support::ulittle32_t TimeDateStamp;
612276479Sdim  support::ulittle16_t MajorVersion;
613276479Sdim  support::ulittle16_t MinorVersion;
614276479Sdim  support::ulittle32_t GlobalFlagsClear;
615276479Sdim  support::ulittle32_t GlobalFlagsSet;
616276479Sdim  support::ulittle32_t CriticalSectionDefaultTimeout;
617276479Sdim  support::ulittle32_t DeCommitFreeBlockThreshold;
618276479Sdim  support::ulittle32_t DeCommitTotalFreeThreshold;
619276479Sdim  support::ulittle32_t LockPrefixTable;
620276479Sdim  support::ulittle32_t MaximumAllocationSize;
621276479Sdim  support::ulittle32_t VirtualMemoryThreshold;
622276479Sdim  support::ulittle32_t ProcessAffinityMask;
623276479Sdim  support::ulittle32_t ProcessHeapFlags;
624276479Sdim  support::ulittle16_t CSDVersion;
625321369Sdim  support::ulittle16_t DependentLoadFlags;
626276479Sdim  support::ulittle32_t EditList;
627276479Sdim  support::ulittle32_t SecurityCookie;
628276479Sdim  support::ulittle32_t SEHandlerTable;
629276479Sdim  support::ulittle32_t SEHandlerCount;
630321369Sdim
631321369Sdim  // Added in MSVC 2015 for /guard:cf.
632321369Sdim  support::ulittle32_t GuardCFCheckFunction;
633321369Sdim  support::ulittle32_t GuardCFCheckDispatch;
634321369Sdim  support::ulittle32_t GuardCFFunctionTable;
635321369Sdim  support::ulittle32_t GuardCFFunctionCount;
636321369Sdim  support::ulittle32_t GuardFlags; // coff_guard_flags
637321369Sdim
638321369Sdim  // Added in MSVC 2017
639321369Sdim  coff_load_config_code_integrity CodeIntegrity;
640321369Sdim  support::ulittle32_t GuardAddressTakenIatEntryTable;
641321369Sdim  support::ulittle32_t GuardAddressTakenIatEntryCount;
642321369Sdim  support::ulittle32_t GuardLongJumpTargetTable;
643321369Sdim  support::ulittle32_t GuardLongJumpTargetCount;
644321369Sdim  support::ulittle32_t DynamicValueRelocTable;
645321369Sdim  support::ulittle32_t CHPEMetadataPointer;
646321369Sdim  support::ulittle32_t GuardRFFailureRoutine;
647321369Sdim  support::ulittle32_t GuardRFFailureRoutineFunctionPointer;
648321369Sdim  support::ulittle32_t DynamicValueRelocTableOffset;
649321369Sdim  support::ulittle16_t DynamicValueRelocTableSection;
650321369Sdim  support::ulittle16_t Reserved2;
651321369Sdim  support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer;
652321369Sdim  support::ulittle32_t HotPatchTableOffset;
653276479Sdim};
654276479Sdim
655321369Sdim/// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64)
656288943Sdimstruct coff_load_configuration64 {
657321369Sdim  support::ulittle32_t Size;
658288943Sdim  support::ulittle32_t TimeDateStamp;
659288943Sdim  support::ulittle16_t MajorVersion;
660288943Sdim  support::ulittle16_t MinorVersion;
661288943Sdim  support::ulittle32_t GlobalFlagsClear;
662288943Sdim  support::ulittle32_t GlobalFlagsSet;
663288943Sdim  support::ulittle32_t CriticalSectionDefaultTimeout;
664321369Sdim  support::ulittle64_t DeCommitFreeBlockThreshold;
665321369Sdim  support::ulittle64_t DeCommitTotalFreeThreshold;
666321369Sdim  support::ulittle64_t LockPrefixTable;
667321369Sdim  support::ulittle64_t MaximumAllocationSize;
668321369Sdim  support::ulittle64_t VirtualMemoryThreshold;
669321369Sdim  support::ulittle64_t ProcessAffinityMask;
670288943Sdim  support::ulittle32_t ProcessHeapFlags;
671288943Sdim  support::ulittle16_t CSDVersion;
672321369Sdim  support::ulittle16_t DependentLoadFlags;
673321369Sdim  support::ulittle64_t EditList;
674288943Sdim  support::ulittle64_t SecurityCookie;
675288943Sdim  support::ulittle64_t SEHandlerTable;
676288943Sdim  support::ulittle64_t SEHandlerCount;
677321369Sdim
678321369Sdim  // Added in MSVC 2015 for /guard:cf.
679321369Sdim  support::ulittle64_t GuardCFCheckFunction;
680321369Sdim  support::ulittle64_t GuardCFCheckDispatch;
681321369Sdim  support::ulittle64_t GuardCFFunctionTable;
682321369Sdim  support::ulittle64_t GuardCFFunctionCount;
683321369Sdim  support::ulittle32_t GuardFlags;
684321369Sdim
685321369Sdim  // Added in MSVC 2017
686321369Sdim  coff_load_config_code_integrity CodeIntegrity;
687321369Sdim  support::ulittle64_t GuardAddressTakenIatEntryTable;
688321369Sdim  support::ulittle64_t GuardAddressTakenIatEntryCount;
689321369Sdim  support::ulittle64_t GuardLongJumpTargetTable;
690321369Sdim  support::ulittle64_t GuardLongJumpTargetCount;
691321369Sdim  support::ulittle64_t DynamicValueRelocTable;
692321369Sdim  support::ulittle64_t CHPEMetadataPointer;
693321369Sdim  support::ulittle64_t GuardRFFailureRoutine;
694321369Sdim  support::ulittle64_t GuardRFFailureRoutineFunctionPointer;
695321369Sdim  support::ulittle32_t DynamicValueRelocTableOffset;
696321369Sdim  support::ulittle16_t DynamicValueRelocTableSection;
697321369Sdim  support::ulittle16_t Reserved2;
698321369Sdim  support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer;
699321369Sdim  support::ulittle32_t HotPatchTableOffset;
700288943Sdim};
701288943Sdim
702276479Sdimstruct coff_runtime_function_x64 {
703276479Sdim  support::ulittle32_t BeginAddress;
704276479Sdim  support::ulittle32_t EndAddress;
705276479Sdim  support::ulittle32_t UnwindInformation;
706276479Sdim};
707276479Sdim
708280031Sdimstruct coff_base_reloc_block_header {
709280031Sdim  support::ulittle32_t PageRVA;
710280031Sdim  support::ulittle32_t BlockSize;
711280031Sdim};
712280031Sdim
713280031Sdimstruct coff_base_reloc_block_entry {
714280031Sdim  support::ulittle16_t Data;
715321369Sdim
716280031Sdim  int getType() const { return Data >> 12; }
717280031Sdim  int getOffset() const { return Data & ((1 << 12) - 1); }
718280031Sdim};
719280031Sdim
720321369Sdimstruct coff_resource_dir_entry {
721321369Sdim  union {
722321369Sdim    support::ulittle32_t NameOffset;
723321369Sdim    support::ulittle32_t ID;
724321369Sdim    uint32_t getNameOffset() const {
725321369Sdim      return maskTrailingOnes<uint32_t>(31) & NameOffset;
726321369Sdim    }
727321369Sdim    // Even though the PE/COFF spec doesn't mention this, the high bit of a name
728321369Sdim    // offset is set.
729321369Sdim    void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); }
730321369Sdim  } Identifier;
731321369Sdim  union {
732321369Sdim    support::ulittle32_t DataEntryOffset;
733321369Sdim    support::ulittle32_t SubdirOffset;
734321369Sdim
735321369Sdim    bool isSubDir() const { return SubdirOffset >> 31; }
736321369Sdim    uint32_t value() const {
737321369Sdim      return maskTrailingOnes<uint32_t>(31) & SubdirOffset;
738321369Sdim    }
739321369Sdim
740321369Sdim  } Offset;
741321369Sdim};
742321369Sdim
743321369Sdimstruct coff_resource_data_entry {
744321369Sdim  support::ulittle32_t DataRVA;
745321369Sdim  support::ulittle32_t DataSize;
746321369Sdim  support::ulittle32_t Codepage;
747321369Sdim  support::ulittle32_t Reserved;
748321369Sdim};
749321369Sdim
750321369Sdimstruct coff_resource_dir_table {
751321369Sdim  support::ulittle32_t Characteristics;
752321369Sdim  support::ulittle32_t TimeDateStamp;
753321369Sdim  support::ulittle16_t MajorVersion;
754321369Sdim  support::ulittle16_t MinorVersion;
755321369Sdim  support::ulittle16_t NumberOfNameEntries;
756321369Sdim  support::ulittle16_t NumberOfIDEntries;
757321369Sdim};
758321369Sdim
759327952Sdimstruct debug_h_header {
760327952Sdim  support::ulittle32_t Magic;
761327952Sdim  support::ulittle16_t Version;
762327952Sdim  support::ulittle16_t HashAlgorithm;
763327952Sdim};
764327952Sdim
765224133Sdimclass COFFObjectFile : public ObjectFile {
766224133Sdimprivate:
767261991Sdim  friend class ImportDirectoryEntryRef;
768276479Sdim  friend class ExportDirectoryEntryRef;
769261991Sdim  const coff_file_header *COFFHeader;
770280031Sdim  const coff_bigobj_file_header *COFFBigObjHeader;
771276479Sdim  const pe32_header *PE32Header;
772276479Sdim  const pe32plus_header *PE32PlusHeader;
773276479Sdim  const data_directory *DataDirectory;
774276479Sdim  const coff_section *SectionTable;
775280031Sdim  const coff_symbol16 *SymbolTable16;
776280031Sdim  const coff_symbol32 *SymbolTable32;
777276479Sdim  const char *StringTable;
778276479Sdim  uint32_t StringTableSize;
779314564Sdim  const coff_import_directory_table_entry *ImportDirectory;
780280031Sdim  const delay_import_directory_table_entry *DelayImportDirectory;
781280031Sdim  uint32_t NumberOfDelayImportDirectory;
782276479Sdim  const export_directory_table_entry *ExportDirectory;
783280031Sdim  const coff_base_reloc_block_header *BaseRelocHeader;
784280031Sdim  const coff_base_reloc_block_header *BaseRelocEnd;
785309124Sdim  const debug_directory *DebugDirectoryBegin;
786309124Sdim  const debug_directory *DebugDirectoryEnd;
787321369Sdim  // Either coff_load_configuration32 or coff_load_configuration64.
788327952Sdim  const void *LoadConfig = nullptr;
789224133Sdim
790276479Sdim  std::error_code getString(uint32_t offset, StringRef &Res) const;
791224133Sdim
792280031Sdim  template <typename coff_symbol_type>
793280031Sdim  const coff_symbol_type *toSymb(DataRefImpl Symb) const;
794276479Sdim  const coff_section *toSec(DataRefImpl Sec) const;
795276479Sdim  const coff_relocation *toRel(DataRefImpl Rel) const;
796224133Sdim
797276479Sdim  std::error_code initSymbolTablePtr();
798276479Sdim  std::error_code initImportTablePtr();
799280031Sdim  std::error_code initDelayImportTablePtr();
800276479Sdim  std::error_code initExportTablePtr();
801280031Sdim  std::error_code initBaseRelocPtr();
802309124Sdim  std::error_code initDebugDirectoryPtr();
803321369Sdim  std::error_code initLoadConfigPtr();
804261991Sdim
805280031Sdimpublic:
806280031Sdim  uintptr_t getSymbolTable() const {
807280031Sdim    if (SymbolTable16)
808280031Sdim      return reinterpret_cast<uintptr_t>(SymbolTable16);
809280031Sdim    if (SymbolTable32)
810280031Sdim      return reinterpret_cast<uintptr_t>(SymbolTable32);
811280031Sdim    return uintptr_t(0);
812280031Sdim  }
813321369Sdim
814280031Sdim  uint16_t getMachine() const {
815280031Sdim    if (COFFHeader)
816280031Sdim      return COFFHeader->Machine;
817280031Sdim    if (COFFBigObjHeader)
818280031Sdim      return COFFBigObjHeader->Machine;
819280031Sdim    llvm_unreachable("no COFF header!");
820280031Sdim  }
821321369Sdim
822280031Sdim  uint16_t getSizeOfOptionalHeader() const {
823280031Sdim    if (COFFHeader)
824280031Sdim      return COFFHeader->isImportLibrary() ? 0
825280031Sdim                                           : COFFHeader->SizeOfOptionalHeader;
826280031Sdim    // bigobj doesn't have this field.
827280031Sdim    if (COFFBigObjHeader)
828280031Sdim      return 0;
829280031Sdim    llvm_unreachable("no COFF header!");
830280031Sdim  }
831321369Sdim
832280031Sdim  uint16_t getCharacteristics() const {
833280031Sdim    if (COFFHeader)
834280031Sdim      return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics;
835280031Sdim    // bigobj doesn't have characteristics to speak of,
836280031Sdim    // editbin will silently lie to you if you attempt to set any.
837280031Sdim    if (COFFBigObjHeader)
838280031Sdim      return 0;
839280031Sdim    llvm_unreachable("no COFF header!");
840280031Sdim  }
841321369Sdim
842280031Sdim  uint32_t getTimeDateStamp() const {
843280031Sdim    if (COFFHeader)
844280031Sdim      return COFFHeader->TimeDateStamp;
845280031Sdim    if (COFFBigObjHeader)
846280031Sdim      return COFFBigObjHeader->TimeDateStamp;
847280031Sdim    llvm_unreachable("no COFF header!");
848280031Sdim  }
849321369Sdim
850280031Sdim  uint32_t getNumberOfSections() const {
851280031Sdim    if (COFFHeader)
852280031Sdim      return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections;
853280031Sdim    if (COFFBigObjHeader)
854280031Sdim      return COFFBigObjHeader->NumberOfSections;
855280031Sdim    llvm_unreachable("no COFF header!");
856280031Sdim  }
857321369Sdim
858280031Sdim  uint32_t getPointerToSymbolTable() const {
859280031Sdim    if (COFFHeader)
860280031Sdim      return COFFHeader->isImportLibrary() ? 0
861280031Sdim                                           : COFFHeader->PointerToSymbolTable;
862280031Sdim    if (COFFBigObjHeader)
863280031Sdim      return COFFBigObjHeader->PointerToSymbolTable;
864280031Sdim    llvm_unreachable("no COFF header!");
865280031Sdim  }
866321369Sdim
867314564Sdim  uint32_t getRawNumberOfSymbols() const {
868280031Sdim    if (COFFHeader)
869280031Sdim      return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols;
870280031Sdim    if (COFFBigObjHeader)
871280031Sdim      return COFFBigObjHeader->NumberOfSymbols;
872280031Sdim    llvm_unreachable("no COFF header!");
873280031Sdim  }
874321369Sdim
875314564Sdim  uint32_t getNumberOfSymbols() const {
876314564Sdim    if (!SymbolTable16 && !SymbolTable32)
877314564Sdim      return 0;
878314564Sdim    return getRawNumberOfSymbols();
879314564Sdim  }
880321369Sdim
881321369Sdim  const coff_load_configuration32 *getLoadConfig32() const {
882321369Sdim    assert(!is64());
883321369Sdim    return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig);
884321369Sdim  }
885321369Sdim
886321369Sdim  const coff_load_configuration64 *getLoadConfig64() const {
887321369Sdim    assert(is64());
888321369Sdim    return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig);
889321369Sdim  }
890344779Sdim  StringRef getRelocationTypeName(uint16_t Type) const;
891321369Sdim
892224133Sdimprotected:
893276479Sdim  void moveSymbolNext(DataRefImpl &Symb) const override;
894309124Sdim  Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
895309124Sdim  Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
896314564Sdim  uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
897288943Sdim  uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
898288943Sdim  uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
899276479Sdim  uint32_t getSymbolFlags(DataRefImpl Symb) const override;
900309124Sdim  Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
901309124Sdim  Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
902276479Sdim  void moveSectionNext(DataRefImpl &Sec) const override;
903353358Sdim  Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
904280031Sdim  uint64_t getSectionAddress(DataRefImpl Sec) const override;
905321369Sdim  uint64_t getSectionIndex(DataRefImpl Sec) const override;
906280031Sdim  uint64_t getSectionSize(DataRefImpl Sec) const override;
907353358Sdim  Expected<ArrayRef<uint8_t>>
908353358Sdim  getSectionContents(DataRefImpl Sec) const override;
909280031Sdim  uint64_t getSectionAlignment(DataRefImpl Sec) const override;
910309124Sdim  bool isSectionCompressed(DataRefImpl Sec) const override;
911280031Sdim  bool isSectionText(DataRefImpl Sec) const override;
912280031Sdim  bool isSectionData(DataRefImpl Sec) const override;
913280031Sdim  bool isSectionBSS(DataRefImpl Sec) const override;
914280031Sdim  bool isSectionVirtual(DataRefImpl Sec) const override;
915276479Sdim  relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
916276479Sdim  relocation_iterator section_rel_end(DataRefImpl Sec) const override;
917224133Sdim
918276479Sdim  void moveRelocationNext(DataRefImpl &Rel) const override;
919288943Sdim  uint64_t getRelocationOffset(DataRefImpl Rel) const override;
920276479Sdim  symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
921288943Sdim  uint64_t getRelocationType(DataRefImpl Rel) const override;
922288943Sdim  void getRelocationTypeName(DataRefImpl Rel,
923288943Sdim                             SmallVectorImpl<char> &Result) const override;
924224133Sdim
925224133Sdimpublic:
926280031Sdim  COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
927321369Sdim
928314564Sdim  basic_symbol_iterator symbol_begin() const override;
929314564Sdim  basic_symbol_iterator symbol_end() const override;
930276479Sdim  section_iterator section_begin() const override;
931276479Sdim  section_iterator section_end() const override;
932224133Sdim
933276479Sdim  const coff_section *getCOFFSection(const SectionRef &Section) const;
934280031Sdim  COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const;
935280031Sdim  COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const;
936276479Sdim  const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
937288943Sdim  unsigned getSectionID(SectionRef Sec) const;
938288943Sdim  unsigned getSymbolSectionID(SymbolRef Sym) const;
939261991Sdim
940276479Sdim  uint8_t getBytesInAddress() const override;
941276479Sdim  StringRef getFileFormatName() const override;
942327952Sdim  Triple::ArchType getArch() const override;
943341825Sdim  Expected<uint64_t> getStartAddress() const override;
944309124Sdim  SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
945234353Sdim
946261991Sdim  import_directory_iterator import_directory_begin() const;
947261991Sdim  import_directory_iterator import_directory_end() const;
948280031Sdim  delay_import_directory_iterator delay_import_directory_begin() const;
949280031Sdim  delay_import_directory_iterator delay_import_directory_end() const;
950276479Sdim  export_directory_iterator export_directory_begin() const;
951276479Sdim  export_directory_iterator export_directory_end() const;
952280031Sdim  base_reloc_iterator base_reloc_begin() const;
953280031Sdim  base_reloc_iterator base_reloc_end() const;
954309124Sdim  const debug_directory *debug_directory_begin() const {
955309124Sdim    return DebugDirectoryBegin;
956309124Sdim  }
957309124Sdim  const debug_directory *debug_directory_end() const {
958309124Sdim    return DebugDirectoryEnd;
959309124Sdim  }
960261991Sdim
961280031Sdim  iterator_range<import_directory_iterator> import_directories() const;
962280031Sdim  iterator_range<delay_import_directory_iterator>
963280031Sdim      delay_import_directories() const;
964280031Sdim  iterator_range<export_directory_iterator> export_directories() const;
965280031Sdim  iterator_range<base_reloc_iterator> base_relocs() const;
966309124Sdim  iterator_range<const debug_directory *> debug_directories() const {
967309124Sdim    return make_range(debug_directory_begin(), debug_directory_end());
968309124Sdim  }
969280031Sdim
970280031Sdim  const dos_header *getDOSHeader() const {
971280031Sdim    if (!PE32Header && !PE32PlusHeader)
972280031Sdim      return nullptr;
973280031Sdim    return reinterpret_cast<const dos_header *>(base());
974280031Sdim  }
975360784Sdim
976360784Sdim  const coff_file_header *getCOFFHeader() const { return COFFHeader; }
977360784Sdim  const coff_bigobj_file_header *getCOFFBigObjHeader() const {
978360784Sdim    return COFFBigObjHeader;
979360784Sdim  }
980360784Sdim  const pe32_header *getPE32Header() const { return PE32Header; }
981360784Sdim  const pe32plus_header *getPE32PlusHeader() const { return PE32PlusHeader; }
982360784Sdim
983276479Sdim  std::error_code getDataDirectory(uint32_t index,
984276479Sdim                                   const data_directory *&Res) const;
985276479Sdim  std::error_code getSection(int32_t index, const coff_section *&Res) const;
986341825Sdim  std::error_code getSection(StringRef SectionName,
987341825Sdim                             const coff_section *&Res) const;
988321369Sdim
989280031Sdim  template <typename coff_symbol_type>
990280031Sdim  std::error_code getSymbol(uint32_t Index,
991280031Sdim                            const coff_symbol_type *&Res) const {
992280031Sdim    if (Index >= getNumberOfSymbols())
993280031Sdim      return object_error::parse_failed;
994280031Sdim
995280031Sdim    Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
996288943Sdim    return std::error_code();
997280031Sdim  }
998327952Sdim  Expected<COFFSymbolRef> getSymbol(uint32_t index) const {
999280031Sdim    if (SymbolTable16) {
1000280031Sdim      const coff_symbol16 *Symb = nullptr;
1001280031Sdim      if (std::error_code EC = getSymbol(index, Symb))
1002327952Sdim        return errorCodeToError(EC);
1003280031Sdim      return COFFSymbolRef(Symb);
1004280031Sdim    }
1005280031Sdim    if (SymbolTable32) {
1006280031Sdim      const coff_symbol32 *Symb = nullptr;
1007280031Sdim      if (std::error_code EC = getSymbol(index, Symb))
1008327952Sdim        return errorCodeToError(EC);
1009280031Sdim      return COFFSymbolRef(Symb);
1010280031Sdim    }
1011327952Sdim    return errorCodeToError(object_error::parse_failed);
1012280031Sdim  }
1013321369Sdim
1014234353Sdim  template <typename T>
1015276479Sdim  std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
1016327952Sdim    Expected<COFFSymbolRef> S = getSymbol(index);
1017327952Sdim    if (Error E = S.takeError())
1018327952Sdim      return errorToErrorCode(std::move(E));
1019327952Sdim    Res = reinterpret_cast<const T *>(S->getRawPtr());
1020288943Sdim    return std::error_code();
1021234353Sdim  }
1022321369Sdim
1023280031Sdim  std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
1024288943Sdim  std::error_code getSymbolName(const coff_symbol_generic *Symbol,
1025288943Sdim                                StringRef &Res) const;
1026239462Sdim
1027280031Sdim  ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
1028280031Sdim
1029344779Sdim  uint32_t getSymbolIndex(COFFSymbolRef Symbol) const;
1030344779Sdim
1031280031Sdim  size_t getSymbolTableEntrySize() const {
1032280031Sdim    if (COFFHeader)
1033280031Sdim      return sizeof(coff_symbol16);
1034280031Sdim    if (COFFBigObjHeader)
1035280031Sdim      return sizeof(coff_symbol32);
1036280031Sdim    llvm_unreachable("null symbol table pointer!");
1037280031Sdim  }
1038280031Sdim
1039341825Sdim  ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const;
1040288943Sdim
1041353358Sdim  Expected<StringRef> getSectionName(const coff_section *Sec) const;
1042280031Sdim  uint64_t getSectionSize(const coff_section *Sec) const;
1043353358Sdim  Error getSectionContents(const coff_section *Sec,
1044353358Sdim                           ArrayRef<uint8_t> &Res) const;
1045234353Sdim
1046296417Sdim  uint64_t getImageBase() const;
1047276479Sdim  std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
1048276479Sdim  std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
1049309124Sdim
1050309124Sdim  /// Given an RVA base and size, returns a valid array of bytes or an error
1051309124Sdim  /// code if the RVA and size is not contained completely within a valid
1052309124Sdim  /// section.
1053309124Sdim  std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
1054309124Sdim                                       ArrayRef<uint8_t> &Contents) const;
1055309124Sdim
1056276479Sdim  std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
1057276479Sdim                              StringRef &Name) const;
1058261991Sdim
1059309124Sdim  /// Get PDB information out of a codeview debug directory entry.
1060309124Sdim  std::error_code getDebugPDBInfo(const debug_directory *DebugDir,
1061314564Sdim                                  const codeview::DebugInfo *&Info,
1062309124Sdim                                  StringRef &PDBFileName) const;
1063309124Sdim
1064309124Sdim  /// Get PDB information from an executable. If the information is not present,
1065309124Sdim  /// Info will be set to nullptr and PDBFileName will be empty. An error is
1066309124Sdim  /// returned only on corrupt object files. Convenience accessor that can be
1067309124Sdim  /// used if the debug directory is not already handy.
1068314564Sdim  std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info,
1069309124Sdim                                  StringRef &PDBFileName) const;
1070309124Sdim
1071280031Sdim  bool isRelocatableObject() const override;
1072280031Sdim  bool is64() const { return PE32PlusHeader; }
1073280031Sdim
1074344779Sdim  StringRef mapDebugSectionName(StringRef Name) const override;
1075344779Sdim
1076321369Sdim  static bool classof(const Binary *v) { return v->isCOFF(); }
1077224133Sdim};
1078224133Sdim
1079261991Sdim// The iterator for the import directory table.
1080261991Sdimclass ImportDirectoryEntryRef {
1081261991Sdimpublic:
1082321369Sdim  ImportDirectoryEntryRef() = default;
1083314564Sdim  ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table,
1084314564Sdim                          uint32_t I, const COFFObjectFile *Owner)
1085276479Sdim      : ImportTable(Table), Index(I), OwningObject(Owner) {}
1086224133Sdim
1087261991Sdim  bool operator==(const ImportDirectoryEntryRef &Other) const;
1088276479Sdim  void moveNext();
1089280031Sdim
1090280031Sdim  imported_symbol_iterator imported_symbol_begin() const;
1091280031Sdim  imported_symbol_iterator imported_symbol_end() const;
1092280031Sdim  iterator_range<imported_symbol_iterator> imported_symbols() const;
1093280031Sdim
1094314564Sdim  imported_symbol_iterator lookup_table_begin() const;
1095314564Sdim  imported_symbol_iterator lookup_table_end() const;
1096314564Sdim  iterator_range<imported_symbol_iterator> lookup_table_symbols() const;
1097314564Sdim
1098276479Sdim  std::error_code getName(StringRef &Result) const;
1099280031Sdim  std::error_code getImportLookupTableRVA(uint32_t &Result) const;
1100280031Sdim  std::error_code getImportAddressTableRVA(uint32_t &Result) const;
1101261991Sdim
1102276479Sdim  std::error_code
1103314564Sdim  getImportTableEntry(const coff_import_directory_table_entry *&Result) const;
1104261991Sdim
1105261991Sdimprivate:
1106314564Sdim  const coff_import_directory_table_entry *ImportTable;
1107276479Sdim  uint32_t Index;
1108321369Sdim  const COFFObjectFile *OwningObject = nullptr;
1109261991Sdim};
1110276479Sdim
1111280031Sdimclass DelayImportDirectoryEntryRef {
1112280031Sdimpublic:
1113321369Sdim  DelayImportDirectoryEntryRef() = default;
1114280031Sdim  DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
1115280031Sdim                               uint32_t I, const COFFObjectFile *Owner)
1116280031Sdim      : Table(T), Index(I), OwningObject(Owner) {}
1117280031Sdim
1118280031Sdim  bool operator==(const DelayImportDirectoryEntryRef &Other) const;
1119280031Sdim  void moveNext();
1120280031Sdim
1121280031Sdim  imported_symbol_iterator imported_symbol_begin() const;
1122280031Sdim  imported_symbol_iterator imported_symbol_end() const;
1123280031Sdim  iterator_range<imported_symbol_iterator> imported_symbols() const;
1124280031Sdim
1125280031Sdim  std::error_code getName(StringRef &Result) const;
1126280031Sdim  std::error_code getDelayImportTable(
1127280031Sdim      const delay_import_directory_table_entry *&Result) const;
1128280031Sdim  std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const;
1129280031Sdim
1130280031Sdimprivate:
1131280031Sdim  const delay_import_directory_table_entry *Table;
1132280031Sdim  uint32_t Index;
1133321369Sdim  const COFFObjectFile *OwningObject = nullptr;
1134280031Sdim};
1135280031Sdim
1136276479Sdim// The iterator for the export directory table entry.
1137276479Sdimclass ExportDirectoryEntryRef {
1138276479Sdimpublic:
1139321369Sdim  ExportDirectoryEntryRef() = default;
1140276479Sdim  ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I,
1141276479Sdim                          const COFFObjectFile *Owner)
1142276479Sdim      : ExportTable(Table), Index(I), OwningObject(Owner) {}
1143276479Sdim
1144276479Sdim  bool operator==(const ExportDirectoryEntryRef &Other) const;
1145276479Sdim  void moveNext();
1146276479Sdim
1147276479Sdim  std::error_code getDllName(StringRef &Result) const;
1148276479Sdim  std::error_code getOrdinalBase(uint32_t &Result) const;
1149276479Sdim  std::error_code getOrdinal(uint32_t &Result) const;
1150276479Sdim  std::error_code getExportRVA(uint32_t &Result) const;
1151276479Sdim  std::error_code getSymbolName(StringRef &Result) const;
1152276479Sdim
1153296417Sdim  std::error_code isForwarder(bool &Result) const;
1154296417Sdim  std::error_code getForwardTo(StringRef &Result) const;
1155296417Sdim
1156276479Sdimprivate:
1157276479Sdim  const export_directory_table_entry *ExportTable;
1158276479Sdim  uint32_t Index;
1159321369Sdim  const COFFObjectFile *OwningObject = nullptr;
1160276479Sdim};
1161280031Sdim
1162280031Sdimclass ImportedSymbolRef {
1163280031Sdimpublic:
1164321369Sdim  ImportedSymbolRef() = default;
1165280031Sdim  ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
1166280031Sdim                    const COFFObjectFile *Owner)
1167280031Sdim      : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
1168280031Sdim  ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I,
1169280031Sdim                    const COFFObjectFile *Owner)
1170280031Sdim      : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {}
1171280031Sdim
1172280031Sdim  bool operator==(const ImportedSymbolRef &Other) const;
1173280031Sdim  void moveNext();
1174280031Sdim
1175280031Sdim  std::error_code getSymbolName(StringRef &Result) const;
1176309124Sdim  std::error_code isOrdinal(bool &Result) const;
1177280031Sdim  std::error_code getOrdinal(uint16_t &Result) const;
1178309124Sdim  std::error_code getHintNameRVA(uint32_t &Result) const;
1179280031Sdim
1180280031Sdimprivate:
1181280031Sdim  const import_lookup_table_entry32 *Entry32;
1182280031Sdim  const import_lookup_table_entry64 *Entry64;
1183280031Sdim  uint32_t Index;
1184321369Sdim  const COFFObjectFile *OwningObject = nullptr;
1185280031Sdim};
1186280031Sdim
1187280031Sdimclass BaseRelocRef {
1188280031Sdimpublic:
1189321369Sdim  BaseRelocRef() = default;
1190280031Sdim  BaseRelocRef(const coff_base_reloc_block_header *Header,
1191280031Sdim               const COFFObjectFile *Owner)
1192327952Sdim      : Header(Header), Index(0) {}
1193280031Sdim
1194280031Sdim  bool operator==(const BaseRelocRef &Other) const;
1195280031Sdim  void moveNext();
1196280031Sdim
1197280031Sdim  std::error_code getType(uint8_t &Type) const;
1198280031Sdim  std::error_code getRVA(uint32_t &Result) const;
1199280031Sdim
1200280031Sdimprivate:
1201280031Sdim  const coff_base_reloc_block_header *Header;
1202280031Sdim  uint32_t Index;
1203280031Sdim};
1204280031Sdim
1205321369Sdimclass ResourceSectionRef {
1206321369Sdimpublic:
1207321369Sdim  ResourceSectionRef() = default;
1208321369Sdim  explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {}
1209321369Sdim
1210360784Sdim  Error load(const COFFObjectFile *O);
1211360784Sdim  Error load(const COFFObjectFile *O, const SectionRef &S);
1212360784Sdim
1213327952Sdim  Expected<ArrayRef<UTF16>>
1214327952Sdim  getEntryNameString(const coff_resource_dir_entry &Entry);
1215327952Sdim  Expected<const coff_resource_dir_table &>
1216321369Sdim  getEntrySubDir(const coff_resource_dir_entry &Entry);
1217360784Sdim  Expected<const coff_resource_data_entry &>
1218360784Sdim  getEntryData(const coff_resource_dir_entry &Entry);
1219327952Sdim  Expected<const coff_resource_dir_table &> getBaseTable();
1220360784Sdim  Expected<const coff_resource_dir_entry &>
1221360784Sdim  getTableEntry(const coff_resource_dir_table &Table, uint32_t Index);
1222321369Sdim
1223360784Sdim  Expected<StringRef> getContents(const coff_resource_data_entry &Entry);
1224360784Sdim
1225321369Sdimprivate:
1226321369Sdim  BinaryByteStream BBS;
1227321369Sdim
1228360784Sdim  SectionRef Section;
1229360784Sdim  const COFFObjectFile *Obj;
1230360784Sdim
1231360784Sdim  std::vector<const coff_relocation *> Relocs;
1232360784Sdim
1233327952Sdim  Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
1234360784Sdim  Expected<const coff_resource_dir_entry &>
1235360784Sdim  getTableEntryAtOffset(uint32_t Offset);
1236360784Sdim  Expected<const coff_resource_data_entry &>
1237360784Sdim  getDataEntryAtOffset(uint32_t Offset);
1238327952Sdim  Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
1239321369Sdim};
1240321369Sdim
1241309124Sdim// Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
1242309124Sdimstruct FpoData {
1243309124Sdim  support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
1244309124Sdim  support::ulittle32_t Size;   // cbProcSize: # bytes in function
1245309124Sdim  support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4
1246309124Sdim  support::ulittle16_t NumParams; // cdwParams: # bytes in params/4
1247309124Sdim  support::ulittle16_t Attributes;
1248309124Sdim
1249309124Sdim  // cbProlog: # bytes in prolog
1250309124Sdim  int getPrologSize() const { return Attributes & 0xF; }
1251309124Sdim
1252309124Sdim  // cbRegs: # regs saved
1253309124Sdim  int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; }
1254309124Sdim
1255309124Sdim  // fHasSEH: true if seh is func
1256309124Sdim  bool hasSEH() const { return (Attributes >> 9) & 1; }
1257309124Sdim
1258309124Sdim  // fUseBP: true if EBP has been allocated
1259309124Sdim  bool useBP() const { return (Attributes >> 10) & 1; }
1260309124Sdim
1261309124Sdim  // cbFrame: frame pointer
1262344779Sdim  frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); }
1263309124Sdim};
1264309124Sdim
1265261991Sdim} // end namespace object
1266321369Sdim
1267261991Sdim} // end namespace llvm
1268261991Sdim
1269321369Sdim#endif // LLVM_OBJECT_COFF_H
1270