Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Object/XCOFFObjectFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- XCOFFObjectFile.cpp - XCOFF 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 defines the XCOFFObjectFile class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/Object/XCOFFObjectFile.h"
14
#include <cstddef>
15
#include <cstring>
16
17
namespace llvm {
18
namespace object {
19
20
// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
21
// 'M'. Returns a pointer to the underlying object on success.
22
template <typename T>
23
static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
24
33
                                     const uint64_t Size = sizeof(T)) {
25
33
  uintptr_t Addr = uintptr_t(Ptr);
26
33
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
27
2
    return errorCodeToError(EC);
28
31
  return reinterpret_cast<const T *>(Addr);
29
31
}
XCOFFObjectFile.cpp:llvm::Expected<char const*> llvm::object::getObject<char>(llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
24
5
                                     const uint64_t Size = sizeof(T)) {
25
5
  uintptr_t Addr = uintptr_t(Ptr);
26
5
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
27
0
    return errorCodeToError(EC);
28
5
  return reinterpret_cast<const T *>(Addr);
29
5
}
XCOFFObjectFile.cpp:llvm::Expected<void const*> llvm::object::getObject<void>(llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
24
22
                                     const uint64_t Size = sizeof(T)) {
25
22
  uintptr_t Addr = uintptr_t(Ptr);
26
22
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
27
2
    return errorCodeToError(EC);
28
20
  return reinterpret_cast<const T *>(Addr);
29
20
}
XCOFFObjectFile.cpp:llvm::Expected<llvm::object::XCOFFSymbolEntry const*> llvm::object::getObject<llvm::object::XCOFFSymbolEntry>(llvm::MemoryBufferRef, void const*, unsigned long long)
Line
Count
Source
24
6
                                     const uint64_t Size = sizeof(T)) {
25
6
  uintptr_t Addr = uintptr_t(Ptr);
26
6
  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
27
0
    return errorCodeToError(EC);
28
6
  return reinterpret_cast<const T *>(Addr);
29
6
}
30
31
14
static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
32
14
  return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
33
14
                                     Offset);
34
14
}
35
36
97
template <typename T> static const T *viewAs(uintptr_t in) {
37
97
  return reinterpret_cast<const T *>(in);
38
97
}
XCOFFObjectFile.cpp:llvm::object::XCOFFSectionHeader32 const* llvm::object::viewAs<llvm::object::XCOFFSectionHeader32>(unsigned long)
Line
Count
Source
36
64
template <typename T> static const T *viewAs(uintptr_t in) {
37
64
  return reinterpret_cast<const T *>(in);
38
64
}
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::XCOFFSectionHeader64 const* llvm::object::viewAs<llvm::object::XCOFFSectionHeader64>(unsigned long)
XCOFFObjectFile.cpp:llvm::object::XCOFFSymbolEntry const* llvm::object::viewAs<llvm::object::XCOFFSymbolEntry>(unsigned long)
Line
Count
Source
36
33
template <typename T> static const T *viewAs(uintptr_t in) {
37
33
  return reinterpret_cast<const T *>(in);
38
33
}
39
40
36
static StringRef generateStringRef(const char *Name, uint64_t Size) {
41
36
  auto NulCharPtr = static_cast<const char *>(memchr(Name, '\0', Size));
42
36
  return NulCharPtr ? 
StringRef(Name, NulCharPtr - Name)33
43
36
                    : 
StringRef(Name, Size)3
;
44
36
}
45
46
void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
47
0
                                          uintptr_t TableAddress) const {
48
0
  if (Addr < TableAddress)
49
0
    report_fatal_error("Section header outside of section header table.");
50
0
51
0
  uintptr_t Offset = Addr - TableAddress;
52
0
  if (Offset >= getSectionHeaderSize() * getNumberOfSections())
53
0
    report_fatal_error("Section header outside of section header table.");
54
0
55
0
  if (Offset % getSectionHeaderSize() != 0)
56
0
    report_fatal_error(
57
0
        "Section header pointer does not point to a valid section header.");
58
0
}
59
60
const XCOFFSectionHeader32 *
61
64
XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
62
64
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
63
#ifndef NDEBUG
64
  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
65
#endif
66
  return viewAs<XCOFFSectionHeader32>(Ref.p);
67
64
}
68
69
const XCOFFSectionHeader64 *
70
0
XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
71
0
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
72
#ifndef NDEBUG
73
  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
74
#endif
75
  return viewAs<XCOFFSectionHeader64>(Ref.p);
76
0
}
77
78
33
const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
79
33
  assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
80
33
  assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
81
33
  auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
82
33
  return SymEntPtr;
83
33
}
84
85
111
const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
86
111
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
87
111
  return static_cast<const XCOFFFileHeader32 *>(FileHeader);
88
111
}
89
90
14
const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
91
14
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
92
14
  return static_cast<const XCOFFFileHeader64 *>(FileHeader);
93
14
}
94
95
const XCOFFSectionHeader32 *
96
9
XCOFFObjectFile::sectionHeaderTable32() const {
97
9
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
98
9
  return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
99
9
}
100
101
const XCOFFSectionHeader64 *
102
1
XCOFFObjectFile::sectionHeaderTable64() const {
103
1
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
104
1
  return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
105
1
}
106
107
11
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
108
11
  const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
109
11
  SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
110
11
  Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
111
11
}
112
113
11
Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
114
11
  const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
115
11
116
11
  if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
117
9
    return generateStringRef(SymEntPtr->SymbolName, XCOFF::SymbolNameSize);
118
2
119
2
  // A storage class value with the high-order bit on indicates that the name is
120
2
  // a symbolic debugger stabstring.
121
2
  if (SymEntPtr->StorageClass & 0x80)
122
0
    return StringRef("Unimplemented Debug Name");
123
2
124
2
  uint32_t Offset = SymEntPtr->NameInStrTbl.Offset;
125
2
  // The byte offset is relative to the start of the string table
126
2
  // or .debug section. A byte offset value of 0 is a null or zero-length symbol
127
2
  // name. A byte offset in the range 1 to 3 (inclusive) points into the length
128
2
  // field; as a soft-error recovery mechanism, we treat such cases as having an
129
2
  // offset of 0.
130
2
  if (Offset < 4)
131
0
    return StringRef(nullptr, 0);
132
2
133
2
  if (StringTable.Data != nullptr && StringTable.Size > Offset)
134
2
    return (StringTable.Data + Offset);
135
0
136
0
  return make_error<GenericBinaryError>("Symbol Name parse failed",
137
0
                                        object_error::parse_failed);
138
0
}
139
140
0
Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
141
0
  uint64_t Result = 0;
142
0
  llvm_unreachable("Not yet implemented!");
143
0
  return Result;
144
0
}
145
146
0
uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
147
0
  return toSymbolEntry(Symb)->Value;
148
0
}
149
150
0
uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
151
0
  uint64_t Result = 0;
152
0
  llvm_unreachable("Not yet implemented!");
153
0
  return Result;
154
0
}
155
156
Expected<SymbolRef::Type>
157
0
XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
158
0
  llvm_unreachable("Not yet implemented!");
159
0
  return SymbolRef::ST_Other;
160
0
}
161
162
Expected<section_iterator>
163
0
XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
164
0
  const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
165
0
  int16_t SectNum = SymEntPtr->SectionNumber;
166
0
167
0
  if (isReservedSectionNumber(SectNum))
168
0
    return section_end();
169
0
170
0
  Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
171
0
  if (!ExpSec)
172
0
    return ExpSec.takeError();
173
0
174
0
  return section_iterator(SectionRef(ExpSec.get(), this));
175
0
}
176
177
8
void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
178
8
  const char *Ptr = reinterpret_cast<const char *>(Sec.p);
179
8
  Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
180
8
}
181
182
8
Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
183
8
  return generateStringRef(getSectionNameInternal(Sec), XCOFF::SectionNameSize);
184
8
}
185
186
8
uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
187
8
  // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
188
8
  // with MSVC.
189
8
  if (is64Bit())
190
0
    return toSection64(Sec)->VirtualAddress;
191
8
192
8
  return toSection32(Sec)->VirtualAddress;
193
8
}
194
195
8
uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
196
8
  // Section numbers in XCOFF are numbered beginning at 1. A section number of
197
8
  // zero is used to indicate that a symbol is being imported or is undefined.
198
8
  if (is64Bit())
199
0
    return toSection64(Sec) - sectionHeaderTable64() + 1;
200
8
  else
201
8
    return toSection32(Sec) - sectionHeaderTable32() + 1;
202
8
}
203
204
8
uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
205
8
  // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
206
8
  // with MSVC.
207
8
  if (is64Bit())
208
0
    return toSection64(Sec)->SectionSize;
209
8
210
8
  return toSection32(Sec)->SectionSize;
211
8
}
212
213
Expected<ArrayRef<uint8_t>>
214
0
XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
215
0
  llvm_unreachable("Not yet implemented!");
216
0
}
217
218
0
uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
219
0
  uint64_t Result = 0;
220
0
  llvm_unreachable("Not yet implemented!");
221
0
  return Result;
222
0
}
223
224
0
bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
225
0
  bool Result = false;
226
0
  llvm_unreachable("Not yet implemented!");
227
0
  return Result;
228
0
}
229
230
8
bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
231
8
  return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
232
8
}
233
234
8
bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
235
8
  uint32_t Flags = getSectionFlags(Sec);
236
8
  return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
237
8
}
238
239
8
bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
240
8
  uint32_t Flags = getSectionFlags(Sec);
241
8
  return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
242
8
}
243
244
0
bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
245
0
  bool Result = false;
246
0
  llvm_unreachable("Not yet implemented!");
247
0
  return Result;
248
0
}
249
250
0
relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
251
0
  llvm_unreachable("Not yet implemented!");
252
0
  return relocation_iterator(RelocationRef());
253
0
}
254
255
0
relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
256
0
  llvm_unreachable("Not yet implemented!");
257
0
  return relocation_iterator(RelocationRef());
258
0
}
259
260
0
void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
261
0
  llvm_unreachable("Not yet implemented!");
262
0
  return;
263
0
}
264
265
0
uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
266
0
  llvm_unreachable("Not yet implemented!");
267
0
  uint64_t Result = 0;
268
0
  return Result;
269
0
}
270
271
0
symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
272
0
  llvm_unreachable("Not yet implemented!");
273
0
  return symbol_iterator(SymbolRef());
274
0
}
275
276
0
uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
277
0
  llvm_unreachable("Not yet implemented!");
278
0
  uint64_t Result = 0;
279
0
  return Result;
280
0
}
281
282
void XCOFFObjectFile::getRelocationTypeName(
283
0
    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
284
0
  llvm_unreachable("Not yet implemented!");
285
0
  return;
286
0
}
287
288
0
uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
289
0
  uint32_t Result = 0;
290
0
  llvm_unreachable("Not yet implemented!");
291
0
  return Result;
292
0
}
293
294
1
basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
295
1
  assert(!is64Bit() && "64-bit support not implemented yet.");
296
1
  DataRefImpl SymDRI;
297
1
  SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
298
1
  return basic_symbol_iterator(SymbolRef(SymDRI, this));
299
1
}
300
301
1
basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
302
1
  assert(!is64Bit() && "64-bit support not implemented yet.");
303
1
  DataRefImpl SymDRI;
304
1
  SymDRI.p = reinterpret_cast<uintptr_t>(
305
1
      SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
306
1
  return basic_symbol_iterator(SymbolRef(SymDRI, this));
307
1
}
308
309
2
section_iterator XCOFFObjectFile::section_begin() const {
310
2
  DataRefImpl DRI;
311
2
  DRI.p = getSectionHeaderTableAddress();
312
2
  return section_iterator(SectionRef(DRI, this));
313
2
}
314
315
6
section_iterator XCOFFObjectFile::section_end() const {
316
6
  DataRefImpl DRI;
317
6
  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
318
6
                        getNumberOfSections() * getSectionHeaderSize());
319
6
  return section_iterator(SectionRef(DRI, this));
320
6
}
321
322
7
uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 
82
:
45
; }
323
324
9
StringRef XCOFFObjectFile::getFileFormatName() const {
325
9
  return is64Bit() ? 
"aix5coff64-rs6000"2
:
"aixcoff-rs6000"7
;
326
9
}
327
328
7
Triple::ArchType XCOFFObjectFile::getArch() const {
329
7
  return is64Bit() ? 
Triple::ppc642
:
Triple::ppc5
;
330
7
}
331
332
0
SubtargetFeatures XCOFFObjectFile::getFeatures() const {
333
0
  llvm_unreachable("Not yet implemented!");
334
0
  return SubtargetFeatures();
335
0
}
336
337
0
bool XCOFFObjectFile::isRelocatableObject() const {
338
0
  bool Result = false;
339
0
  llvm_unreachable("Not yet implemented!");
340
0
  return Result;
341
0
}
342
343
0
Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
344
0
  // TODO FIXME Should get from auxiliary_header->o_entry when support for the
345
0
  // auxiliary_header is added.
346
0
  return 0;
347
0
}
348
349
23
size_t XCOFFObjectFile::getFileHeaderSize() const {
350
23
  return is64Bit() ? 
sizeof(XCOFFFileHeader64)4
:
sizeof(XCOFFFileHeader32)19
;
351
23
}
352
353
32
size_t XCOFFObjectFile::getSectionHeaderSize() const {
354
32
  return is64Bit() ? 
sizeof(XCOFFSectionHeader64)2
:
355
32
                     
sizeof(XCOFFSectionHeader32)30
;
356
32
}
357
358
238
bool XCOFFObjectFile::is64Bit() const {
359
238
  return Binary::ID_XCOFF64 == getType();
360
238
}
361
362
6
uint16_t XCOFFObjectFile::getMagic() const {
363
6
  return is64Bit() ? 
fileHeader64()->Magic1
:
fileHeader32()->Magic5
;
364
6
}
365
366
8
Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
367
8
  if (Num <= 0 || Num > getNumberOfSections())
368
0
    return errorCodeToError(object_error::invalid_section_index);
369
8
370
8
  DataRefImpl DRI;
371
8
  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
372
8
                        getSectionHeaderSize() * (Num - 1));
373
8
  return DRI;
374
8
}
375
376
Expected<StringRef>
377
11
XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
378
11
  assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
379
11
  int16_t SectionNum = SymEntPtr->SectionNumber;
380
11
381
11
  switch (SectionNum) {
382
11
  case XCOFF::N_DEBUG:
383
1
    return "N_DEBUG";
384
11
  case XCOFF::N_ABS:
385
0
    return "N_ABS";
386
11
  case XCOFF::N_UNDEF:
387
2
    return "N_UNDEF";
388
11
  default:
389
8
    Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
390
8
    if (SecRef)
391
8
      return generateStringRef(getSectionNameInternal(SecRef.get()),
392
8
                               XCOFF::SectionNameSize);
393
0
    return SecRef.takeError();
394
11
  }
395
11
}
396
397
0
bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
398
0
  return (SectionNumber <= 0 && SectionNumber >= -2);
399
0
}
400
401
43
uint16_t XCOFFObjectFile::getNumberOfSections() const {
402
43
  return is64Bit() ? 
fileHeader64()->NumberOfSections6
403
43
                   : 
fileHeader32()->NumberOfSections37
;
404
43
}
405
406
6
int32_t XCOFFObjectFile::getTimeStamp() const {
407
6
  return is64Bit() ? 
fileHeader64()->TimeStamp1
:
fileHeader32()->TimeStamp5
;
408
6
}
409
410
17
uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
411
17
  return is64Bit() ? 
fileHeader64()->AuxHeaderSize3
412
17
                   : 
fileHeader32()->AuxHeaderSize14
;
413
17
}
414
415
5
uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
416
5
  return fileHeader32()->SymbolTableOffset;
417
5
}
418
419
5
int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
420
5
  // As far as symbol table size is concerned, if this field is negative it is
421
5
  // to be treated as a 0. However since this field is also used for printing we
422
5
  // don't want to truncate any negative values.
423
5
  return fileHeader32()->NumberOfSymTableEntries;
424
5
}
425
426
15
uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
427
15
  return (fileHeader32()->NumberOfSymTableEntries >= 0
428
15
              ? 
fileHeader32()->NumberOfSymTableEntries14
429
15
              : 
01
);
430
15
}
431
432
1
uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
433
1
  return fileHeader64()->SymbolTableOffset;
434
1
}
435
436
1
uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
437
1
  return fileHeader64()->NumberOfSymTableEntries;
438
1
}
439
440
6
uint16_t XCOFFObjectFile::getFlags() const {
441
6
  return is64Bit() ? 
fileHeader64()->Flags1
:
fileHeader32()->Flags5
;
442
6
}
443
444
16
const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
445
16
  return is64Bit() ? 
toSection64(Sec)->Name0
: toSection32(Sec)->Name;
446
16
}
447
448
16
uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
449
16
  return reinterpret_cast<uintptr_t>(SectionHeaderTable);
450
16
}
451
452
24
int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
453
24
  return is64Bit() ? 
toSection64(Sec)->Flags0
: toSection32(Sec)->Flags;
454
24
}
455
456
XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
457
12
    : ObjectFile(Type, Object) {
458
12
  assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
459
12
}
460
461
1
ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
462
1
  assert(is64Bit() && "64-bit interface called for non 64-bit file.");
463
1
  const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
464
1
  return ArrayRef<XCOFFSectionHeader64>(TablePtr,
465
1
                                        TablePtr + getNumberOfSections());
466
1
}
467
468
1
ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
469
1
  assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
470
1
  const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
471
1
  return ArrayRef<XCOFFSectionHeader32>(TablePtr,
472
1
                                        TablePtr + getNumberOfSections());
473
1
}
474
475
Expected<XCOFFStringTable>
476
6
XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
477
6
  // If there is a string table, then the buffer must contain at least 4 bytes
478
6
  // for the string table's size. Not having a string table is not an error.
479
6
  if (auto EC = Binary::checkOffset(
480
1
          Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4))
481
1
    return XCOFFStringTable{0, nullptr};
482
5
483
5
  // Read the size out of the buffer.
484
5
  uint32_t Size = support::endian::read32be(Obj->base() + Offset);
485
5
486
5
  // If the size is less then 4, then the string table is just a size and no
487
5
  // string data.
488
5
  if (Size <= 4)
489
0
    return XCOFFStringTable{4, nullptr};
490
5
491
5
  auto StringTableOrErr =
492
5
      getObject<char>(Obj->Data, Obj->base() + Offset, Size);
493
5
  if (Error E = StringTableOrErr.takeError())
494
0
    return std::move(E);
495
5
496
5
  const char *StringTablePtr = StringTableOrErr.get();
497
5
  if (StringTablePtr[Size - 1] != '\0')
498
0
    return errorCodeToError(object_error::string_table_non_null_end);
499
5
500
5
  return XCOFFStringTable{Size, StringTablePtr};
501
5
}
502
503
Expected<std::unique_ptr<XCOFFObjectFile>>
504
12
XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
505
12
  // Can't use make_unique because of the private constructor.
506
12
  std::unique_ptr<XCOFFObjectFile> Obj;
507
12
  Obj.reset(new XCOFFObjectFile(Type, MBR));
508
12
509
12
  uint64_t CurOffset = 0;
510
12
  const auto *Base = Obj->base();
511
12
  MemoryBufferRef Data = Obj->Data;
512
12
513
12
  // Parse file header.
514
12
  auto FileHeaderOrErr =
515
12
      getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
516
12
  if (Error E = FileHeaderOrErr.takeError())
517
1
    return std::move(E);
518
11
  Obj->FileHeader = FileHeaderOrErr.get();
519
11
520
11
  CurOffset += Obj->getFileHeaderSize();
521
11
  // TODO FIXME we don't have support for an optional header yet, so just skip
522
11
  // past it.
523
11
  CurOffset += Obj->getOptionalHeaderSize();
524
11
525
11
  // Parse the section header table if it is present.
526
11
  if (Obj->getNumberOfSections()) {
527
10
    auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
528
10
                                           Obj->getNumberOfSections() *
529
10
                                               Obj->getSectionHeaderSize());
530
10
    if (Error E = SecHeadersOrErr.takeError())
531
1
      return std::move(E);
532
9
    Obj->SectionHeaderTable = SecHeadersOrErr.get();
533
9
  }
534
11
535
11
  // 64-bit object supports only file header and section headers for now.
536
11
  
if (10
Obj->is64Bit()10
)
537
2
    return std::move(Obj);
538
8
539
8
  // If there is no symbol table we are done parsing the memory buffer.
540
8
  if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
541
2
    return std::move(Obj);
542
6
543
6
  // Parse symbol table.
544
6
  CurOffset = Obj->fileHeader32()->SymbolTableOffset;
545
6
  uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
546
6
                             Obj->getLogicalNumberOfSymbolTableEntries32();
547
6
  auto SymTableOrErr =
548
6
      getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
549
6
  if (Error E = SymTableOrErr.takeError())
550
0
    return std::move(E);
551
6
  Obj->SymbolTblPtr = SymTableOrErr.get();
552
6
  CurOffset += SymbolTableSize;
553
6
554
6
  // Parse String table.
555
6
  Expected<XCOFFStringTable> StringTableOrErr =
556
6
      parseStringTable(Obj.get(), CurOffset);
557
6
  if (Error E = StringTableOrErr.takeError())
558
0
    return std::move(E);
559
6
  Obj->StringTable = StringTableOrErr.get();
560
6
561
6
  return std::move(Obj);
562
6
}
563
564
Expected<std::unique_ptr<ObjectFile>>
565
ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
566
12
                                  unsigned FileType) {
567
12
  return XCOFFObjectFile::create(FileType, MemBufRef);
568
12
}
569
570
6
StringRef XCOFFSectionHeader32::getName() const {
571
6
  return generateStringRef(Name, XCOFF::SectionNameSize);
572
6
}
573
574
5
StringRef XCOFFSectionHeader64::getName() const {
575
5
  return generateStringRef(Name, XCOFF::SectionNameSize);
576
5
}
577
578
} // namespace object
579
} // namespace llvm