Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Object/COFFObjectFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file declares the COFFObjectFile class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/ADT/ArrayRef.h"
14
#include "llvm/ADT/StringRef.h"
15
#include "llvm/ADT/Triple.h"
16
#include "llvm/ADT/iterator_range.h"
17
#include "llvm/BinaryFormat/COFF.h"
18
#include "llvm/Object/Binary.h"
19
#include "llvm/Object/COFF.h"
20
#include "llvm/Object/Error.h"
21
#include "llvm/Object/ObjectFile.h"
22
#include "llvm/Support/BinaryStreamReader.h"
23
#include "llvm/Support/Endian.h"
24
#include "llvm/Support/Error.h"
25
#include "llvm/Support/ErrorHandling.h"
26
#include "llvm/Support/MathExtras.h"
27
#include "llvm/Support/MemoryBuffer.h"
28
#include <algorithm>
29
#include <cassert>
30
#include <cstddef>
31
#include <cstdint>
32
#include <cstring>
33
#include <limits>
34
#include <memory>
35
#include <system_error>
36
37
using namespace llvm;
38
using namespace object;
39
40
using support::ulittle16_t;
41
using support::ulittle32_t;
42
using support::ulittle64_t;
43
using support::little16_t;
44
45
// Returns false if size is greater than the buffer size. And sets ec.
46
5.09k
static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
47
5.09k
  if (M.getBufferSize() < Size) {
48
8
    EC = object_error::unexpected_eof;
49
8
    return false;
50
8
  }
51
5.08k
  return true;
52
5.08k
}
53
54
// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
55
// Returns unexpected_eof if error.
56
template <typename T>
57
static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
58
                                 const void *Ptr,
59
12.3k
                                 const uint64_t Size = sizeof(T)) {
60
12.3k
  uintptr_t Addr = uintptr_t(Ptr);
61
12.3k
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
12.3k
  Obj = reinterpret_cast<const T *>(Addr);
64
12.3k
  return std::error_code();
65
12.3k
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::coff_relocation>(llvm::object::coff_relocation const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
6
                                 const uint64_t Size = sizeof(T)) {
60
6
  uintptr_t Addr = uintptr_t(Ptr);
61
6
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
6
  Obj = reinterpret_cast<const T *>(Addr);
64
6
  return std::error_code();
65
6
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> > >(llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> > const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
2.12k
                                 const uint64_t Size = sizeof(T)) {
60
2.12k
  uintptr_t Addr = uintptr_t(Ptr);
61
2.12k
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
2.12k
  Obj = reinterpret_cast<const T *>(Addr);
64
2.12k
  return std::error_code();
65
2.12k
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> > >(llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> > const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
5
                                 const uint64_t Size = sizeof(T)) {
60
5
  uintptr_t Addr = uintptr_t(Ptr);
61
5
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
5
  Obj = reinterpret_cast<const T *>(Addr);
64
5
  return std::error_code();
65
5
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> >(llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
2.13k
                                 const uint64_t Size = sizeof(T)) {
60
2.13k
  uintptr_t Addr = uintptr_t(Ptr);
61
2.13k
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
2.13k
  Obj = reinterpret_cast<const T *>(Addr);
64
2.13k
  return std::error_code();
65
2.13k
}
COFFObjectFile.cpp:std::__1::error_code getObject<char>(char const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
2.13k
                                 const uint64_t Size = sizeof(T)) {
60
2.13k
  uintptr_t Addr = uintptr_t(Ptr);
61
2.13k
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
2.13k
  Obj = reinterpret_cast<const T *>(Addr);
64
2.13k
  return std::error_code();
65
2.13k
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::coff_file_header>(llvm::object::coff_file_header const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
2.54k
                                 const uint64_t Size = sizeof(T)) {
60
2.54k
  uintptr_t Addr = uintptr_t(Ptr);
61
2.54k
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
2.54k
  Obj = reinterpret_cast<const T *>(Addr);
64
2.54k
  return std::error_code();
65
2.54k
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::coff_bigobj_file_header>(llvm::object::coff_bigobj_file_header const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
5
                                 const uint64_t Size = sizeof(T)) {
60
5
  uintptr_t Addr = uintptr_t(Ptr);
61
5
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
5
  Obj = reinterpret_cast<const T *>(Addr);
64
5
  return std::error_code();
65
5
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::pe32_header>(llvm::object::pe32_header const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
410
                                 const uint64_t Size = sizeof(T)) {
60
410
  uintptr_t Addr = uintptr_t(Ptr);
61
410
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
410
  Obj = reinterpret_cast<const T *>(Addr);
64
410
  return std::error_code();
65
410
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::data_directory>(llvm::object::data_directory const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
410
                                 const uint64_t Size = sizeof(T)) {
60
410
  uintptr_t Addr = uintptr_t(Ptr);
61
410
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
410
  Obj = reinterpret_cast<const T *>(Addr);
64
410
  return std::error_code();
65
410
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::coff_section>(llvm::object::coff_section const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
2.54k
                                 const uint64_t Size = sizeof(T)) {
60
2.54k
  uintptr_t Addr = uintptr_t(Ptr);
61
2.54k
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
2.54k
  Obj = reinterpret_cast<const T *>(Addr);
64
2.54k
  return std::error_code();
65
2.54k
}
COFFObjectFile.cpp:std::__1::error_code getObject<llvm::object::coff_import_directory_table_entry>(llvm::object::coff_import_directory_table_entry const*&, llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
59
4
                                 const uint64_t Size = sizeof(T)) {
60
4
  uintptr_t Addr = uintptr_t(Ptr);
61
4
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62
0
    return EC;
63
4
  Obj = reinterpret_cast<const T *>(Addr);
64
4
  return std::error_code();
65
4
}
66
67
// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
68
// prefixed slashes.
69
1
static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
70
1
  assert(Str.size() <= 6 && "String too long, possible overflow.");
71
1
  if (Str.size() > 6)
72
0
    return true;
73
1
74
1
  uint64_t Value = 0;
75
7
  while (!Str.empty()) {
76
6
    unsigned CharVal;
77
6
    if (Str[0] >= 'A' && 
Str[0] <= 'Z'5
) // 0..25
78
3
      CharVal = Str[0] - 'A';
79
3
    else if (Str[0] >= 'a' && 
Str[0] <= 'z'2
) // 26..51
80
2
      CharVal = Str[0] - 'a' + 26;
81
1
    else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
82
1
      CharVal = Str[0] - '0' + 52;
83
0
    else if (Str[0] == '+') // 62
84
0
      CharVal = 62;
85
0
    else if (Str[0] == '/') // 63
86
0
      CharVal = 63;
87
0
    else
88
0
      return true;
89
6
90
6
    Value = (Value * 64) + CharVal;
91
6
    Str = Str.substr(1);
92
6
  }
93
1
94
1
  if (Value > std::numeric_limits<uint32_t>::max())
95
0
    return true;
96
1
97
1
  Result = static_cast<uint32_t>(Value);
98
1
  return false;
99
1
}
100
101
template <typename coff_symbol_type>
102
21.2k
const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
103
21.2k
  const coff_symbol_type *Addr =
104
21.2k
      reinterpret_cast<const coff_symbol_type *>(Ref.p);
105
21.2k
106
21.2k
  assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
107
#ifndef NDEBUG
108
  // Verify that the symbol points to a valid entry in the symbol table.
109
  uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
110
111
  assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
112
         "Symbol did not point to the beginning of a symbol");
113
#endif
114
115
21.2k
  return Addr;
116
21.2k
}
llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> > const* llvm::object::COFFObjectFile::toSymb<llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> > >(llvm::object::DataRefImpl) const
Line
Count
Source
102
21.2k
const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
103
21.2k
  const coff_symbol_type *Addr =
104
21.2k
      reinterpret_cast<const coff_symbol_type *>(Ref.p);
105
21.2k
106
21.2k
  assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
107
#ifndef NDEBUG
108
  // Verify that the symbol points to a valid entry in the symbol table.
109
  uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
110
111
  assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
112
         "Symbol did not point to the beginning of a symbol");
113
#endif
114
115
21.2k
  return Addr;
116
21.2k
}
llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> > const* llvm::object::COFFObjectFile::toSymb<llvm::object::coff_symbol<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> > >(llvm::object::DataRefImpl) const
Line
Count
Source
102
8
const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
103
8
  const coff_symbol_type *Addr =
104
8
      reinterpret_cast<const coff_symbol_type *>(Ref.p);
105
8
106
8
  assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
107
#ifndef NDEBUG
108
  // Verify that the symbol points to a valid entry in the symbol table.
109
  uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
110
111
  assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
112
         "Symbol did not point to the beginning of a symbol");
113
#endif
114
115
8
  return Addr;
116
8
}
117
118
335k
const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
119
335k
  const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
120
335k
121
#ifndef NDEBUG
122
  // Verify that the section points to a valid entry in the section table.
123
  if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
124
    report_fatal_error("Section was outside of section table.");
125
126
  uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
127
  assert(Offset % sizeof(coff_section) == 0 &&
128
         "Section did not point to the beginning of a section");
129
#endif
130
131
335k
  return Addr;
132
335k
}
133
134
4.96k
void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
135
4.96k
  auto End = reinterpret_cast<uintptr_t>(StringTable);
136
4.96k
  if (SymbolTable16) {
137
4.96k
    const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
138
4.96k
    Symb += 1 + Symb->NumberOfAuxSymbols;
139
4.96k
    Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
140
4.96k
  } else 
if (4
SymbolTable324
) {
141
4
    const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
142
4
    Symb += 1 + Symb->NumberOfAuxSymbols;
143
4
    Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
144
4
  } else {
145
0
    llvm_unreachable("no symbol table pointer!");
146
0
  }
147
4.96k
}
148
149
3.56k
Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
150
3.56k
  COFFSymbolRef Symb = getCOFFSymbol(Ref);
151
3.56k
  StringRef Result;
152
3.56k
  if (std::error_code EC = getSymbolName(Symb, Result))
153
0
    return errorCodeToError(EC);
154
3.56k
  return Result;
155
3.56k
}
156
157
1.00k
uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
158
1.00k
  return getCOFFSymbol(Ref).getValue();
159
1.00k
}
160
161
0
uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
162
0
  // MSVC/link.exe seems to align symbols to the next-power-of-2
163
0
  // up to 32 bytes.
164
0
  COFFSymbolRef Symb = getCOFFSymbol(Ref);
165
0
  return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
166
0
}
167
168
862
Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
169
862
  uint64_t Result = getSymbolValue(Ref);
170
862
  COFFSymbolRef Symb = getCOFFSymbol(Ref);
171
862
  int32_t SectionNumber = Symb.getSectionNumber();
172
862
173
862
  if (Symb.isAnyUndefined() || 
Symb.isCommon()778
||
174
862
      
COFF::isReservedSectionNumber(SectionNumber)776
)
175
140
    return Result;
176
722
177
722
  const coff_section *Section = nullptr;
178
722
  if (std::error_code EC = getSection(SectionNumber, Section))
179
0
    return errorCodeToError(EC);
180
722
  Result += Section->VirtualAddress;
181
722
182
722
  // The section VirtualAddress does not include ImageBase, and we want to
183
722
  // return virtual addresses.
184
722
  Result += getImageBase();
185
722
186
722
  return Result;
187
722
}
188
189
140
Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
190
140
  COFFSymbolRef Symb = getCOFFSymbol(Ref);
191
140
  int32_t SectionNumber = Symb.getSectionNumber();
192
140
193
140
  if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
194
16
    return SymbolRef::ST_Function;
195
124
  if (Symb.isAnyUndefined())
196
0
    return SymbolRef::ST_Unknown;
197
124
  if (Symb.isCommon())
198
0
    return SymbolRef::ST_Data;
199
124
  if (Symb.isFileRecord())
200
0
    return SymbolRef::ST_File;
201
124
202
124
  // TODO: perhaps we need a new symbol type ST_Section.
203
124
  if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
204
34
    return SymbolRef::ST_Debug;
205
90
206
90
  if (!COFF::isReservedSectionNumber(SectionNumber))
207
90
    return SymbolRef::ST_Data;
208
0
209
0
  return SymbolRef::ST_Other;
210
0
}
211
212
6.88k
uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
213
6.88k
  COFFSymbolRef Symb = getCOFFSymbol(Ref);
214
6.88k
  uint32_t Result = SymbolRef::SF_None;
215
6.88k
216
6.88k
  if (Symb.isExternal() || 
Symb.isWeakExternal()3.64k
)
217
3.30k
    Result |= SymbolRef::SF_Global;
218
6.88k
219
6.88k
  if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
220
64
    Result |= SymbolRef::SF_Weak;
221
64
    if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
222
34
      Result |= SymbolRef::SF_Undefined;
223
64
  }
224
6.88k
225
6.88k
  if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
226
196
    Result |= SymbolRef::SF_Absolute;
227
6.88k
228
6.88k
  if (Symb.isFileRecord())
229
19
    Result |= SymbolRef::SF_FormatSpecific;
230
6.88k
231
6.88k
  if (Symb.isSectionDefinition())
232
2.12k
    Result |= SymbolRef::SF_FormatSpecific;
233
6.88k
234
6.88k
  if (Symb.isCommon())
235
5
    Result |= SymbolRef::SF_Common;
236
6.88k
237
6.88k
  if (Symb.isUndefined())
238
868
    Result |= SymbolRef::SF_Undefined;
239
6.88k
240
6.88k
  return Result;
241
6.88k
}
242
243
2
uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
244
2
  COFFSymbolRef Symb = getCOFFSymbol(Ref);
245
2
  return Symb.getValue();
246
2
}
247
248
Expected<section_iterator>
249
2.11k
COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
250
2.11k
  COFFSymbolRef Symb = getCOFFSymbol(Ref);
251
2.11k
  if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
252
378
    return section_end();
253
1.73k
  const coff_section *Sec = nullptr;
254
1.73k
  if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
255
0
    return errorCodeToError(EC);
256
1.73k
  DataRefImpl Ret;
257
1.73k
  Ret.p = reinterpret_cast<uintptr_t>(Sec);
258
1.73k
  return section_iterator(SectionRef(Ret, this));
259
1.73k
}
260
261
210
unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
262
210
  COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
263
210
  return Symb.getSectionNumber();
264
210
}
265
266
10.1k
void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
267
10.1k
  const coff_section *Sec = toSec(Ref);
268
10.1k
  Sec += 1;
269
10.1k
  Ref.p = reinterpret_cast<uintptr_t>(Sec);
270
10.1k
}
271
272
4.92k
Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
273
4.92k
  const coff_section *Sec = toSec(Ref);
274
4.92k
  return getSectionName(Sec);
275
4.92k
}
276
277
861
uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
278
861
  const coff_section *Sec = toSec(Ref);
279
861
  uint64_t Result = Sec->VirtualAddress;
280
861
281
861
  // The section VirtualAddress does not include ImageBase, and we want to
282
861
  // return virtual addresses.
283
861
  Result += getImageBase();
284
861
  return Result;
285
861
}
286
287
151k
uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
288
151k
  return toSec(Sec) - SectionTable;
289
151k
}
290
291
150k
uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
292
150k
  return getSectionSize(toSec(Ref));
293
150k
}
294
295
Expected<ArrayRef<uint8_t>>
296
1.06k
COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
297
1.06k
  const coff_section *Sec = toSec(Ref);
298
1.06k
  ArrayRef<uint8_t> Res;
299
1.06k
  if (Error E = getSectionContents(Sec, Res))
300
0
    return std::move(E);
301
1.06k
  return Res;
302
1.06k
}
303
304
34
uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
305
34
  const coff_section *Sec = toSec(Ref);
306
34
  return Sec->getAlignment();
307
34
}
308
309
137
bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
310
137
  return false;
311
137
}
312
313
426
bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
314
426
  const coff_section *Sec = toSec(Ref);
315
426
  return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
316
426
}
317
318
99
bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
319
99
  const coff_section *Sec = toSec(Ref);
320
99
  return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
321
99
}
322
323
707
bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
324
707
  const coff_section *Sec = toSec(Ref);
325
707
  const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
326
707
                            COFF::IMAGE_SCN_MEM_READ |
327
707
                            COFF::IMAGE_SCN_MEM_WRITE;
328
707
  return (Sec->Characteristics & BssFlags) == BssFlags;
329
707
}
330
331
468
unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
332
468
  uintptr_t Offset =
333
468
      uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
334
468
  assert((Offset % sizeof(coff_section)) == 0);
335
468
  return (Offset / sizeof(coff_section)) + 1;
336
468
}
337
338
739
bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
339
739
  const coff_section *Sec = toSec(Ref);
340
739
  // In COFF, a virtual section won't have any in-file
341
739
  // content, so the file pointer to the content will be zero.
342
739
  return Sec->PointerToRawData == 0;
343
739
}
344
345
static uint32_t getNumberOfRelocations(const coff_section *Sec,
346
402k
                                       MemoryBufferRef M, const uint8_t *base) {
347
402k
  // The field for the number of relocations in COFF section table is only
348
402k
  // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
349
402k
  // NumberOfRelocations field, and the actual relocation count is stored in the
350
402k
  // VirtualAddress field in the first relocation entry.
351
402k
  if (Sec->hasExtendedRelocations()) {
352
6
    const coff_relocation *FirstReloc;
353
6
    if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
354
6
        base + Sec->PointerToRelocations)))
355
0
      return 0;
356
6
    // -1 to exclude this first relocation entry.
357
6
    return FirstReloc->VirtualAddress - 1;
358
6
  }
359
402k
  return Sec->NumberOfRelocations;
360
402k
}
361
362
static const coff_relocation *
363
202k
getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
364
202k
  uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
365
202k
  if (!NumRelocs)
366
199k
    return nullptr;
367
2.63k
  auto begin = reinterpret_cast<const coff_relocation *>(
368
2.63k
      Base + Sec->PointerToRelocations);
369
2.63k
  if (Sec->hasExtendedRelocations()) {
370
4
    // Skip the first relocation entry repurposed to store the number of
371
4
    // relocations.
372
4
    begin++;
373
4
  }
374
2.63k
  if (Binary::checkOffset(M, uintptr_t(begin),
375
2.63k
                          sizeof(coff_relocation) * NumRelocs))
376
0
    return nullptr;
377
2.63k
  return begin;
378
2.63k
}
379
380
1.89k
relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
381
1.89k
  const coff_section *Sec = toSec(Ref);
382
1.89k
  const coff_relocation *begin = getFirstReloc(Sec, Data, base());
383
1.89k
  if (begin && 
Sec->VirtualAddress != 0972
)
384
1
    report_fatal_error("Sections with relocations should have an address of 0");
385
1.89k
  DataRefImpl Ret;
386
1.89k
  Ret.p = reinterpret_cast<uintptr_t>(begin);
387
1.89k
  return relocation_iterator(RelocationRef(Ret, this));
388
1.89k
}
389
390
1.89k
relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
391
1.89k
  const coff_section *Sec = toSec(Ref);
392
1.89k
  const coff_relocation *I = getFirstReloc(Sec, Data, base());
393
1.89k
  if (I)
394
971
    I += getNumberOfRelocations(Sec, Data, base());
395
1.89k
  DataRefImpl Ret;
396
1.89k
  Ret.p = reinterpret_cast<uintptr_t>(I);
397
1.89k
  return relocation_iterator(RelocationRef(Ret, this));
398
1.89k
}
399
400
// Initialize the pointer to the symbol table.
401
2.13k
std::error_code COFFObjectFile::initSymbolTablePtr() {
402
2.13k
  if (COFFHeader)
403
2.12k
    if (std::error_code EC = getObject(
404
0
            SymbolTable16, Data, base() + getPointerToSymbolTable(),
405
0
            (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
406
0
      return EC;
407
2.13k
408
2.13k
  if (COFFBigObjHeader)
409
5
    if (std::error_code EC = getObject(
410
0
            SymbolTable32, Data, base() + getPointerToSymbolTable(),
411
0
            (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
412
0
      return EC;
413
2.13k
414
2.13k
  // Find string table. The first four byte of the string table contains the
415
2.13k
  // total size of the string table, including the size field itself. If the
416
2.13k
  // string table is empty, the value of the first four byte would be 4.
417
2.13k
  uint32_t StringTableOffset = getPointerToSymbolTable() +
418
2.13k
                               getNumberOfSymbols() * getSymbolTableEntrySize();
419
2.13k
  const uint8_t *StringTableAddr = base() + StringTableOffset;
420
2.13k
  const ulittle32_t *StringTableSizePtr;
421
2.13k
  if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
422
0
    return EC;
423
2.13k
  StringTableSize = *StringTableSizePtr;
424
2.13k
  if (std::error_code EC =
425
0
          getObject(StringTable, Data, StringTableAddr, StringTableSize))
426
0
    return EC;
427
2.13k
428
2.13k
  // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
429
2.13k
  // tools like cvtres write a size of 0 for an empty table instead of 4.
430
2.13k
  if (StringTableSize < 4)
431
29
      StringTableSize = 4;
432
2.13k
433
2.13k
  // Check that the string table is null terminated if has any in it.
434
2.13k
  if (StringTableSize > 4 && 
StringTable[StringTableSize - 1] != 01.43k
)
435
0
    return  object_error::parse_failed;
436
2.13k
  return std::error_code();
437
2.13k
}
438
439
1.93k
uint64_t COFFObjectFile::getImageBase() const {
440
1.93k
  if (PE32Header)
441
116
    return PE32Header->ImageBase;
442
1.81k
  else if (PE32PlusHeader)
443
541
    return PE32PlusHeader->ImageBase;
444
1.27k
  // This actually comes up in practice.
445
1.27k
  return 0;
446
1.27k
}
447
448
// Returns the file offset for the given VA.
449
44
std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
450
44
  uint64_t ImageBase = getImageBase();
451
44
  uint64_t Rva = Addr - ImageBase;
452
44
  assert(Rva <= UINT32_MAX);
453
44
  return getRvaPtr((uint32_t)Rva, Res);
454
44
}
455
456
// Returns the file offset for the given RVA.
457
3.34k
std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
458
6.87k
  for (const SectionRef &S : sections()) {
459
6.87k
    const coff_section *Section = getCOFFSection(S);
460
6.87k
    uint32_t SectionStart = Section->VirtualAddress;
461
6.87k
    uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
462
6.87k
    if (SectionStart <= Addr && Addr < SectionEnd) {
463
3.34k
      uint32_t Offset = Addr - SectionStart;
464
3.34k
      Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
465
3.34k
      return std::error_code();
466
3.34k
    }
467
6.87k
  }
468
3.34k
  
return object_error::parse_failed0
;
469
3.34k
}
470
471
std::error_code
472
COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
473
22
                                     ArrayRef<uint8_t> &Contents) const {
474
46
  for (const SectionRef &S : sections()) {
475
46
    const coff_section *Section = getCOFFSection(S);
476
46
    uint32_t SectionStart = Section->VirtualAddress;
477
46
    // Check if this RVA is within the section bounds. Be careful about integer
478
46
    // overflow.
479
46
    uint32_t OffsetIntoSection = RVA - SectionStart;
480
46
    if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
481
46
        
Size <= Section->VirtualSize - OffsetIntoSection22
) {
482
22
      uintptr_t Begin =
483
22
          uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
484
22
      Contents =
485
22
          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
486
22
      return std::error_code();
487
22
    }
488
46
  }
489
22
  
return object_error::parse_failed0
;
490
22
}
491
492
// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
493
// table entry.
494
std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
495
70
                                            StringRef &Name) const {
496
70
  uintptr_t IntPtr = 0;
497
70
  if (std::error_code EC = getRvaPtr(Rva, IntPtr))
498
0
    return EC;
499
70
  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
500
70
  Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
501
70
  Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
502
70
  return std::error_code();
503
70
}
504
505
std::error_code
506
COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
507
                                const codeview::DebugInfo *&PDBInfo,
508
21
                                StringRef &PDBFileName) const {
509
21
  ArrayRef<uint8_t> InfoBytes;
510
21
  if (std::error_code EC = getRvaAndSizeAsBytes(
511
0
          DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
512
0
    return EC;
513
21
  if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
514
0
    return object_error::parse_failed;
515
21
  PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
516
21
  InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
517
21
  PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
518
21
                          InfoBytes.size());
519
21
  // Truncate the name at the first null byte. Ignore any padding.
520
21
  PDBFileName = PDBFileName.split('\0').first;
521
21
  return std::error_code();
522
21
}
523
524
std::error_code
525
COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
526
0
                                StringRef &PDBFileName) const {
527
0
  for (const debug_directory &D : debug_directories())
528
0
    if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
529
0
      return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
530
0
  // If we get here, there is no PDB info to return.
531
0
  PDBInfo = nullptr;
532
0
  PDBFileName = StringRef();
533
0
  return std::error_code();
534
0
}
535
536
// Find the import table.
537
2.54k
std::error_code COFFObjectFile::initImportTablePtr() {
538
2.54k
  // First, we get the RVA of the import table. If the file lacks a pointer to
539
2.54k
  // the import table, do nothing.
540
2.54k
  const data_directory *DataEntry;
541
2.54k
  if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
542
2.13k
    return std::error_code();
543
410
544
410
  // Do nothing if the pointer to import table is NULL.
545
410
  if (DataEntry->RelativeVirtualAddress == 0)
546
347
    return std::error_code();
547
63
548
63
  uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
549
63
550
63
  // Find the section that contains the RVA. This is needed because the RVA is
551
63
  // the import table's memory address which is different from its file offset.
552
63
  uintptr_t IntPtr = 0;
553
63
  if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
554
0
    return EC;
555
63
  if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
556
0
    return EC;
557
63
  ImportDirectory = reinterpret_cast<
558
63
      const coff_import_directory_table_entry *>(IntPtr);
559
63
  return std::error_code();
560
63
}
561
562
// Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
563
2.54k
std::error_code COFFObjectFile::initDelayImportTablePtr() {
564
2.54k
  const data_directory *DataEntry;
565
2.54k
  if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
566
2.13k
    return std::error_code();
567
410
  if (DataEntry->RelativeVirtualAddress == 0)
568
397
    return std::error_code();
569
13
570
13
  uint32_t RVA = DataEntry->RelativeVirtualAddress;
571
13
  NumberOfDelayImportDirectory = DataEntry->Size /
572
13
      sizeof(delay_import_directory_table_entry) - 1;
573
13
574
13
  uintptr_t IntPtr = 0;
575
13
  if (std::error_code EC = getRvaPtr(RVA, IntPtr))
576
0
    return EC;
577
13
  DelayImportDirectory = reinterpret_cast<
578
13
      const delay_import_directory_table_entry *>(IntPtr);
579
13
  return std::error_code();
580
13
}
581
582
// Find the export table.
583
2.54k
std::error_code COFFObjectFile::initExportTablePtr() {
584
2.54k
  // First, we get the RVA of the export table. If the file lacks a pointer to
585
2.54k
  // the export table, do nothing.
586
2.54k
  const data_directory *DataEntry;
587
2.54k
  if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
588
2.13k
    return std::error_code();
589
410
590
410
  // Do nothing if the pointer to export table is NULL.
591
410
  if (DataEntry->RelativeVirtualAddress == 0)
592
357
    return std::error_code();
593
53
594
53
  uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
595
53
  uintptr_t IntPtr = 0;
596
53
  if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
597
0
    return EC;
598
53
  ExportDirectory =
599
53
      reinterpret_cast<const export_directory_table_entry *>(IntPtr);
600
53
  return std::error_code();
601
53
}
602
603
2.54k
std::error_code COFFObjectFile::initBaseRelocPtr() {
604
2.54k
  const data_directory *DataEntry;
605
2.54k
  if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
606
2.13k
    return std::error_code();
607
410
  if (DataEntry->RelativeVirtualAddress == 0)
608
303
    return std::error_code();
609
107
610
107
  uintptr_t IntPtr = 0;
611
107
  if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
612
0
    return EC;
613
107
  BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
614
107
      IntPtr);
615
107
  BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
616
107
      IntPtr + DataEntry->Size);
617
107
  // FIXME: Verify the section containing BaseRelocHeader has at least
618
107
  // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
619
107
  return std::error_code();
620
107
}
621
622
2.54k
std::error_code COFFObjectFile::initDebugDirectoryPtr() {
623
2.54k
  // Get the RVA of the debug directory. Do nothing if it does not exist.
624
2.54k
  const data_directory *DataEntry;
625
2.54k
  if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
626
2.13k
    return std::error_code();
627
410
628
410
  // Do nothing if the RVA is NULL.
629
410
  if (DataEntry->RelativeVirtualAddress == 0)
630
359
    return std::error_code();
631
51
632
51
  // Check that the size is a multiple of the entry size.
633
51
  if (DataEntry->Size % sizeof(debug_directory) != 0)
634
0
    return object_error::parse_failed;
635
51
636
51
  uintptr_t IntPtr = 0;
637
51
  if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
638
0
    return EC;
639
51
  DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
640
51
  DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
641
51
      IntPtr + DataEntry->Size);
642
51
  // FIXME: Verify the section containing DebugDirectoryBegin has at least
643
51
  // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
644
51
  return std::error_code();
645
51
}
646
647
2.54k
std::error_code COFFObjectFile::initLoadConfigPtr() {
648
2.54k
  // Get the RVA of the debug directory. Do nothing if it does not exist.
649
2.54k
  const data_directory *DataEntry;
650
2.54k
  if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
651
2.13k
    return std::error_code();
652
410
653
410
  // Do nothing if the RVA is NULL.
654
410
  if (DataEntry->RelativeVirtualAddress == 0)
655
374
    return std::error_code();
656
36
  uintptr_t IntPtr = 0;
657
36
  if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
658
0
    return EC;
659
36
660
36
  LoadConfig = (const void *)IntPtr;
661
36
  return std::error_code();
662
36
}
663
664
COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
665
    : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
666
      COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
667
      DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
668
      SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
669
      ImportDirectory(nullptr),
670
      DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
671
      ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
672
2.54k
      DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
673
2.54k
  // Check that we at least have enough room for a header.
674
2.54k
  if (!checkSize(Data, EC, sizeof(coff_file_header)))
675
0
    return;
676
2.54k
677
2.54k
  // The current location in the file where we are looking at.
678
2.54k
  uint64_t CurPtr = 0;
679
2.54k
680
2.54k
  // PE header is optional and is present only in executables. If it exists,
681
2.54k
  // it is placed right after COFF header.
682
2.54k
  bool HasPEHeader = false;
683
2.54k
684
2.54k
  // Check if this is a PE/COFF file.
685
2.54k
  if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
686
2.53k
    // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
687
2.53k
    // PE signature to find 'normal' COFF header.
688
2.53k
    const auto *DH = reinterpret_cast<const dos_header *>(base());
689
2.53k
    if (DH->Magic[0] == 'M' && 
DH->Magic[1] == 'Z'410
) {
690
410
      CurPtr = DH->AddressOfNewExeHeader;
691
410
      // Check the PE magic bytes. ("PE\0\0")
692
410
      if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
693
0
        EC = object_error::parse_failed;
694
0
        return;
695
0
      }
696
410
      CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
697
410
      HasPEHeader = true;
698
410
    }
699
2.53k
  }
700
2.54k
701
2.54k
  if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
702
0
    return;
703
2.54k
704
2.54k
  // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
705
2.54k
  // import libraries share a common prefix but bigobj is more restrictive.
706
2.54k
  if (!HasPEHeader && 
COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN2.13k
&&
707
2.54k
      
COFFHeader->NumberOfSections == uint16_t(0xffff)8
&&
708
2.54k
      
checkSize(Data, EC, sizeof(coff_bigobj_file_header))5
) {
709
5
    if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
710
0
      return;
711
5
712
5
    // Verify that we are dealing with bigobj.
713
5
    if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
714
5
        std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
715
5
                    sizeof(COFF::BigObjMagic)) == 0) {
716
5
      COFFHeader = nullptr;
717
5
      CurPtr += sizeof(coff_bigobj_file_header);
718
5
    } else {
719
0
      // It's not a bigobj.
720
0
      COFFBigObjHeader = nullptr;
721
0
    }
722
5
  }
723
2.54k
  if (COFFHeader) {
724
2.54k
    // The prior checkSize call may have failed.  This isn't a hard error
725
2.54k
    // because we were just trying to sniff out bigobj.
726
2.54k
    EC = std::error_code();
727
2.54k
    CurPtr += sizeof(coff_file_header);
728
2.54k
729
2.54k
    if (COFFHeader->isImportLibrary())
730
0
      return;
731
2.54k
  }
732
2.54k
733
2.54k
  if (HasPEHeader) {
734
410
    const pe32_header *Header;
735
410
    if ((EC = getObject(Header, Data, base() + CurPtr)))
736
0
      return;
737
410
738
410
    const uint8_t *DataDirAddr;
739
410
    uint64_t DataDirSize;
740
410
    if (Header->Magic == COFF::PE32Header::PE32) {
741
112
      PE32Header = Header;
742
112
      DataDirAddr = base() + CurPtr + sizeof(pe32_header);
743
112
      DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
744
298
    } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
745
298
      PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
746
298
      DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
747
298
      DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
748
298
    } else {
749
0
      // It's neither PE32 nor PE32+.
750
0
      EC = object_error::parse_failed;
751
0
      return;
752
0
    }
753
410
    if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
754
0
      return;
755
2.54k
  }
756
2.54k
757
2.54k
  if (COFFHeader)
758
2.54k
    CurPtr += COFFHeader->SizeOfOptionalHeader;
759
2.54k
760
2.54k
  if ((EC = getObject(SectionTable, Data, base() + CurPtr,
761
2.54k
                      (uint64_t)getNumberOfSections() * sizeof(coff_section))))
762
0
    return;
763
2.54k
764
2.54k
  // Initialize the pointer to the symbol table.
765
2.54k
  if (getPointerToSymbolTable() != 0) {
766
2.13k
    if ((EC = initSymbolTablePtr())) {
767
0
      SymbolTable16 = nullptr;
768
0
      SymbolTable32 = nullptr;
769
0
      StringTable = nullptr;
770
0
      StringTableSize = 0;
771
0
    }
772
2.13k
  } else {
773
414
    // We had better not have any symbols if we don't have a symbol table.
774
414
    if (getNumberOfSymbols() != 0) {
775
0
      EC = object_error::parse_failed;
776
0
      return;
777
0
    }
778
2.54k
  }
779
2.54k
780
2.54k
  // Initialize the pointer to the beginning of the import table.
781
2.54k
  if ((EC = initImportTablePtr()))
782
0
    return;
783
2.54k
  if ((EC = initDelayImportTablePtr()))
784
0
    return;
785
2.54k
786
2.54k
  // Initialize the pointer to the export table.
787
2.54k
  if ((EC = initExportTablePtr()))
788
0
    return;
789
2.54k
790
2.54k
  // Initialize the pointer to the base relocation table.
791
2.54k
  if ((EC = initBaseRelocPtr()))
792
0
    return;
793
2.54k
794
2.54k
  // Initialize the pointer to the export table.
795
2.54k
  if ((EC = initDebugDirectoryPtr()))
796
0
    return;
797
2.54k
798
2.54k
  if ((EC = initLoadConfigPtr()))
799
0
    return;
800
2.54k
801
2.54k
  EC = std::error_code();
802
2.54k
}
803
804
994
basic_symbol_iterator COFFObjectFile::symbol_begin() const {
805
994
  DataRefImpl Ret;
806
994
  Ret.p = getSymbolTable();
807
994
  return basic_symbol_iterator(SymbolRef(Ret, this));
808
994
}
809
810
4.67k
basic_symbol_iterator COFFObjectFile::symbol_end() const {
811
4.67k
  // The symbol table ends where the string table begins.
812
4.67k
  DataRefImpl Ret;
813
4.67k
  Ret.p = reinterpret_cast<uintptr_t>(StringTable);
814
4.67k
  return basic_symbol_iterator(SymbolRef(Ret, this));
815
4.67k
}
816
817
55
import_directory_iterator COFFObjectFile::import_directory_begin() const {
818
55
  if (!ImportDirectory)
819
32
    return import_directory_end();
820
23
  if (ImportDirectory->isNull())
821
0
    return import_directory_end();
822
23
  return import_directory_iterator(
823
23
      ImportDirectoryEntryRef(ImportDirectory, 0, this));
824
23
}
825
826
87
import_directory_iterator COFFObjectFile::import_directory_end() const {
827
87
  return import_directory_iterator(
828
87
      ImportDirectoryEntryRef(nullptr, -1, this));
829
87
}
830
831
delay_import_directory_iterator
832
25
COFFObjectFile::delay_import_directory_begin() const {
833
25
  return delay_import_directory_iterator(
834
25
      DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
835
25
}
836
837
delay_import_directory_iterator
838
25
COFFObjectFile::delay_import_directory_end() const {
839
25
  return delay_import_directory_iterator(
840
25
      DelayImportDirectoryEntryRef(
841
25
          DelayImportDirectory, NumberOfDelayImportDirectory, this));
842
25
}
843
844
127
export_directory_iterator COFFObjectFile::export_directory_begin() const {
845
127
  return export_directory_iterator(
846
127
      ExportDirectoryEntryRef(ExportDirectory, 0, this));
847
127
}
848
849
127
export_directory_iterator COFFObjectFile::export_directory_end() const {
850
127
  if (!ExportDirectory)
851
83
    return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
852
44
  ExportDirectoryEntryRef Ref(ExportDirectory,
853
44
                              ExportDirectory->AddressTableEntries, this);
854
44
  return export_directory_iterator(Ref);
855
44
}
856
857
4.53k
section_iterator COFFObjectFile::section_begin() const {
858
4.53k
  DataRefImpl Ret;
859
4.53k
  Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
860
4.53k
  return section_iterator(SectionRef(Ret, this));
861
4.53k
}
862
863
6.30k
section_iterator COFFObjectFile::section_end() const {
864
6.30k
  DataRefImpl Ret;
865
6.30k
  int NumSections =
866
6.30k
      COFFHeader && 
COFFHeader->isImportLibrary()6.29k
?
00
: getNumberOfSections();
867
6.30k
  Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
868
6.30k
  return section_iterator(SectionRef(Ret, this));
869
6.30k
}
870
871
14
base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
872
14
  return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
873
14
}
874
875
14
base_reloc_iterator COFFObjectFile::base_reloc_end() const {
876
14
  return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
877
14
}
878
879
882
uint8_t COFFObjectFile::getBytesInAddress() const {
880
882
  return getArch() == Triple::x86_64 || 
getArch() == Triple::aarch64414
?
8526
:
4356
;
881
882
}
882
883
868
StringRef COFFObjectFile::getFileFormatName() const {
884
868
  switch(getMachine()) {
885
868
  case COFF::IMAGE_FILE_MACHINE_I386:
886
275
    return "COFF-i386";
887
868
  case COFF::IMAGE_FILE_MACHINE_AMD64:
888
492
    return "COFF-x86-64";
889
868
  case COFF::IMAGE_FILE_MACHINE_ARMNT:
890
50
    return "COFF-ARM";
891
868
  case COFF::IMAGE_FILE_MACHINE_ARM64:
892
50
    return "COFF-ARM64";
893
868
  default:
894
1
    return "COFF-<unknown arch>";
895
868
  }
896
868
}
897
898
153k
Triple::ArchType COFFObjectFile::getArch() const {
899
153k
  switch (getMachine()) {
900
153k
  case COFF::IMAGE_FILE_MACHINE_I386:
901
990
    return Triple::x86;
902
153k
  case COFF::IMAGE_FILE_MACHINE_AMD64:
903
151k
    return Triple::x86_64;
904
153k
  case COFF::IMAGE_FILE_MACHINE_ARMNT:
905
316
    return Triple::thumb;
906
153k
  case COFF::IMAGE_FILE_MACHINE_ARM64:
907
326
    return Triple::aarch64;
908
153k
  default:
909
3
    return Triple::UnknownArch;
910
153k
  }
911
153k
}
912
913
5
Expected<uint64_t> COFFObjectFile::getStartAddress() const {
914
5
  if (PE32Header)
915
2
    return PE32Header->AddressOfEntryPoint;
916
3
  return 0;
917
3
}
918
919
iterator_range<import_directory_iterator>
920
28
COFFObjectFile::import_directories() const {
921
28
  return make_range(import_directory_begin(), import_directory_end());
922
28
}
923
924
iterator_range<delay_import_directory_iterator>
925
25
COFFObjectFile::delay_import_directories() const {
926
25
  return make_range(delay_import_directory_begin(),
927
25
                    delay_import_directory_end());
928
25
}
929
930
iterator_range<export_directory_iterator>
931
100
COFFObjectFile::export_directories() const {
932
100
  return make_range(export_directory_begin(), export_directory_end());
933
100
}
934
935
14
iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
936
14
  return make_range(base_reloc_begin(), base_reloc_end());
937
14
}
938
939
std::error_code
940
40
COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
941
40
  Res = COFFHeader;
942
40
  return std::error_code();
943
40
}
944
945
std::error_code
946
40
COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const {
947
40
  Res = COFFBigObjHeader;
948
40
  return std::error_code();
949
40
}
950
951
233
std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
952
233
  Res = PE32Header;
953
233
  return std::error_code();
954
233
}
955
956
std::error_code
957
208
COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
958
208
  Res = PE32PlusHeader;
959
208
  return std::error_code();
960
208
}
961
962
std::error_code
963
COFFObjectFile::getDataDirectory(uint32_t Index,
964
17.6k
                                 const data_directory *&Res) const {
965
17.6k
  // Error if there's no data directory or the index is out of range.
966
17.6k
  if (!DataDirectory) {
967
12.8k
    Res = nullptr;
968
12.8k
    return object_error::parse_failed;
969
12.8k
  }
970
4.84k
  assert(PE32Header || PE32PlusHeader);
971
4.84k
  uint32_t NumEnt = PE32Header ? 
PE32Header->NumberOfRvaAndSize1.14k
972
4.84k
                               : 
PE32PlusHeader->NumberOfRvaAndSize3.70k
;
973
4.84k
  if (Index >= NumEnt) {
974
0
    Res = nullptr;
975
0
    return object_error::parse_failed;
976
0
  }
977
4.84k
  Res = &DataDirectory[Index];
978
4.84k
  return std::error_code();
979
4.84k
}
980
981
std::error_code COFFObjectFile::getSection(int32_t Index,
982
205k
                                           const coff_section *&Result) const {
983
205k
  Result = nullptr;
984
205k
  if (COFF::isReservedSectionNumber(Index))
985
75
    return std::error_code();
986
204k
  if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
987
204k
    // We already verified the section table data, so no need to check again.
988
204k
    Result = SectionTable + (Index - 1);
989
204k
    return std::error_code();
990
204k
  }
991
0
  return object_error::parse_failed;
992
0
}
993
994
std::error_code COFFObjectFile::getSection(StringRef SectionName,
995
0
                                           const coff_section *&Result) const {
996
0
  Result = nullptr;
997
0
  StringRef SecName;
998
0
  for (const SectionRef &Section : sections()) {
999
0
    if (std::error_code E = Section.getName(SecName))
1000
0
      return E;
1001
0
    if (SecName == SectionName) {
1002
0
      Result = getCOFFSection(Section);
1003
0
      return std::error_code();
1004
0
    }
1005
0
  }
1006
0
  return object_error::parse_failed;
1007
0
}
1008
1009
std::error_code COFFObjectFile::getString(uint32_t Offset,
1010
3.92k
                                          StringRef &Result) const {
1011
3.92k
  if (StringTableSize <= 4)
1012
0
    // Tried to get a string from an empty string table.
1013
0
    return object_error::parse_failed;
1014
3.92k
  if (Offset >= StringTableSize)
1015
0
    return object_error::unexpected_eof;
1016
3.92k
  Result = StringRef(StringTable + Offset);
1017
3.92k
  return std::error_code();
1018
3.92k
}
1019
1020
std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
1021
7.35k
                                              StringRef &Res) const {
1022
7.35k
  return getSymbolName(Symbol.getGeneric(), Res);
1023
7.35k
}
1024
1025
std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
1026
7.61k
                                              StringRef &Res) const {
1027
7.61k
  // Check for string table entry. First 4 bytes are 0.
1028
7.61k
  if (Symbol->Name.Offset.Zeroes == 0) {
1029
3.18k
    if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
1030
0
      return EC;
1031
3.18k
    return std::error_code();
1032
3.18k
  }
1033
4.43k
1034
4.43k
  if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
1035
3.43k
    // Null terminated, let ::strlen figure out the length.
1036
3.43k
    Res = StringRef(Symbol->Name.ShortName);
1037
995
  else
1038
995
    // Not null terminated, use all 8 bytes.
1039
995
    Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
1040
4.43k
  return std::error_code();
1041
4.43k
}
1042
1043
ArrayRef<uint8_t>
1044
594
COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
1045
594
  const uint8_t *Aux = nullptr;
1046
594
1047
594
  size_t SymbolSize = getSymbolTableEntrySize();
1048
594
  if (Symbol.getNumberOfAuxSymbols() > 0) {
1049
461
    // AUX data comes immediately after the symbol in COFF
1050
461
    Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
1051
#ifndef NDEBUG
1052
    // Verify that the Aux symbol points to a valid entry in the symbol table.
1053
    uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
1054
    if (Offset < getPointerToSymbolTable() ||
1055
        Offset >=
1056
            getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
1057
      report_fatal_error("Aux Symbol data was outside of symbol table.");
1058
1059
    assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
1060
           "Aux Symbol data did not point to the beginning of a symbol");
1061
#endif
1062
  }
1063
594
  return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
1064
594
}
1065
1066
364
uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
1067
364
  uintptr_t Offset =
1068
364
      reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
1069
364
  assert(Offset % getSymbolTableEntrySize() == 0 &&
1070
364
         "Symbol did not point to the beginning of a symbol");
1071
364
  size_t Index = Offset / getSymbolTableEntrySize();
1072
364
  assert(Index < getNumberOfSymbols());
1073
364
  return Index;
1074
364
}
1075
1076
Expected<StringRef>
1077
207k
COFFObjectFile::getSectionName(const coff_section *Sec) const {
1078
207k
  StringRef Name;
1079
207k
  if (Sec->Name[COFF::NameSize - 1] == 0)
1080
204k
    // Null terminated, let ::strlen figure out the length.
1081
204k
    Name = Sec->Name;
1082
3.15k
  else
1083
3.15k
    // Not null terminated, use all 8 bytes.
1084
3.15k
    Name = StringRef(Sec->Name, COFF::NameSize);
1085
207k
1086
207k
  // Check for string table entry. First byte is '/'.
1087
207k
  if (Name.startswith("/")) {
1088
735
    uint32_t Offset;
1089
735
    if (Name.startswith("//")) {
1090
1
      if (decodeBase64StringEntry(Name.substr(2), Offset))
1091
0
        return createStringError(object_error::parse_failed,
1092
0
                                 "inalid section name");
1093
734
    } else {
1094
734
      if (Name.substr(1).getAsInteger(10, Offset))
1095
0
        return createStringError(object_error::parse_failed,
1096
0
                                 "invalid section name");
1097
735
    }
1098
735
    if (std::error_code EC = getString(Offset, Name))
1099
0
      return errorCodeToError(EC);
1100
207k
  }
1101
207k
1102
207k
  return Name;
1103
207k
}
1104
1105
154k
uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1106
154k
  // SizeOfRawData and VirtualSize change what they represent depending on
1107
154k
  // whether or not we have an executable image.
1108
154k
  //
1109
154k
  // For object files, SizeOfRawData contains the size of section's data;
1110
154k
  // VirtualSize should be zero but isn't due to buggy COFF writers.
1111
154k
  //
1112
154k
  // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1113
154k
  // actual section size is in VirtualSize.  It is possible for VirtualSize to
1114
154k
  // be greater than SizeOfRawData; the contents past that point should be
1115
154k
  // considered to be zero.
1116
154k
  if (getDOSHeader())
1117
150k
    return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1118
4.29k
  return Sec->SizeOfRawData;
1119
4.29k
}
1120
1121
Error COFFObjectFile::getSectionContents(const coff_section *Sec,
1122
199k
                                         ArrayRef<uint8_t> &Res) const {
1123
199k
  // In COFF, a virtual section won't have any in-file
1124
199k
  // content, so the file pointer to the content will be zero.
1125
199k
  if (Sec->PointerToRawData == 0)
1126
195k
    return Error::success();
1127
4.10k
  // The only thing that we need to verify is that the contents is contained
1128
4.10k
  // within the file bounds. We don't need to make sure it doesn't cover other
1129
4.10k
  // data, as there's nothing that says that is not allowed.
1130
4.10k
  uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1131
4.10k
  uint32_t SectionSize = getSectionSize(Sec);
1132
4.10k
  if (checkOffset(Data, ConStart, SectionSize))
1133
0
    return make_error<BinaryError>();
1134
4.10k
  Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1135
4.10k
  return Error::success();
1136
4.10k
}
1137
1138
26.2k
const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1139
26.2k
  return reinterpret_cast<const coff_relocation*>(Rel.p);
1140
26.2k
}
1141
1142
4.28k
void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1143
4.28k
  Rel.p = reinterpret_cast<uintptr_t>(
1144
4.28k
            reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1145
4.28k
}
1146
1147
22.7k
uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
1148
22.7k
  const coff_relocation *R = toRel(Rel);
1149
22.7k
  return R->VirtualAddress;
1150
22.7k
}
1151
1152
2.09k
symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1153
2.09k
  const coff_relocation *R = toRel(Rel);
1154
2.09k
  DataRefImpl Ref;
1155
2.09k
  if (R->SymbolTableIndex >= getNumberOfSymbols())
1156
2
    return symbol_end();
1157
2.09k
  if (SymbolTable16)
1158
2.09k
    Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
1159
0
  else if (SymbolTable32)
1160
0
    Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
1161
0
  else
1162
0
    llvm_unreachable("no symbol table pointer!");
1163
2.09k
  return symbol_iterator(SymbolRef(Ref, this));
1164
2.09k
}
1165
1166
830
uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1167
830
  const coff_relocation* R = toRel(Rel);
1168
830
  return R->Type;
1169
830
}
1170
1171
const coff_section *
1172
10.3k
COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
1173
10.3k
  return toSec(Section.getRawDataRefImpl());
1174
10.3k
}
1175
1176
16.2k
COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
1177
16.2k
  if (SymbolTable16)
1178
16.2k
    return toSymb<coff_symbol16>(Ref);
1179
4
  if (SymbolTable32)
1180
4
    return toSymb<coff_symbol32>(Ref);
1181
0
  llvm_unreachable("no symbol table pointer!");
1182
0
}
1183
1184
1.46k
COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
1185
1.46k
  return getCOFFSymbol(Symbol.getRawDataRefImpl());
1186
1.46k
}
1187
1188
const coff_relocation *
1189
155
COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
1190
155
  return toRel(Reloc.getRawDataRefImpl());
1191
155
}
1192
1193
ArrayRef<coff_relocation>
1194
198k
COFFObjectFile::getRelocations(const coff_section *Sec) const {
1195
198k
  return {getFirstReloc(Sec, Data, base()),
1196
198k
          getNumberOfRelocations(Sec, Data, base())};
1197
198k
}
1198
1199
#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
1200
414
  case COFF::reloc_type:                                                       \
1201
414
    return #reloc_type;
1202
1203
414
StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
1204
414
  switch (getMachine()) {
1205
414
  case COFF::IMAGE_FILE_MACHINE_AMD64:
1206
168
    switch (Type) {
1207
168
    
LLVM_COFF_SWITCH_RELOC_TYPE_NAME1
(IMAGE_REL_AMD64_ABSOLUTE);
1208
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_ADDR64)0
;
1209
6
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_ADDR32)0
;
1210
58
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_ADDR32NB)0
;
1211
40
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_REL32)0
;
1212
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_REL32_1)0
;
1213
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_REL32_2)0
;
1214
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_REL32_3)0
;
1215
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_REL32_4)0
;
1216
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_REL32_5)0
;
1217
24
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_SECTION)0
;
1218
27
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_SECREL)0
;
1219
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_SECREL7)0
;
1220
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_TOKEN)0
;
1221
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_SREL32)0
;
1222
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_PAIR)0
;
1223
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_AMD64_SSPAN32)0
;
1224
0
    default:
1225
0
      return "Unknown";
1226
0
    }
1227
0
    break;
1228
34
  case COFF::IMAGE_FILE_MACHINE_ARMNT:
1229
34
    switch (Type) {
1230
34
    
LLVM_COFF_SWITCH_RELOC_TYPE_NAME0
(IMAGE_REL_ARM_ABSOLUTE);
1231
5
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_ADDR32)0
;
1232
9
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_ADDR32NB)0
;
1233
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
1234
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
1235
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
1236
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
1237
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1238
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
1239
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_SECTION)0
;
1240
11
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_SECREL)0
;
1241
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
1242
3
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_MOV32T)0
;
1243
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_BRANCH20T)0
;
1244
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_BRANCH24T)0
;
1245
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM_BLX23T)0
;
1246
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
1247
0
    default:
1248
0
      return "Unknown";
1249
0
    }
1250
0
    break;
1251
40
  case COFF::IMAGE_FILE_MACHINE_ARM64:
1252
40
    switch (Type) {
1253
40
    
LLVM_COFF_SWITCH_RELOC_TYPE_NAME0
(IMAGE_REL_ARM64_ABSOLUTE);
1254
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_ADDR32)0
;
1255
19
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_ADDR32NB)0
;
1256
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_BRANCH26)0
;
1257
4
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_PAGEBASE_REL21)0
;
1258
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_REL21)0
;
1259
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_PAGEOFFSET_12A)0
;
1260
4
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_PAGEOFFSET_12L)0
;
1261
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_SECREL)0
;
1262
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_SECREL_LOW12A)0
;
1263
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_SECREL_HIGH12A)0
;
1264
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_SECREL_LOW12L)0
;
1265
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
1266
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_SECTION)0
;
1267
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_ADDR64)0
;
1268
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_BRANCH19)0
;
1269
1
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_ARM64_BRANCH14)0
;
1270
0
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
1271
0
    default:
1272
0
      return "Unknown";
1273
0
    }
1274
0
    break;
1275
172
  case COFF::IMAGE_FILE_MACHINE_I386:
1276
172
    switch (Type) {
1277
172
    
LLVM_COFF_SWITCH_RELOC_TYPE_NAME3
(IMAGE_REL_I386_ABSOLUTE);
1278
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_DIR16)0
;
1279
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_REL16)0
;
1280
37
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_DIR32)0
;
1281
26
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_DIR32NB)0
;
1282
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_SEG12)0
;
1283
27
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_SECTION)0
;
1284
35
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_SECREL)0
;
1285
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_TOKEN)0
;
1286
2
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_SECREL7)0
;
1287
34
    LLVM_COFF_SWITCH_RELOC_TYPE_NAME
(IMAGE_REL_I386_REL32)0
;
1288
0
    default:
1289
0
      return "Unknown";
1290
0
    }
1291
0
    break;
1292
0
  default:
1293
0
    return "Unknown";
1294
414
  }
1295
414
}
1296
1297
#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1298
1299
void COFFObjectFile::getRelocationTypeName(
1300
411
    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1301
411
  const coff_relocation *Reloc = toRel(Rel);
1302
411
  StringRef Res = getRelocationTypeName(Reloc->Type);
1303
411
  Result.append(Res.begin(), Res.end());
1304
411
}
1305
1306
27.8k
bool COFFObjectFile::isRelocatableObject() const {
1307
27.8k
  return !DataDirectory;
1308
27.8k
}
1309
1310
137
StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1311
137
  return StringSwitch<StringRef>(Name)
1312
137
      .Case("eh_fram", "eh_frame")
1313
137
      .Default(Name);
1314
137
}
1315
1316
bool ImportDirectoryEntryRef::
1317
84
operator==(const ImportDirectoryEntryRef &Other) const {
1318
84
  return ImportTable == Other.ImportTable && 
Index == Other.Index53
;
1319
84
}
1320
1321
29
void ImportDirectoryEntryRef::moveNext() {
1322
29
  ++Index;
1323
29
  if (ImportTable[Index].isNull()) {
1324
21
    Index = -1;
1325
21
    ImportTable = nullptr;
1326
21
  }
1327
29
}
1328
1329
std::error_code ImportDirectoryEntryRef::getImportTableEntry(
1330
4
    const coff_import_directory_table_entry *&Result) const {
1331
4
  return getObject(Result, OwningObject->Data, ImportTable + Index);
1332
4
}
1333
1334
static imported_symbol_iterator
1335
makeImportedSymbolIterator(const COFFObjectFile *Object,
1336
72
                           uintptr_t Ptr, int Index) {
1337
72
  if (Object->getBytesInAddress() == 4) {
1338
26
    auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
1339
26
    return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1340
26
  }
1341
46
  auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
1342
46
  return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1343
46
}
1344
1345
static imported_symbol_iterator
1346
36
importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1347
36
  uintptr_t IntPtr = 0;
1348
36
  Object->getRvaPtr(RVA, IntPtr);
1349
36
  return makeImportedSymbolIterator(Object, IntPtr, 0);
1350
36
}
1351
1352
static imported_symbol_iterator
1353
36
importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1354
36
  uintptr_t IntPtr = 0;
1355
36
  Object->getRvaPtr(RVA, IntPtr);
1356
36
  // Forward the pointer to the last entry which is null.
1357
36
  int Index = 0;
1358
36
  if (Object->getBytesInAddress() == 4) {
1359
13
    auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1360
102
    while (*Entry++)
1361
89
      ++Index;
1362
23
  } else {
1363
23
    auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1364
71
    while (*Entry++)
1365
48
      ++Index;
1366
23
  }
1367
36
  return makeImportedSymbolIterator(Object, IntPtr, Index);
1368
36
}
1369
1370
imported_symbol_iterator
1371
4
ImportDirectoryEntryRef::imported_symbol_begin() const {
1372
4
  return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
1373
4
                             OwningObject);
1374
4
}
1375
1376
imported_symbol_iterator
1377
4
ImportDirectoryEntryRef::imported_symbol_end() const {
1378
4
  return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
1379
4
                           OwningObject);
1380
4
}
1381
1382
iterator_range<imported_symbol_iterator>
1383
4
ImportDirectoryEntryRef::imported_symbols() const {
1384
4
  return make_range(imported_symbol_begin(), imported_symbol_end());
1385
4
}
1386
1387
24
imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
1388
24
  return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
1389
24
                             OwningObject);
1390
24
}
1391
1392
24
imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
1393
24
  return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
1394
24
                           OwningObject);
1395
24
}
1396
1397
iterator_range<imported_symbol_iterator>
1398
24
ImportDirectoryEntryRef::lookup_table_symbols() const {
1399
24
  return make_range(lookup_table_begin(), lookup_table_end());
1400
24
}
1401
1402
29
std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1403
29
  uintptr_t IntPtr = 0;
1404
29
  if (std::error_code EC =
1405
0
          OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1406
0
    return EC;
1407
29
  Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1408
29
  return std::error_code();
1409
29
}
1410
1411
std::error_code
1412
24
ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
1413
24
  Result = ImportTable[Index].ImportLookupTableRVA;
1414
24
  return std::error_code();
1415
24
}
1416
1417
std::error_code
1418
24
ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
1419
24
  Result = ImportTable[Index].ImportAddressTableRVA;
1420
24
  return std::error_code();
1421
24
}
1422
1423
bool DelayImportDirectoryEntryRef::
1424
33
operator==(const DelayImportDirectoryEntryRef &Other) const {
1425
33
  return Table == Other.Table && Index == Other.Index;
1426
33
}
1427
1428
8
void DelayImportDirectoryEntryRef::moveNext() {
1429
8
  ++Index;
1430
8
}
1431
1432
imported_symbol_iterator
1433
8
DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1434
8
  return importedSymbolBegin(Table[Index].DelayImportNameTable,
1435
8
                             OwningObject);
1436
8
}
1437
1438
imported_symbol_iterator
1439
8
DelayImportDirectoryEntryRef::imported_symbol_end() const {
1440
8
  return importedSymbolEnd(Table[Index].DelayImportNameTable,
1441
8
                           OwningObject);
1442
8
}
1443
1444
iterator_range<imported_symbol_iterator>
1445
8
DelayImportDirectoryEntryRef::imported_symbols() const {
1446
8
  return make_range(imported_symbol_begin(), imported_symbol_end());
1447
8
}
1448
1449
8
std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
1450
8
  uintptr_t IntPtr = 0;
1451
8
  if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
1452
0
    return EC;
1453
8
  Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1454
8
  return std::error_code();
1455
8
}
1456
1457
std::error_code DelayImportDirectoryEntryRef::
1458
8
getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
1459
8
  Result = &Table[Index];
1460
8
  return std::error_code();
1461
8
}
1462
1463
std::error_code DelayImportDirectoryEntryRef::
1464
15
getImportAddress(int AddrIndex, uint64_t &Result) const {
1465
15
  uint32_t RVA = Table[Index].DelayImportAddressTable +
1466
15
      AddrIndex * (OwningObject->is64() ? 
810
:
45
);
1467
15
  uintptr_t IntPtr = 0;
1468
15
  if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1469
0
    return EC;
1470
15
  if (OwningObject->is64())
1471
10
    Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1472
5
  else
1473
5
    Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
1474
15
  return std::error_code();
1475
15
}
1476
1477
bool ExportDirectoryEntryRef::
1478
809
operator==(const ExportDirectoryEntryRef &Other) const {
1479
809
  return ExportTable == Other.ExportTable && Index == Other.Index;
1480
809
}
1481
1482
658
void ExportDirectoryEntryRef::moveNext() {
1483
658
  ++Index;
1484
658
}
1485
1486
// Returns the name of the current export symbol. If the symbol is exported only
1487
// by ordinal, the empty string is set as a result.
1488
24
std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1489
24
  uintptr_t IntPtr = 0;
1490
24
  if (std::error_code EC =
1491
0
          OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1492
0
    return EC;
1493
24
  Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1494
24
  return std::error_code();
1495
24
}
1496
1497
// Returns the starting ordinal number.
1498
std::error_code
1499
24
ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1500
24
  Result = ExportTable->OrdinalBase;
1501
24
  return std::error_code();
1502
24
}
1503
1504
// Returns the export ordinal of the current export symbol.
1505
164
std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1506
164
  Result = ExportTable->OrdinalBase + Index;
1507
164
  return std::error_code();
1508
164
}
1509
1510
// Returns the address of the current export symbol.
1511
771
std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1512
771
  uintptr_t IntPtr = 0;
1513
771
  if (std::error_code EC =
1514
0
          OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1515
0
    return EC;
1516
771
  const export_address_table_entry *entry =
1517
771
      reinterpret_cast<const export_address_table_entry *>(IntPtr);
1518
771
  Result = entry[Index].ExportRVA;
1519
771
  return std::error_code();
1520
771
}
1521
1522
// Returns the name of the current export symbol. If the symbol is exported only
1523
// by ordinal, the empty string is set as a result.
1524
std::error_code
1525
658
ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1526
658
  uintptr_t IntPtr = 0;
1527
658
  if (std::error_code EC =
1528
0
          OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1529
0
    return EC;
1530
658
  const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1531
658
1532
658
  uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1533
658
  int Offset = 0;
1534
658
  for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1535
60.2k
       I < E; 
++I, ++Offset59.5k
) {
1536
60.1k
    if (*I != Index)
1537
59.5k
      continue;
1538
599
    if (std::error_code EC =
1539
0
            OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1540
0
      return EC;
1541
599
    const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1542
599
    if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1543
0
      return EC;
1544
599
    Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1545
599
    return std::error_code();
1546
599
  }
1547
658
  Result = "";
1548
59
  return std::error_code();
1549
658
}
1550
1551
113
std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
1552
113
  const data_directory *DataEntry;
1553
113
  if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
1554
0
    return EC;
1555
113
  uint32_t RVA;
1556
113
  if (auto EC = getExportRVA(RVA))
1557
0
    return EC;
1558
113
  uint32_t Begin = DataEntry->RelativeVirtualAddress;
1559
113
  uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
1560
113
  Result = (Begin <= RVA && 
RVA < End5
);
1561
113
  return std::error_code();
1562
113
}
1563
1564
2
std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
1565
2
  uint32_t RVA;
1566
2
  if (auto EC = getExportRVA(RVA))
1567
0
    return EC;
1568
2
  uintptr_t IntPtr = 0;
1569
2
  if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
1570
0
    return EC;
1571
2
  Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1572
2
  return std::error_code();
1573
2
}
1574
1575
bool ImportedSymbolRef::
1576
173
operator==(const ImportedSymbolRef &Other) const {
1577
173
  return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1578
173
      && Index == Other.Index;
1579
173
}
1580
1581
137
void ImportedSymbolRef::moveNext() {
1582
137
  ++Index;
1583
137
}
1584
1585
std::error_code
1586
67
ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1587
67
  uint32_t RVA;
1588
67
  if (Entry32) {
1589
19
    // If a symbol is imported only by ordinal, it has no name.
1590
19
    if (Entry32[Index].isOrdinal())
1591
1
      return std::error_code();
1592
18
    RVA = Entry32[Index].getHintNameRVA();
1593
48
  } else {
1594
48
    if (Entry64[Index].isOrdinal())
1595
7
      return std::error_code();
1596
41
    RVA = Entry64[Index].getHintNameRVA();
1597
41
  }
1598
67
  uintptr_t IntPtr = 0;
1599
59
  if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1600
0
    return EC;
1601
59
  // +2 because the first two bytes is hint.
1602
59
  Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
1603
59
  return std::error_code();
1604
59
}
1605
1606
70
std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1607
70
  if (Entry32)
1608
70
    Result = Entry32[Index].isOrdinal();
1609
0
  else
1610
0
    Result = Entry64[Index].isOrdinal();
1611
70
  return std::error_code();
1612
70
}
1613
1614
70
std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1615
70
  if (Entry32)
1616
70
    Result = Entry32[Index].getHintNameRVA();
1617
0
  else
1618
0
    Result = Entry64[Index].getHintNameRVA();
1619
70
  return std::error_code();
1620
70
}
1621
1622
67
std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1623
67
  uint32_t RVA;
1624
67
  if (Entry32) {
1625
19
    if (Entry32[Index].isOrdinal()) {
1626
1
      Result = Entry32[Index].getOrdinal();
1627
1
      return std::error_code();
1628
1
    }
1629
18
    RVA = Entry32[Index].getHintNameRVA();
1630
48
  } else {
1631
48
    if (Entry64[Index].isOrdinal()) {
1632
7
      Result = Entry64[Index].getOrdinal();
1633
7
      return std::error_code();
1634
7
    }
1635
41
    RVA = Entry64[Index].getHintNameRVA();
1636
41
  }
1637
67
  uintptr_t IntPtr = 0;
1638
59
  if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1639
0
    return EC;
1640
59
  Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
1641
59
  return std::error_code();
1642
59
}
1643
1644
Expected<std::unique_ptr<COFFObjectFile>>
1645
2.51k
ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1646
2.51k
  std::error_code EC;
1647
2.51k
  std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1648
2.51k
  if (EC)
1649
0
    return errorCodeToError(EC);
1650
2.51k
  return std::move(Ret);
1651
2.51k
}
1652
1653
116
bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
1654
116
  return Header == Other.Header && 
Index == Other.Index14
;
1655
116
}
1656
1657
102
void BaseRelocRef::moveNext() {
1658
102
  // Header->BlockSize is the size of the current block, including the
1659
102
  // size of the header itself.
1660
102
  uint32_t Size = sizeof(*Header) +
1661
102
      sizeof(coff_base_reloc_block_entry) * (Index + 1);
1662
102
  if (Size == Header->BlockSize) {
1663
16
    // .reloc contains a list of base relocation blocks. Each block
1664
16
    // consists of the header followed by entries. The header contains
1665
16
    // how many entories will follow. When we reach the end of the
1666
16
    // current block, proceed to the next block.
1667
16
    Header = reinterpret_cast<const coff_base_reloc_block_header *>(
1668
16
        reinterpret_cast<const uint8_t *>(Header) + Size);
1669
16
    Index = 0;
1670
86
  } else {
1671
86
    ++Index;
1672
86
  }
1673
102
}
1674
1675
102
std::error_code BaseRelocRef::getType(uint8_t &Type) const {
1676
102
  auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
1677
102
  Type = Entry[Index].getType();
1678
102
  return std::error_code();
1679
102
}
1680
1681
102
std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
1682
102
  auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
1683
102
  Result = Header->PageRVA + Entry[Index].getOffset();
1684
102
  return std::error_code();
1685
102
}
1686
1687
#define RETURN_IF_ERROR(E)                                                     \
1688
187
  if (E)                                                                       \
1689
187
    
return E0
;
1690
1691
Expected<ArrayRef<UTF16>>
1692
28
ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1693
28
  BinaryStreamReader Reader = BinaryStreamReader(BBS);
1694
28
  Reader.setOffset(Offset);
1695
28
  uint16_t Length;
1696
28
  RETURN_IF_ERROR(Reader.readInteger(Length));
1697
28
  ArrayRef<UTF16> RawDirString;
1698
28
  RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1699
28
  return RawDirString;
1700
28
}
1701
1702
Expected<ArrayRef<UTF16>>
1703
28
ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1704
28
  return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1705
28
}
1706
1707
Expected<const coff_resource_dir_table &>
1708
131
ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1709
131
  const coff_resource_dir_table *Table = nullptr;
1710
131
1711
131
  BinaryStreamReader Reader(BBS);
1712
131
  Reader.setOffset(Offset);
1713
131
  RETURN_IF_ERROR(Reader.readObject(Table));
1714
131
  assert(Table != nullptr);
1715
131
  return *Table;
1716
131
}
1717
1718
Expected<const coff_resource_dir_table &>
1719
124
ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1720
124
  return getTableAtOffset(Entry.Offset.value());
1721
124
}
1722
1723
7
Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1724
7
  return getTableAtOffset(0);
1725
7
}