Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/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 "llvm/ADT/StringSwitch.h"
15
#include "llvm/Support/DataExtractor.h"
16
#include "llvm/TargetParser/SubtargetFeature.h"
17
#include <cstddef>
18
#include <cstring>
19
20
namespace llvm {
21
22
using namespace XCOFF;
23
24
namespace object {
25
26
static const uint8_t FunctionSym = 0x20;
27
static const uint16_t NoRelMask = 0x0001;
28
static const size_t SymbolAuxTypeOffset = 17;
29
30
// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
31
// 'M'. Returns a pointer to the underlying object on success.
32
template <typename T>
33
static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
34
0
                                     const uint64_t Size = sizeof(T)) {
35
0
  uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
36
0
  if (Error E = Binary::checkOffset(M, Addr, Size))
37
0
    return std::move(E);
38
0
  return reinterpret_cast<const T *>(Addr);
39
0
}
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::Expected<char const*> llvm::object::getObject<char>(llvm::MemoryBufferRef, void const*, unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::Expected<void const*> llvm::object::getObject<void>(llvm::MemoryBufferRef, void const*, unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::Expected<void* const*> llvm::object::getObject<void*>(llvm::MemoryBufferRef, void const*, unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::Expected<llvm::object::XCOFFRelocation64 const*> llvm::object::getObject<llvm::object::XCOFFRelocation64>(llvm::MemoryBufferRef, void const*, unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::Expected<llvm::object::XCOFFRelocation32 const*> llvm::object::getObject<llvm::object::XCOFFRelocation32>(llvm::MemoryBufferRef, void const*, unsigned long)
40
41
0
static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
42
0
  return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
43
0
                                     Offset);
44
0
}
45
46
0
template <typename T> static const T *viewAs(uintptr_t in) {
47
0
  return reinterpret_cast<const T *>(in);
48
0
}
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::XCOFF::SymbolAuxType const* llvm::object::viewAs<llvm::XCOFF::SymbolAuxType>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::XCOFFSectionHeader32 const* llvm::object::viewAs<llvm::object::XCOFFSectionHeader32>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::XCOFFSectionHeader64 const* llvm::object::viewAs<llvm::object::XCOFFSectionHeader64>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::XCOFFRelocation64 const* llvm::object::viewAs<llvm::object::XCOFFRelocation64>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::XCOFFRelocation32 const* llvm::object::viewAs<llvm::object::XCOFFRelocation32>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::LoaderSectionHeader64 const* llvm::object::viewAs<llvm::object::LoaderSectionHeader64>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::LoaderSectionHeader32 const* llvm::object::viewAs<llvm::object::LoaderSectionHeader32>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::XCOFFCsectAuxEnt32 const* llvm::object::viewAs<llvm::object::XCOFFCsectAuxEnt32>(unsigned long)
Unexecuted instantiation: XCOFFObjectFile.cpp:llvm::object::XCOFFCsectAuxEnt64 const* llvm::object::viewAs<llvm::object::XCOFFCsectAuxEnt64>(unsigned long)
49
50
0
static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
51
0
  auto NulCharPtr =
52
0
      static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
53
0
  return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
54
0
                    : StringRef(Name, XCOFF::NameSize);
55
0
}
56
57
0
template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
58
0
  const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
59
0
  return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
60
0
}
Unexecuted instantiation: llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader32>::getName() const
Unexecuted instantiation: llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader64>::getName() const
61
62
0
template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
63
0
  const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
64
0
  return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
65
0
}
Unexecuted instantiation: llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader32>::getSectionType() const
Unexecuted instantiation: llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader64>::getSectionType() const
66
67
template <typename T>
68
0
bool XCOFFSectionHeader<T>::isReservedSectionType() const {
69
0
  return getSectionType() & SectionFlagsReservedMask;
70
0
}
Unexecuted instantiation: llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader32>::isReservedSectionType() const
Unexecuted instantiation: llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader64>::isReservedSectionType() const
71
72
template <typename AddressType>
73
0
bool XCOFFRelocation<AddressType>::isRelocationSigned() const {
74
0
  return Info & XR_SIGN_INDICATOR_MASK;
75
0
}
Unexecuted instantiation: llvm::object::XCOFFRelocation<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::endianness)0, 1ul, 1ul> >::isRelocationSigned() const
Unexecuted instantiation: llvm::object::XCOFFRelocation<llvm::support::detail::packed_endian_specific_integral<unsigned long, (llvm::endianness)0, 1ul, 1ul> >::isRelocationSigned() const
76
77
template <typename AddressType>
78
0
bool XCOFFRelocation<AddressType>::isFixupIndicated() const {
79
0
  return Info & XR_FIXUP_INDICATOR_MASK;
80
0
}
Unexecuted instantiation: llvm::object::XCOFFRelocation<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::endianness)0, 1ul, 1ul> >::isFixupIndicated() const
Unexecuted instantiation: llvm::object::XCOFFRelocation<llvm::support::detail::packed_endian_specific_integral<unsigned long, (llvm::endianness)0, 1ul, 1ul> >::isFixupIndicated() const
81
82
template <typename AddressType>
83
0
uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
84
  // The relocation encodes the bit length being relocated minus 1. Add back
85
  // the 1 to get the actual length being relocated.
86
0
  return (Info & XR_BIASED_LENGTH_MASK) + 1;
87
0
}
Unexecuted instantiation: llvm::object::XCOFFRelocation<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::endianness)0, 1ul, 1ul> >::getRelocatedLength() const
Unexecuted instantiation: llvm::object::XCOFFRelocation<llvm::support::detail::packed_endian_specific_integral<unsigned long, (llvm::endianness)0, 1ul, 1ul> >::getRelocatedLength() const
88
89
template struct ExceptionSectionEntry<support::ubig32_t>;
90
template struct ExceptionSectionEntry<support::ubig64_t>;
91
92
template <typename T>
93
Expected<StringRef> getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader,
94
0
                                                uint64_t Offset) {
95
0
  if (LoaderSecHeader->LengthOfStrTbl > Offset)
96
0
    return (reinterpret_cast<const char *>(LoaderSecHeader) +
97
0
            LoaderSecHeader->OffsetToStrTbl + Offset);
98
99
0
  return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
100
0
                     " in the loader section's string table with size 0x" +
101
0
                     Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) +
102
0
                     " is invalid");
103
0
}
Unexecuted instantiation: llvm::Expected<llvm::StringRef> llvm::object::getLoaderSecSymNameInStrTbl<llvm::object::LoaderSectionHeader32>(llvm::object::LoaderSectionHeader32 const*, unsigned long)
Unexecuted instantiation: llvm::Expected<llvm::StringRef> llvm::object::getLoaderSecSymNameInStrTbl<llvm::object::LoaderSectionHeader64>(llvm::object::LoaderSectionHeader64 const*, unsigned long)
104
105
Expected<StringRef> LoaderSectionSymbolEntry32::getSymbolName(
106
0
    const LoaderSectionHeader32 *LoaderSecHeader32) const {
107
0
  const NameOffsetInStrTbl *NameInStrTbl =
108
0
      reinterpret_cast<const NameOffsetInStrTbl *>(SymbolName);
109
0
  if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
110
0
    return generateXCOFFFixedNameStringRef(SymbolName);
111
112
0
  return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset);
113
0
}
114
115
Expected<StringRef> LoaderSectionSymbolEntry64::getSymbolName(
116
0
    const LoaderSectionHeader64 *LoaderSecHeader64) const {
117
0
  return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset);
118
0
}
119
120
uintptr_t
121
XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
122
0
                                               uint32_t Distance) {
123
0
  return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
124
0
}
125
126
const XCOFF::SymbolAuxType *
127
0
XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
128
0
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
129
0
  return viewAs<XCOFF::SymbolAuxType>(
130
0
      getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
131
0
}
132
133
void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
134
0
                                          uintptr_t TableAddress) const {
135
0
  if (Addr < TableAddress)
136
0
    report_fatal_error("Section header outside of section header table.");
137
138
0
  uintptr_t Offset = Addr - TableAddress;
139
0
  if (Offset >= getSectionHeaderSize() * getNumberOfSections())
140
0
    report_fatal_error("Section header outside of section header table.");
141
142
0
  if (Offset % getSectionHeaderSize() != 0)
143
0
    report_fatal_error(
144
0
        "Section header pointer does not point to a valid section header.");
145
0
}
146
147
const XCOFFSectionHeader32 *
148
0
XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
149
0
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
150
0
#ifndef NDEBUG
151
0
  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
152
0
#endif
153
0
  return viewAs<XCOFFSectionHeader32>(Ref.p);
154
0
}
155
156
const XCOFFSectionHeader64 *
157
0
XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
158
0
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
159
0
#ifndef NDEBUG
160
0
  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
161
0
#endif
162
0
  return viewAs<XCOFFSectionHeader64>(Ref.p);
163
0
}
164
165
0
XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
166
0
  assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
167
0
#ifndef NDEBUG
168
0
  checkSymbolEntryPointer(Ref.p);
169
0
#endif
170
0
  return XCOFFSymbolRef(Ref, this);
171
0
}
172
173
0
const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
174
0
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
175
0
  return static_cast<const XCOFFFileHeader32 *>(FileHeader);
176
0
}
177
178
0
const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
179
0
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
180
0
  return static_cast<const XCOFFFileHeader64 *>(FileHeader);
181
0
}
182
183
0
const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
184
0
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
185
0
  return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
186
0
}
187
188
0
const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
189
0
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
190
0
  return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
191
0
}
192
193
0
template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
194
0
  return static_cast<const T *>(SectionHeaderTable);
195
0
}
Unexecuted instantiation: llvm::object::XCOFFSectionHeader64 const* llvm::object::XCOFFObjectFile::sectionHeaderTable<llvm::object::XCOFFSectionHeader64>() const
Unexecuted instantiation: llvm::object::XCOFFSectionHeader32 const* llvm::object::XCOFFObjectFile::sectionHeaderTable<llvm::object::XCOFFSectionHeader32>() const
196
197
const XCOFFSectionHeader32 *
198
0
XCOFFObjectFile::sectionHeaderTable32() const {
199
0
  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
200
0
  return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
201
0
}
202
203
const XCOFFSectionHeader64 *
204
0
XCOFFObjectFile::sectionHeaderTable64() const {
205
0
  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
206
0
  return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
207
0
}
208
209
0
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
210
0
  uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
211
0
      Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
212
0
#ifndef NDEBUG
213
  // This function is used by basic_symbol_iterator, which allows to
214
  // point to the end-of-symbol-table address.
215
0
  if (NextSymbolAddr != getEndOfSymbolTableAddress())
216
0
    checkSymbolEntryPointer(NextSymbolAddr);
217
0
#endif
218
0
  Symb.p = NextSymbolAddr;
219
0
}
220
221
Expected<StringRef>
222
0
XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
223
  // The byte offset is relative to the start of the string table.
224
  // A byte offset value of 0 is a null or zero-length symbol
225
  // name. A byte offset in the range 1 to 3 (inclusive) points into the length
226
  // field; as a soft-error recovery mechanism, we treat such cases as having an
227
  // offset of 0.
228
0
  if (Offset < 4)
229
0
    return StringRef(nullptr, 0);
230
231
0
  if (StringTable.Data != nullptr && StringTable.Size > Offset)
232
0
    return (StringTable.Data + Offset);
233
234
0
  return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
235
0
                     " in a string table with size 0x" +
236
0
                     Twine::utohexstr(StringTable.Size) + " is invalid");
237
0
}
238
239
0
StringRef XCOFFObjectFile::getStringTable() const {
240
  // If the size is less than or equal to 4, then the string table contains no
241
  // string data.
242
0
  return StringRef(StringTable.Data,
243
0
                   StringTable.Size <= 4 ? 0 : StringTable.Size);
244
0
}
245
246
Expected<StringRef>
247
0
XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
248
0
  if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
249
0
    return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
250
0
  return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
251
0
}
252
253
0
Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
254
0
  return toSymbolRef(Symb).getName();
255
0
}
256
257
0
Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
258
0
  return toSymbolRef(Symb).getValue();
259
0
}
260
261
0
uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
262
0
  return toSymbolRef(Symb).getValue();
263
0
}
264
265
0
uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
266
0
  uint64_t Result = 0;
267
0
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
268
0
  if (XCOFFSym.isCsectSymbol()) {
269
0
    Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
270
0
        XCOFFSym.getXCOFFCsectAuxRef();
271
0
    if (!CsectAuxRefOrError)
272
      // TODO: report the error up the stack.
273
0
      consumeError(CsectAuxRefOrError.takeError());
274
0
    else
275
0
      Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2();
276
0
  }
277
0
  return Result;
278
0
}
279
280
0
uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
281
0
  uint64_t Result = 0;
282
0
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
283
0
  if (XCOFFSym.isCsectSymbol()) {
284
0
    Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
285
0
        XCOFFSym.getXCOFFCsectAuxRef();
286
0
    if (!CsectAuxRefOrError)
287
      // TODO: report the error up the stack.
288
0
      consumeError(CsectAuxRefOrError.takeError());
289
0
    else {
290
0
      XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
291
0
      assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM);
292
0
      Result = CsectAuxRef.getSectionOrLength();
293
0
    }
294
0
  }
295
0
  return Result;
296
0
}
297
298
Expected<SymbolRef::Type>
299
0
XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
300
0
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
301
302
0
  Expected<bool> IsFunction = XCOFFSym.isFunction();
303
0
  if (!IsFunction)
304
0
    return IsFunction.takeError();
305
306
0
  if (*IsFunction)
307
0
    return SymbolRef::ST_Function;
308
309
0
  if (XCOFF::C_FILE == XCOFFSym.getStorageClass())
310
0
    return SymbolRef::ST_File;
311
312
0
  int16_t SecNum = XCOFFSym.getSectionNumber();
313
0
  if (SecNum <= 0)
314
0
    return SymbolRef::ST_Other;
315
316
0
  Expected<DataRefImpl> SecDRIOrErr =
317
0
      getSectionByNum(XCOFFSym.getSectionNumber());
318
319
0
  if (!SecDRIOrErr)
320
0
    return SecDRIOrErr.takeError();
321
322
0
  DataRefImpl SecDRI = SecDRIOrErr.get();
323
324
0
  Expected<StringRef> SymNameOrError = XCOFFSym.getName();
325
0
  if (SymNameOrError) {
326
    // The "TOC" symbol is treated as SymbolRef::ST_Other.
327
0
    if (SymNameOrError.get() == "TOC")
328
0
      return SymbolRef::ST_Other;
329
330
    // The symbol for a section name is treated as SymbolRef::ST_Other.
331
0
    StringRef SecName;
332
0
    if (is64Bit())
333
0
      SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName();
334
0
    else
335
0
      SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName();
336
337
0
    if (SecName == SymNameOrError.get())
338
0
      return SymbolRef::ST_Other;
339
0
  } else
340
0
    return SymNameOrError.takeError();
341
342
0
  if (isSectionData(SecDRI) || isSectionBSS(SecDRI))
343
0
    return SymbolRef::ST_Data;
344
345
0
  if (isDebugSection(SecDRI))
346
0
    return SymbolRef::ST_Debug;
347
348
0
  return SymbolRef::ST_Other;
349
0
}
350
351
Expected<section_iterator>
352
0
XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
353
0
  const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
354
355
0
  if (isReservedSectionNumber(SectNum))
356
0
    return section_end();
357
358
0
  Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
359
0
  if (!ExpSec)
360
0
    return ExpSec.takeError();
361
362
0
  return section_iterator(SectionRef(ExpSec.get(), this));
363
0
}
364
365
0
void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
366
0
  const char *Ptr = reinterpret_cast<const char *>(Sec.p);
367
0
  Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
368
0
}
369
370
0
Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
371
0
  return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
372
0
}
373
374
0
uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
375
  // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
376
  // with MSVC.
377
0
  if (is64Bit())
378
0
    return toSection64(Sec)->VirtualAddress;
379
380
0
  return toSection32(Sec)->VirtualAddress;
381
0
}
382
383
0
uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
384
  // Section numbers in XCOFF are numbered beginning at 1. A section number of
385
  // zero is used to indicate that a symbol is being imported or is undefined.
386
0
  if (is64Bit())
387
0
    return toSection64(Sec) - sectionHeaderTable64() + 1;
388
0
  else
389
0
    return toSection32(Sec) - sectionHeaderTable32() + 1;
390
0
}
391
392
0
uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
393
  // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
394
  // with MSVC.
395
0
  if (is64Bit())
396
0
    return toSection64(Sec)->SectionSize;
397
398
0
  return toSection32(Sec)->SectionSize;
399
0
}
400
401
Expected<ArrayRef<uint8_t>>
402
0
XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
403
0
  if (isSectionVirtual(Sec))
404
0
    return ArrayRef<uint8_t>();
405
406
0
  uint64_t OffsetToRaw;
407
0
  if (is64Bit())
408
0
    OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
409
0
  else
410
0
    OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
411
412
0
  const uint8_t * ContentStart = base() + OffsetToRaw;
413
0
  uint64_t SectionSize = getSectionSize(Sec);
414
0
  if (Error E = Binary::checkOffset(
415
0
          Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
416
0
    return createError(
417
0
        toString(std::move(E)) + ": section data with offset 0x" +
418
0
        Twine::utohexstr(OffsetToRaw) + " and size 0x" +
419
0
        Twine::utohexstr(SectionSize) + " goes past the end of the file");
420
421
0
  return ArrayRef(ContentStart, SectionSize);
422
0
}
423
424
0
uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
425
0
  uint64_t Result = 0;
426
0
  llvm_unreachable("Not yet implemented!");
427
0
  return Result;
428
0
}
429
430
0
uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const {
431
0
  if (is64Bit())
432
0
    return toSection64(Sec)->FileOffsetToRawData;
433
434
0
  return toSection32(Sec)->FileOffsetToRawData;
435
0
}
436
437
Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData(
438
0
    XCOFF::SectionTypeFlags SectType) const {
439
0
  DataRefImpl DRI = getSectionByType(SectType);
440
441
0
  if (DRI.p == 0) // No section is not an error.
442
0
    return 0;
443
444
0
  uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI);
445
0
  uint64_t SizeOfSection = getSectionSize(DRI);
446
447
0
  uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset);
448
0
  if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) {
449
0
    SmallString<32> UnknownType;
450
0
    Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">")
451
0
        .toVector(UnknownType);
452
0
    const char *SectionName = UnknownType.c_str();
453
454
0
    switch (SectType) {
455
0
#define ECASE(Value, String)                                                   \
456
0
  case XCOFF::Value:                                                           \
457
0
    SectionName = String;                                                      \
458
0
    break
459
460
0
      ECASE(STYP_PAD, "pad");
461
0
      ECASE(STYP_DWARF, "dwarf");
462
0
      ECASE(STYP_TEXT, "text");
463
0
      ECASE(STYP_DATA, "data");
464
0
      ECASE(STYP_BSS, "bss");
465
0
      ECASE(STYP_EXCEPT, "expect");
466
0
      ECASE(STYP_INFO, "info");
467
0
      ECASE(STYP_TDATA, "tdata");
468
0
      ECASE(STYP_TBSS, "tbss");
469
0
      ECASE(STYP_LOADER, "loader");
470
0
      ECASE(STYP_DEBUG, "debug");
471
0
      ECASE(STYP_TYPCHK, "typchk");
472
0
      ECASE(STYP_OVRFLO, "ovrflo");
473
0
#undef ECASE
474
0
    }
475
0
    return createError(toString(std::move(E)) + ": " + SectionName +
476
0
                       " section with offset 0x" +
477
0
                       Twine::utohexstr(SectionOffset) + " and size 0x" +
478
0
                       Twine::utohexstr(SizeOfSection) +
479
0
                       " goes past the end of the file");
480
0
  }
481
0
  return SectionStart;
482
0
}
483
484
0
bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
485
0
  return false;
486
0
}
487
488
0
bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
489
0
  return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
490
0
}
491
492
0
bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
493
0
  uint32_t Flags = getSectionFlags(Sec);
494
0
  return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
495
0
}
496
497
0
bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
498
0
  uint32_t Flags = getSectionFlags(Sec);
499
0
  return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
500
0
}
501
502
0
bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const {
503
0
  uint32_t Flags = getSectionFlags(Sec);
504
0
  return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF);
505
0
}
506
507
0
bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
508
0
  return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
509
0
                   : toSection32(Sec)->FileOffsetToRawData == 0;
510
0
}
511
512
0
relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
513
0
  DataRefImpl Ret;
514
0
  if (is64Bit()) {
515
0
    const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
516
0
    auto RelocationsOrErr =
517
0
        relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
518
0
    if (Error E = RelocationsOrErr.takeError()) {
519
      // TODO: report the error up the stack.
520
0
      consumeError(std::move(E));
521
0
      return relocation_iterator(RelocationRef());
522
0
    }
523
0
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
524
0
  } else {
525
0
    const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
526
0
    auto RelocationsOrErr =
527
0
        relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
528
0
    if (Error E = RelocationsOrErr.takeError()) {
529
      // TODO: report the error up the stack.
530
0
      consumeError(std::move(E));
531
0
      return relocation_iterator(RelocationRef());
532
0
    }
533
0
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
534
0
  }
535
0
  return relocation_iterator(RelocationRef(Ret, this));
536
0
}
537
538
0
relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
539
0
  DataRefImpl Ret;
540
0
  if (is64Bit()) {
541
0
    const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
542
0
    auto RelocationsOrErr =
543
0
        relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
544
0
    if (Error E = RelocationsOrErr.takeError()) {
545
      // TODO: report the error up the stack.
546
0
      consumeError(std::move(E));
547
0
      return relocation_iterator(RelocationRef());
548
0
    }
549
0
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
550
0
  } else {
551
0
    const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
552
0
    auto RelocationsOrErr =
553
0
        relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
554
0
    if (Error E = RelocationsOrErr.takeError()) {
555
      // TODO: report the error up the stack.
556
0
      consumeError(std::move(E));
557
0
      return relocation_iterator(RelocationRef());
558
0
    }
559
0
    Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
560
0
  }
561
0
  return relocation_iterator(RelocationRef(Ret, this));
562
0
}
563
564
0
void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
565
0
  if (is64Bit())
566
0
    Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1);
567
0
  else
568
0
    Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
569
0
}
570
571
0
uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
572
0
  if (is64Bit()) {
573
0
    const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
574
0
    const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64();
575
0
    const uint64_t RelocAddress = Reloc->VirtualAddress;
576
0
    const uint16_t NumberOfSections = getNumberOfSections();
577
0
    for (uint16_t I = 0; I < NumberOfSections; ++I) {
578
      // Find which section this relocation belongs to, and get the
579
      // relocation offset relative to the start of the section.
580
0
      if (Sec64->VirtualAddress <= RelocAddress &&
581
0
          RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) {
582
0
        return RelocAddress - Sec64->VirtualAddress;
583
0
      }
584
0
      ++Sec64;
585
0
    }
586
0
  } else {
587
0
    const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
588
0
    const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
589
0
    const uint32_t RelocAddress = Reloc->VirtualAddress;
590
0
    const uint16_t NumberOfSections = getNumberOfSections();
591
0
    for (uint16_t I = 0; I < NumberOfSections; ++I) {
592
      // Find which section this relocation belongs to, and get the
593
      // relocation offset relative to the start of the section.
594
0
      if (Sec32->VirtualAddress <= RelocAddress &&
595
0
          RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
596
0
        return RelocAddress - Sec32->VirtualAddress;
597
0
      }
598
0
      ++Sec32;
599
0
    }
600
0
  }
601
0
  return InvalidRelocOffset;
602
0
}
603
604
0
symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
605
0
  uint32_t Index;
606
0
  if (is64Bit()) {
607
0
    const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
608
0
    Index = Reloc->SymbolIndex;
609
610
0
    if (Index >= getNumberOfSymbolTableEntries64())
611
0
      return symbol_end();
612
0
  } else {
613
0
    const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
614
0
    Index = Reloc->SymbolIndex;
615
616
0
    if (Index >= getLogicalNumberOfSymbolTableEntries32())
617
0
      return symbol_end();
618
0
  }
619
0
  DataRefImpl SymDRI;
620
0
  SymDRI.p = getSymbolEntryAddressByIndex(Index);
621
0
  return symbol_iterator(SymbolRef(SymDRI, this));
622
0
}
623
624
0
uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
625
0
  if (is64Bit())
626
0
    return viewAs<XCOFFRelocation64>(Rel.p)->Type;
627
0
  return viewAs<XCOFFRelocation32>(Rel.p)->Type;
628
0
}
629
630
void XCOFFObjectFile::getRelocationTypeName(
631
0
    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
632
0
  StringRef Res;
633
0
  if (is64Bit()) {
634
0
    const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
635
0
    Res = XCOFF::getRelocationTypeString(Reloc->Type);
636
0
  } else {
637
0
    const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
638
0
    Res = XCOFF::getRelocationTypeString(Reloc->Type);
639
0
  }
640
0
  Result.append(Res.begin(), Res.end());
641
0
}
642
643
0
Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
644
0
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
645
0
  uint32_t Result = SymbolRef::SF_None;
646
647
0
  if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS)
648
0
    Result |= SymbolRef::SF_Absolute;
649
650
0
  XCOFF::StorageClass SC = XCOFFSym.getStorageClass();
651
0
  if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC)
652
0
    Result |= SymbolRef::SF_Global;
653
654
0
  if (XCOFF::C_WEAKEXT == SC)
655
0
    Result |= SymbolRef::SF_Weak;
656
657
0
  if (XCOFFSym.isCsectSymbol()) {
658
0
    Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr =
659
0
        XCOFFSym.getXCOFFCsectAuxRef();
660
0
    if (CsectAuxEntOrErr) {
661
0
      if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM)
662
0
        Result |= SymbolRef::SF_Common;
663
0
    } else
664
0
      return CsectAuxEntOrErr.takeError();
665
0
  }
666
667
0
  if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF)
668
0
    Result |= SymbolRef::SF_Undefined;
669
670
  // There is no visibility in old 32 bit XCOFF object file interpret.
671
0
  if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() ==
672
0
                                            NEW_XCOFF_INTERPRET))) {
673
0
    uint16_t SymType = XCOFFSym.getSymbolType();
674
0
    if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN)
675
0
      Result |= SymbolRef::SF_Hidden;
676
677
0
    if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED)
678
0
      Result |= SymbolRef::SF_Exported;
679
0
  }
680
0
  return Result;
681
0
}
682
683
0
basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
684
0
  DataRefImpl SymDRI;
685
0
  SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
686
0
  return basic_symbol_iterator(SymbolRef(SymDRI, this));
687
0
}
688
689
0
basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
690
0
  DataRefImpl SymDRI;
691
0
  const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
692
0
  SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
693
0
  return basic_symbol_iterator(SymbolRef(SymDRI, this));
694
0
}
695
696
0
XCOFFObjectFile::xcoff_symbol_iterator_range XCOFFObjectFile::symbols() const {
697
0
  return xcoff_symbol_iterator_range(symbol_begin(), symbol_end());
698
0
}
699
700
0
section_iterator XCOFFObjectFile::section_begin() const {
701
0
  DataRefImpl DRI;
702
0
  DRI.p = getSectionHeaderTableAddress();
703
0
  return section_iterator(SectionRef(DRI, this));
704
0
}
705
706
0
section_iterator XCOFFObjectFile::section_end() const {
707
0
  DataRefImpl DRI;
708
0
  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
709
0
                        getNumberOfSections() * getSectionHeaderSize());
710
0
  return section_iterator(SectionRef(DRI, this));
711
0
}
712
713
0
uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
714
715
0
StringRef XCOFFObjectFile::getFileFormatName() const {
716
0
  return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
717
0
}
718
719
0
Triple::ArchType XCOFFObjectFile::getArch() const {
720
0
  return is64Bit() ? Triple::ppc64 : Triple::ppc;
721
0
}
722
723
0
Expected<SubtargetFeatures> XCOFFObjectFile::getFeatures() const {
724
0
  return SubtargetFeatures();
725
0
}
726
727
0
bool XCOFFObjectFile::isRelocatableObject() const {
728
0
  if (is64Bit())
729
0
    return !(fileHeader64()->Flags & NoRelMask);
730
0
  return !(fileHeader32()->Flags & NoRelMask);
731
0
}
732
733
0
Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
734
  // TODO FIXME Should get from auxiliary_header->o_entry when support for the
735
  // auxiliary_header is added.
736
0
  return 0;
737
0
}
738
739
0
StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
740
0
  return StringSwitch<StringRef>(Name)
741
0
      .Case("dwinfo", "debug_info")
742
0
      .Case("dwline", "debug_line")
743
0
      .Case("dwpbnms", "debug_pubnames")
744
0
      .Case("dwpbtyp", "debug_pubtypes")
745
0
      .Case("dwarnge", "debug_aranges")
746
0
      .Case("dwabrev", "debug_abbrev")
747
0
      .Case("dwstr", "debug_str")
748
0
      .Case("dwrnges", "debug_ranges")
749
0
      .Case("dwloc", "debug_loc")
750
0
      .Case("dwframe", "debug_frame")
751
0
      .Case("dwmac", "debug_macinfo")
752
0
      .Default(Name);
753
0
}
754
755
0
size_t XCOFFObjectFile::getFileHeaderSize() const {
756
0
  return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
757
0
}
758
759
0
size_t XCOFFObjectFile::getSectionHeaderSize() const {
760
0
  return is64Bit() ? sizeof(XCOFFSectionHeader64) :
761
0
                     sizeof(XCOFFSectionHeader32);
762
0
}
763
764
0
bool XCOFFObjectFile::is64Bit() const {
765
0
  return Binary::ID_XCOFF64 == getType();
766
0
}
767
768
Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start,
769
                                                uint64_t Size,
770
0
                                                StringRef Name) const {
771
0
  uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start);
772
  // TODO: this path is untested.
773
0
  if (Error E = Binary::checkOffset(Data, StartPtr, Size))
774
0
    return createError(toString(std::move(E)) + ": " + Name.data() +
775
0
                       " data with offset 0x" + Twine::utohexstr(StartPtr) +
776
0
                       " and size 0x" + Twine::utohexstr(Size) +
777
0
                       " goes past the end of the file");
778
0
  return StringRef(Start, Size);
779
0
}
780
781
0
uint16_t XCOFFObjectFile::getMagic() const {
782
0
  return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
783
0
}
784
785
0
Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
786
0
  if (Num <= 0 || Num > getNumberOfSections())
787
0
    return createStringError(object_error::invalid_section_index,
788
0
                             "the section index (" + Twine(Num) +
789
0
                                 ") is invalid");
790
791
0
  DataRefImpl DRI;
792
0
  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
793
0
                        getSectionHeaderSize() * (Num - 1));
794
0
  return DRI;
795
0
}
796
797
DataRefImpl
798
0
XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const {
799
0
  DataRefImpl DRI;
800
0
  auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t {
801
0
    for (const auto &Sec : Sections)
802
0
      if (Sec.getSectionType() == SectType)
803
0
        return reinterpret_cast<uintptr_t>(&Sec);
804
0
    return uintptr_t(0);
805
0
  };
Unexecuted instantiation: XCOFFObjectFile.cpp:unsigned long llvm::object::XCOFFObjectFile::getSectionByType(llvm::XCOFF::SectionTypeFlags) const::$_0::operator()<llvm::ArrayRef<llvm::object::XCOFFSectionHeader64> >(llvm::ArrayRef<llvm::object::XCOFFSectionHeader64> const&) const
Unexecuted instantiation: XCOFFObjectFile.cpp:unsigned long llvm::object::XCOFFObjectFile::getSectionByType(llvm::XCOFF::SectionTypeFlags) const::$_0::operator()<llvm::ArrayRef<llvm::object::XCOFFSectionHeader32> >(llvm::ArrayRef<llvm::object::XCOFFSectionHeader32> const&) const
806
0
  if (is64Bit())
807
0
    DRI.p = GetSectionAddr(sections64());
808
0
  else
809
0
    DRI.p = GetSectionAddr(sections32());
810
0
  return DRI;
811
0
}
812
813
Expected<StringRef>
814
0
XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
815
0
  const int16_t SectionNum = SymEntPtr.getSectionNumber();
816
817
0
  switch (SectionNum) {
818
0
  case XCOFF::N_DEBUG:
819
0
    return "N_DEBUG";
820
0
  case XCOFF::N_ABS:
821
0
    return "N_ABS";
822
0
  case XCOFF::N_UNDEF:
823
0
    return "N_UNDEF";
824
0
  default:
825
0
    Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
826
0
    if (SecRef)
827
0
      return generateXCOFFFixedNameStringRef(
828
0
          getSectionNameInternal(SecRef.get()));
829
0
    return SecRef.takeError();
830
0
  }
831
0
}
832
833
0
unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
834
0
  XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this);
835
0
  return XCOFFSymRef.getSectionNumber();
836
0
}
837
838
0
bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
839
0
  return (SectionNumber <= 0 && SectionNumber >= -2);
840
0
}
841
842
0
uint16_t XCOFFObjectFile::getNumberOfSections() const {
843
0
  return is64Bit() ? fileHeader64()->NumberOfSections
844
0
                   : fileHeader32()->NumberOfSections;
845
0
}
846
847
0
int32_t XCOFFObjectFile::getTimeStamp() const {
848
0
  return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
849
0
}
850
851
0
uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
852
0
  return is64Bit() ? fileHeader64()->AuxHeaderSize
853
0
                   : fileHeader32()->AuxHeaderSize;
854
0
}
855
856
0
uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
857
0
  return fileHeader32()->SymbolTableOffset;
858
0
}
859
860
0
int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
861
  // As far as symbol table size is concerned, if this field is negative it is
862
  // to be treated as a 0. However since this field is also used for printing we
863
  // don't want to truncate any negative values.
864
0
  return fileHeader32()->NumberOfSymTableEntries;
865
0
}
866
867
0
uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
868
0
  return (fileHeader32()->NumberOfSymTableEntries >= 0
869
0
              ? fileHeader32()->NumberOfSymTableEntries
870
0
              : 0);
871
0
}
872
873
0
uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
874
0
  return fileHeader64()->SymbolTableOffset;
875
0
}
876
877
0
uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
878
0
  return fileHeader64()->NumberOfSymTableEntries;
879
0
}
880
881
0
uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
882
0
  return is64Bit() ? getNumberOfSymbolTableEntries64()
883
0
                   : getLogicalNumberOfSymbolTableEntries32();
884
0
}
885
886
0
uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
887
0
  const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
888
0
  return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
889
0
                       XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
890
0
}
891
892
0
void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
893
0
  if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
894
0
    report_fatal_error("Symbol table entry is outside of symbol table.");
895
896
0
  if (SymbolEntPtr >= getEndOfSymbolTableAddress())
897
0
    report_fatal_error("Symbol table entry is outside of symbol table.");
898
899
0
  ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
900
0
                     reinterpret_cast<const char *>(SymbolTblPtr);
901
902
0
  if (Offset % XCOFF::SymbolTableEntrySize != 0)
903
0
    report_fatal_error(
904
0
        "Symbol table entry position is not valid inside of symbol table.");
905
0
}
906
907
0
uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
908
0
  return (reinterpret_cast<const char *>(SymbolEntPtr) -
909
0
          reinterpret_cast<const char *>(SymbolTblPtr)) /
910
0
         XCOFF::SymbolTableEntrySize;
911
0
}
912
913
0
uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
914
0
  uint64_t Result = 0;
915
0
  XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
916
0
  if (XCOFFSym.isCsectSymbol()) {
917
0
    Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
918
0
        XCOFFSym.getXCOFFCsectAuxRef();
919
0
    if (!CsectAuxRefOrError)
920
      // TODO: report the error up the stack.
921
0
      consumeError(CsectAuxRefOrError.takeError());
922
0
    else {
923
0
      XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
924
0
      uint8_t SymType = CsectAuxRef.getSymbolType();
925
0
      if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM)
926
0
        Result = CsectAuxRef.getSectionOrLength();
927
0
    }
928
0
  }
929
0
  return Result;
930
0
}
931
932
0
uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
933
0
  return getAdvancedSymbolEntryAddress(
934
0
      reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
935
0
}
936
937
Expected<StringRef>
938
0
XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
939
0
  const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
940
941
0
  if (Index >= NumberOfSymTableEntries)
942
0
    return createError("symbol index " + Twine(Index) +
943
0
                       " exceeds symbol count " +
944
0
                       Twine(NumberOfSymTableEntries));
945
946
0
  DataRefImpl SymDRI;
947
0
  SymDRI.p = getSymbolEntryAddressByIndex(Index);
948
0
  return getSymbolName(SymDRI);
949
0
}
950
951
0
uint16_t XCOFFObjectFile::getFlags() const {
952
0
  return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
953
0
}
954
955
0
const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
956
0
  return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
957
0
}
958
959
0
uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
960
0
  return reinterpret_cast<uintptr_t>(SectionHeaderTable);
961
0
}
962
963
0
int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
964
0
  return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
965
0
}
966
967
XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
968
0
    : ObjectFile(Type, Object) {
969
0
  assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
970
0
}
971
972
0
ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
973
0
  assert(is64Bit() && "64-bit interface called for non 64-bit file.");
974
0
  const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
975
0
  return ArrayRef<XCOFFSectionHeader64>(TablePtr,
976
0
                                        TablePtr + getNumberOfSections());
977
0
}
978
979
0
ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
980
0
  assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
981
0
  const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
982
0
  return ArrayRef<XCOFFSectionHeader32>(TablePtr,
983
0
                                        TablePtr + getNumberOfSections());
984
0
}
985
986
// In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
987
// section header contains the actual count of relocation entries in the s_paddr
988
// field. STYP_OVRFLO headers contain the section index of their corresponding
989
// sections as their raw "NumberOfRelocations" field value.
990
template <typename T>
991
Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries(
992
0
    const XCOFFSectionHeader<T> &Sec) const {
993
0
  const T &Section = static_cast<const T &>(Sec);
994
0
  if (is64Bit())
995
0
    return Section.NumberOfRelocations;
996
997
0
  uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1;
998
0
  if (Section.NumberOfRelocations < XCOFF::RelocOverflow)
999
0
    return Section.NumberOfRelocations;
1000
0
  for (const auto &Sec : sections32()) {
1001
0
    if (Sec.Flags == XCOFF::STYP_OVRFLO &&
1002
0
        Sec.NumberOfRelocations == SectionIndex)
1003
0
      return Sec.PhysicalAddress;
1004
0
  }
1005
0
  return errorCodeToError(object_error::parse_failed);
1006
0
}
Unexecuted instantiation: llvm::Expected<unsigned int> llvm::object::XCOFFObjectFile::getNumberOfRelocationEntries<llvm::object::XCOFFSectionHeader64>(llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader64> const&) const
Unexecuted instantiation: llvm::Expected<unsigned int> llvm::object::XCOFFObjectFile::getNumberOfRelocationEntries<llvm::object::XCOFFSectionHeader32>(llvm::object::XCOFFSectionHeader<llvm::object::XCOFFSectionHeader32> const&) const
1007
1008
template <typename Shdr, typename Reloc>
1009
0
Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
1010
0
  uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
1011
0
                                      Sec.FileOffsetToRelocationInfo);
1012
0
  auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec);
1013
0
  if (Error E = NumRelocEntriesOrErr.takeError())
1014
0
    return std::move(E);
1015
1016
0
  uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
1017
0
  static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 ||
1018
0
                 sizeof(Reloc) == XCOFF::RelocationSerializationSize32),
1019
0
                "Relocation structure is incorrect");
1020
0
  auto RelocationOrErr =
1021
0
      getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
1022
0
                       NumRelocEntries * sizeof(Reloc));
1023
0
  if (!RelocationOrErr)
1024
0
    return createError(
1025
0
        toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" +
1026
0
        Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" +
1027
0
        Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) +
1028
0
        " go past the end of the file");
1029
1030
0
  const Reloc *StartReloc = RelocationOrErr.get();
1031
1032
0
  return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
1033
0
}
Unexecuted instantiation: llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64> > llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64, llvm::object::XCOFFRelocation64>(llvm::object::XCOFFSectionHeader64 const&) const
Unexecuted instantiation: llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32> > llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32, llvm::object::XCOFFRelocation32>(llvm::object::XCOFFSectionHeader32 const&) const
1034
1035
template <typename ExceptEnt>
1036
0
Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const {
1037
0
  assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) ||
1038
0
         (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32)));
1039
1040
0
  Expected<uintptr_t> ExceptionSectOrErr =
1041
0
      getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT);
1042
0
  if (!ExceptionSectOrErr)
1043
0
    return ExceptionSectOrErr.takeError();
1044
1045
0
  DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT);
1046
0
  if (DRI.p == 0)
1047
0
    return ArrayRef<ExceptEnt>();
1048
1049
0
  ExceptEnt *ExceptEntStart =
1050
0
      reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr);
1051
0
  return ArrayRef<ExceptEnt>(
1052
0
      ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt));
1053
0
}
Unexecuted instantiation: llvm::Expected<llvm::ArrayRef<llvm::object::ExceptionSectionEntry<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::endianness)0, 1ul, 1ul> > > > llvm::object::XCOFFObjectFile::getExceptionEntries<llvm::object::ExceptionSectionEntry<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::endianness)0, 1ul, 1ul> > >() const
Unexecuted instantiation: llvm::Expected<llvm::ArrayRef<llvm::object::ExceptionSectionEntry<llvm::support::detail::packed_endian_specific_integral<unsigned long, (llvm::endianness)0, 1ul, 1ul> > > > llvm::object::XCOFFObjectFile::getExceptionEntries<llvm::object::ExceptionSectionEntry<llvm::support::detail::packed_endian_specific_integral<unsigned long, (llvm::endianness)0, 1ul, 1ul> > >() const
1054
1055
template Expected<ArrayRef<ExceptionSectionEntry32>>
1056
XCOFFObjectFile::getExceptionEntries() const;
1057
template Expected<ArrayRef<ExceptionSectionEntry64>>
1058
XCOFFObjectFile::getExceptionEntries() const;
1059
1060
Expected<XCOFFStringTable>
1061
0
XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
1062
  // If there is a string table, then the buffer must contain at least 4 bytes
1063
  // for the string table's size. Not having a string table is not an error.
1064
0
  if (Error E = Binary::checkOffset(
1065
0
          Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
1066
0
    consumeError(std::move(E));
1067
0
    return XCOFFStringTable{0, nullptr};
1068
0
  }
1069
1070
  // Read the size out of the buffer.
1071
0
  uint32_t Size = support::endian::read32be(Obj->base() + Offset);
1072
1073
  // If the size is less then 4, then the string table is just a size and no
1074
  // string data.
1075
0
  if (Size <= 4)
1076
0
    return XCOFFStringTable{4, nullptr};
1077
1078
0
  auto StringTableOrErr =
1079
0
      getObject<char>(Obj->Data, Obj->base() + Offset, Size);
1080
0
  if (!StringTableOrErr)
1081
0
    return createError(toString(StringTableOrErr.takeError()) +
1082
0
                       ": string table with offset 0x" +
1083
0
                       Twine::utohexstr(Offset) + " and size 0x" +
1084
0
                       Twine::utohexstr(Size) +
1085
0
                       " goes past the end of the file");
1086
1087
0
  const char *StringTablePtr = StringTableOrErr.get();
1088
0
  if (StringTablePtr[Size - 1] != '\0')
1089
0
    return errorCodeToError(object_error::string_table_non_null_end);
1090
1091
0
  return XCOFFStringTable{Size, StringTablePtr};
1092
0
}
1093
1094
// This function returns the import file table. Each entry in the import file
1095
// table consists of: "path_name\0base_name\0archive_member_name\0".
1096
0
Expected<StringRef> XCOFFObjectFile::getImportFileTable() const {
1097
0
  Expected<uintptr_t> LoaderSectionAddrOrError =
1098
0
      getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
1099
0
  if (!LoaderSectionAddrOrError)
1100
0
    return LoaderSectionAddrOrError.takeError();
1101
1102
0
  uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
1103
0
  if (!LoaderSectionAddr)
1104
0
    return StringRef();
1105
1106
0
  uint64_t OffsetToImportFileTable = 0;
1107
0
  uint64_t LengthOfImportFileTable = 0;
1108
0
  if (is64Bit()) {
1109
0
    const LoaderSectionHeader64 *LoaderSec64 =
1110
0
        viewAs<LoaderSectionHeader64>(LoaderSectionAddr);
1111
0
    OffsetToImportFileTable = LoaderSec64->OffsetToImpid;
1112
0
    LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl;
1113
0
  } else {
1114
0
    const LoaderSectionHeader32 *LoaderSec32 =
1115
0
        viewAs<LoaderSectionHeader32>(LoaderSectionAddr);
1116
0
    OffsetToImportFileTable = LoaderSec32->OffsetToImpid;
1117
0
    LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl;
1118
0
  }
1119
1120
0
  auto ImportTableOrErr = getObject<char>(
1121
0
      Data,
1122
0
      reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable),
1123
0
      LengthOfImportFileTable);
1124
0
  if (!ImportTableOrErr)
1125
0
    return createError(
1126
0
        toString(ImportTableOrErr.takeError()) +
1127
0
        ": import file table with offset 0x" +
1128
0
        Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1129
0
        " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1130
0
        " goes past the end of the file");
1131
1132
0
  const char *ImportTablePtr = ImportTableOrErr.get();
1133
0
  if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0')
1134
0
    return createError(
1135
0
        ": import file name table with offset 0x" +
1136
0
        Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1137
0
        " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1138
0
        " must end with a null terminator");
1139
1140
0
  return StringRef(ImportTablePtr, LengthOfImportFileTable);
1141
0
}
1142
1143
Expected<std::unique_ptr<XCOFFObjectFile>>
1144
0
XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
1145
  // Can't use std::make_unique because of the private constructor.
1146
0
  std::unique_ptr<XCOFFObjectFile> Obj;
1147
0
  Obj.reset(new XCOFFObjectFile(Type, MBR));
1148
1149
0
  uint64_t CurOffset = 0;
1150
0
  const auto *Base = Obj->base();
1151
0
  MemoryBufferRef Data = Obj->Data;
1152
1153
  // Parse file header.
1154
0
  auto FileHeaderOrErr =
1155
0
      getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
1156
0
  if (Error E = FileHeaderOrErr.takeError())
1157
0
    return std::move(E);
1158
0
  Obj->FileHeader = FileHeaderOrErr.get();
1159
1160
0
  CurOffset += Obj->getFileHeaderSize();
1161
1162
0
  if (Obj->getOptionalHeaderSize()) {
1163
0
    auto AuxiliaryHeaderOrErr =
1164
0
        getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize());
1165
0
    if (Error E = AuxiliaryHeaderOrErr.takeError())
1166
0
      return std::move(E);
1167
0
    Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get();
1168
0
  }
1169
1170
0
  CurOffset += Obj->getOptionalHeaderSize();
1171
1172
  // Parse the section header table if it is present.
1173
0
  if (Obj->getNumberOfSections()) {
1174
0
    uint64_t SectionHeadersSize =
1175
0
        Obj->getNumberOfSections() * Obj->getSectionHeaderSize();
1176
0
    auto SecHeadersOrErr =
1177
0
        getObject<void>(Data, Base + CurOffset, SectionHeadersSize);
1178
0
    if (!SecHeadersOrErr)
1179
0
      return createError(toString(SecHeadersOrErr.takeError()) +
1180
0
                         ": section headers with offset 0x" +
1181
0
                         Twine::utohexstr(CurOffset) + " and size 0x" +
1182
0
                         Twine::utohexstr(SectionHeadersSize) +
1183
0
                         " go past the end of the file");
1184
1185
0
    Obj->SectionHeaderTable = SecHeadersOrErr.get();
1186
0
  }
1187
1188
0
  const uint32_t NumberOfSymbolTableEntries =
1189
0
      Obj->getNumberOfSymbolTableEntries();
1190
1191
  // If there is no symbol table we are done parsing the memory buffer.
1192
0
  if (NumberOfSymbolTableEntries == 0)
1193
0
    return std::move(Obj);
1194
1195
  // Parse symbol table.
1196
0
  CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
1197
0
                             : Obj->getSymbolTableOffset32();
1198
0
  const uint64_t SymbolTableSize =
1199
0
      static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
1200
0
      NumberOfSymbolTableEntries;
1201
0
  auto SymTableOrErr =
1202
0
      getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
1203
0
  if (!SymTableOrErr)
1204
0
    return createError(
1205
0
        toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" +
1206
0
        Twine::utohexstr(CurOffset) + " and size 0x" +
1207
0
        Twine::utohexstr(SymbolTableSize) + " goes past the end of the file");
1208
1209
0
  Obj->SymbolTblPtr = SymTableOrErr.get();
1210
0
  CurOffset += SymbolTableSize;
1211
1212
  // Parse String table.
1213
0
  Expected<XCOFFStringTable> StringTableOrErr =
1214
0
      parseStringTable(Obj.get(), CurOffset);
1215
0
  if (Error E = StringTableOrErr.takeError())
1216
0
    return std::move(E);
1217
0
  Obj->StringTable = StringTableOrErr.get();
1218
1219
0
  return std::move(Obj);
1220
0
}
1221
1222
Expected<std::unique_ptr<ObjectFile>>
1223
ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
1224
0
                                  unsigned FileType) {
1225
0
  return XCOFFObjectFile::create(FileType, MemBufRef);
1226
0
}
1227
1228
0
std::optional<StringRef> XCOFFObjectFile::tryGetCPUName() const {
1229
0
  return StringRef("future");
1230
0
}
1231
1232
0
Expected<bool> XCOFFSymbolRef::isFunction() const {
1233
0
  if (!isCsectSymbol())
1234
0
    return false;
1235
1236
0
  if (getSymbolType() & FunctionSym)
1237
0
    return true;
1238
1239
0
  Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
1240
0
  if (!ExpCsectAuxEnt)
1241
0
    return ExpCsectAuxEnt.takeError();
1242
1243
0
  const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
1244
1245
0
  if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR &&
1246
0
      CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_GL)
1247
0
    return false;
1248
1249
  // A function definition should not be a common type symbol or an external
1250
  // symbol.
1251
0
  if (CsectAuxRef.getSymbolType() == XCOFF::XTY_CM ||
1252
0
      CsectAuxRef.getSymbolType() == XCOFF::XTY_ER)
1253
0
    return false;
1254
1255
  // If the next symbol is an XTY_LD type symbol with the same address, this
1256
  // XTY_SD symbol is not a function. Otherwise this is a function symbol for
1257
  // -ffunction-sections.
1258
0
  if (CsectAuxRef.getSymbolType() == XCOFF::XTY_SD) {
1259
    // If this is a csect with size 0, it won't be a function definition.
1260
    // This is used to work around the fact that LLVM always generates below
1261
    // symbol for -ffunction-sections:
1262
    // m   0x00000000     .text     1  unamex                    **No Symbol**
1263
    // a4  0x00000000       0    0     SD       PR    0    0
1264
    // FIXME: remove or replace this meaningless symbol.
1265
0
    if (getSize() == 0)
1266
0
      return false;
1267
1268
0
    xcoff_symbol_iterator NextIt(this);
1269
    // If this is the last main symbol table entry, there won't be an XTY_LD
1270
    // type symbol below.
1271
0
    if (++NextIt == getObject()->symbol_end())
1272
0
      return true;
1273
1274
0
    if (cantFail(getAddress()) != cantFail(NextIt->getAddress()))
1275
0
      return true;
1276
1277
    // Check next symbol is XTY_LD. If so, this symbol is not a function.
1278
0
    Expected<XCOFFCsectAuxRef> NextCsectAuxEnt = NextIt->getXCOFFCsectAuxRef();
1279
0
    if (!NextCsectAuxEnt)
1280
0
      return NextCsectAuxEnt.takeError();
1281
1282
0
    if (NextCsectAuxEnt.get().getSymbolType() == XCOFF::XTY_LD)
1283
0
      return false;
1284
1285
0
    return true;
1286
0
  }
1287
1288
0
  if (CsectAuxRef.getSymbolType() == XCOFF::XTY_LD)
1289
0
    return true;
1290
1291
0
  return createError(
1292
0
      "symbol csect aux entry with index " +
1293
0
      Twine(getObject()->getSymbolIndex(CsectAuxRef.getEntryAddress())) +
1294
0
      " has invalid symbol type " +
1295
0
      Twine::utohexstr(CsectAuxRef.getSymbolType()));
1296
0
}
1297
1298
0
bool XCOFFSymbolRef::isCsectSymbol() const {
1299
0
  XCOFF::StorageClass SC = getStorageClass();
1300
0
  return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
1301
0
          SC == XCOFF::C_HIDEXT);
1302
0
}
1303
1304
0
Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
1305
0
  assert(isCsectSymbol() &&
1306
0
         "Calling csect symbol interface with a non-csect symbol.");
1307
1308
0
  uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
1309
1310
0
  Expected<StringRef> NameOrErr = getName();
1311
0
  if (auto Err = NameOrErr.takeError())
1312
0
    return std::move(Err);
1313
1314
0
  uint32_t SymbolIdx = getObject()->getSymbolIndex(getEntryAddress());
1315
0
  if (!NumberOfAuxEntries) {
1316
0
    return createError("csect symbol \"" + *NameOrErr + "\" with index " +
1317
0
                       Twine(SymbolIdx) + " contains no auxiliary entry");
1318
0
  }
1319
1320
0
  if (!getObject()->is64Bit()) {
1321
    // In XCOFF32, the csect auxilliary entry is always the last auxiliary
1322
    // entry for the symbol.
1323
0
    uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1324
0
        getEntryAddress(), NumberOfAuxEntries);
1325
0
    return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
1326
0
  }
1327
1328
  // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
1329
  // We need to iterate through all the auxiliary entries to find it.
1330
0
  for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
1331
0
    uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1332
0
        getEntryAddress(), Index);
1333
0
    if (*getObject()->getSymbolAuxType(AuxAddr) ==
1334
0
        XCOFF::SymbolAuxType::AUX_CSECT) {
1335
0
#ifndef NDEBUG
1336
0
      getObject()->checkSymbolEntryPointer(AuxAddr);
1337
0
#endif
1338
0
      return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
1339
0
    }
1340
0
  }
1341
1342
0
  return createError(
1343
0
      "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr +
1344
0
      "\" with index " + Twine(SymbolIdx));
1345
0
}
1346
1347
0
Expected<StringRef> XCOFFSymbolRef::getName() const {
1348
  // A storage class value with the high-order bit on indicates that the name is
1349
  // a symbolic debugger stabstring.
1350
0
  if (getStorageClass() & 0x80)
1351
0
    return StringRef("Unimplemented Debug Name");
1352
1353
0
  if (!getObject()->is64Bit()) {
1354
0
    if (getSymbol32()->NameInStrTbl.Magic !=
1355
0
        XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
1356
0
      return generateXCOFFFixedNameStringRef(getSymbol32()->SymbolName);
1357
1358
0
    return getObject()->getStringTableEntry(getSymbol32()->NameInStrTbl.Offset);
1359
0
  }
1360
1361
0
  return getObject()->getStringTableEntry(getSymbol64()->Offset);
1362
0
}
1363
1364
// Explictly instantiate template classes.
1365
template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
1366
template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
1367
1368
template struct XCOFFRelocation<llvm::support::ubig32_t>;
1369
template struct XCOFFRelocation<llvm::support::ubig64_t>;
1370
1371
template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>>
1372
llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64,
1373
                                           llvm::object::XCOFFRelocation64>(
1374
    llvm::object::XCOFFSectionHeader64 const &) const;
1375
template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>>
1376
llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32,
1377
                                           llvm::object::XCOFFRelocation32>(
1378
    llvm::object::XCOFFSectionHeader32 const &) const;
1379
1380
0
bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
1381
0
  if (Bytes.size() < 4)
1382
0
    return false;
1383
1384
0
  return support::endian::read32be(Bytes.data()) == 0;
1385
0
}
1386
1387
0
#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
1388
#define GETVALUEWITHMASKSHIFT(X, S)                                            \
1389
0
  ((Data & (TracebackTable::X)) >> (TracebackTable::S))
1390
1391
0
Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) {
1392
0
  Error Err = Error::success();
1393
0
  TBVectorExt TBTVecExt(TBvectorStrRef, Err);
1394
0
  if (Err)
1395
0
    return std::move(Err);
1396
0
  return TBTVecExt;
1397
0
}
1398
1399
0
TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) {
1400
0
  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
1401
0
  Data = support::endian::read16be(Ptr);
1402
0
  uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
1403
0
  unsigned ParmsNum =
1404
0
      GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);
1405
1406
0
  ErrorAsOutParameter EAO(&Err);
1407
0
  Expected<SmallString<32>> VecParmsTypeOrError =
1408
0
      parseVectorParmsType(VecParmsTypeValue, ParmsNum);
1409
0
  if (!VecParmsTypeOrError)
1410
0
    Err = VecParmsTypeOrError.takeError();
1411
0
  else
1412
0
    VecParmsInfo = VecParmsTypeOrError.get();
1413
0
}
1414
1415
0
uint8_t TBVectorExt::getNumberOfVRSaved() const {
1416
0
  return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
1417
0
}
1418
1419
0
bool TBVectorExt::isVRSavedOnStack() const {
1420
0
  return GETVALUEWITHMASK(IsVRSavedOnStackMask);
1421
0
}
1422
1423
0
bool TBVectorExt::hasVarArgs() const {
1424
0
  return GETVALUEWITHMASK(HasVarArgsMask);
1425
0
}
1426
1427
0
uint8_t TBVectorExt::getNumberOfVectorParms() const {
1428
0
  return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
1429
0
                               NumberOfVectorParmsShift);
1430
0
}
1431
1432
0
bool TBVectorExt::hasVMXInstruction() const {
1433
0
  return GETVALUEWITHMASK(HasVMXInstructionMask);
1434
0
}
1435
#undef GETVALUEWITHMASK
1436
#undef GETVALUEWITHMASKSHIFT
1437
1438
Expected<XCOFFTracebackTable>
1439
0
XCOFFTracebackTable::create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bit) {
1440
0
  Error Err = Error::success();
1441
0
  XCOFFTracebackTable TBT(Ptr, Size, Err, Is64Bit);
1442
0
  if (Err)
1443
0
    return std::move(Err);
1444
0
  return TBT;
1445
0
}
1446
1447
XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
1448
                                         Error &Err, bool Is64Bit)
1449
0
    : TBPtr(Ptr), Is64BitObj(Is64Bit) {
1450
0
  ErrorAsOutParameter EAO(&Err);
1451
0
  DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
1452
0
                   /*AddressSize=*/0);
1453
0
  DataExtractor::Cursor Cur(/*Offset=*/0);
1454
1455
  // Skip 8 bytes of mandatory fields.
1456
0
  DE.getU64(Cur);
1457
1458
0
  unsigned FixedParmsNum = getNumberOfFixedParms();
1459
0
  unsigned FloatingParmsNum = getNumberOfFPParms();
1460
0
  uint32_t ParamsTypeValue = 0;
1461
1462
  // Begin to parse optional fields.
1463
0
  if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
1464
0
    ParamsTypeValue = DE.getU32(Cur);
1465
1466
0
  if (Cur && hasTraceBackTableOffset())
1467
0
    TraceBackTableOffset = DE.getU32(Cur);
1468
1469
0
  if (Cur && isInterruptHandler())
1470
0
    HandlerMask = DE.getU32(Cur);
1471
1472
0
  if (Cur && hasControlledStorage()) {
1473
0
    NumOfCtlAnchors = DE.getU32(Cur);
1474
0
    if (Cur && NumOfCtlAnchors) {
1475
0
      SmallVector<uint32_t, 8> Disp;
1476
0
      Disp.reserve(*NumOfCtlAnchors);
1477
0
      for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
1478
0
        Disp.push_back(DE.getU32(Cur));
1479
0
      if (Cur)
1480
0
        ControlledStorageInfoDisp = std::move(Disp);
1481
0
    }
1482
0
  }
1483
1484
0
  if (Cur && isFuncNamePresent()) {
1485
0
    uint16_t FunctionNameLen = DE.getU16(Cur);
1486
0
    if (Cur)
1487
0
      FunctionName = DE.getBytes(Cur, FunctionNameLen);
1488
0
  }
1489
1490
0
  if (Cur && isAllocaUsed())
1491
0
    AllocaRegister = DE.getU8(Cur);
1492
1493
0
  unsigned VectorParmsNum = 0;
1494
0
  if (Cur && hasVectorInfo()) {
1495
0
    StringRef VectorExtRef = DE.getBytes(Cur, 6);
1496
0
    if (Cur) {
1497
0
      Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
1498
0
      if (!TBVecExtOrErr) {
1499
0
        Err = TBVecExtOrErr.takeError();
1500
0
        return;
1501
0
      }
1502
0
      VecExt = TBVecExtOrErr.get();
1503
0
      VectorParmsNum = VecExt->getNumberOfVectorParms();
1504
      // Skip two bytes of padding after vector info.
1505
0
      DE.skip(Cur, 2);
1506
0
    }
1507
0
  }
1508
1509
  // As long as there is no fixed-point or floating-point parameter, this
1510
  // field remains not present even when hasVectorInfo gives true and
1511
  // indicates the presence of vector parameters.
1512
0
  if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
1513
0
    Expected<SmallString<32>> ParmsTypeOrError =
1514
0
        hasVectorInfo()
1515
0
            ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
1516
0
                                        FloatingParmsNum, VectorParmsNum)
1517
0
            : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);
1518
1519
0
    if (!ParmsTypeOrError) {
1520
0
      Err = ParmsTypeOrError.takeError();
1521
0
      return;
1522
0
    }
1523
0
    ParmsType = ParmsTypeOrError.get();
1524
0
  }
1525
1526
0
  if (Cur && hasExtensionTable()) {
1527
0
    ExtensionTable = DE.getU8(Cur);
1528
1529
0
    if (*ExtensionTable & ExtendedTBTableFlag::TB_EH_INFO) {
1530
      // eh_info displacement must be 4-byte aligned.
1531
0
      Cur.seek(alignTo(Cur.tell(), 4));
1532
0
      EhInfoDisp = Is64BitObj ? DE.getU64(Cur) : DE.getU32(Cur);
1533
0
    }
1534
0
  }
1535
0
  if (!Cur)
1536
0
    Err = Cur.takeError();
1537
1538
0
  Size = Cur.tell();
1539
0
}
1540
1541
#define GETBITWITHMASK(P, X)                                                   \
1542
0
  (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
1543
#define GETBITWITHMASKSHIFT(P, X, S)                                           \
1544
0
  ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >>           \
1545
0
   (TracebackTable::S))
1546
1547
0
uint8_t XCOFFTracebackTable::getVersion() const {
1548
0
  return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
1549
0
}
1550
1551
0
uint8_t XCOFFTracebackTable::getLanguageID() const {
1552
0
  return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
1553
0
}
1554
1555
0
bool XCOFFTracebackTable::isGlobalLinkage() const {
1556
0
  return GETBITWITHMASK(0, IsGlobaLinkageMask);
1557
0
}
1558
1559
0
bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
1560
0
  return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
1561
0
}
1562
1563
0
bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
1564
0
  return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
1565
0
}
1566
1567
0
bool XCOFFTracebackTable::isInternalProcedure() const {
1568
0
  return GETBITWITHMASK(0, IsInternalProcedureMask);
1569
0
}
1570
1571
0
bool XCOFFTracebackTable::hasControlledStorage() const {
1572
0
  return GETBITWITHMASK(0, HasControlledStorageMask);
1573
0
}
1574
1575
0
bool XCOFFTracebackTable::isTOCless() const {
1576
0
  return GETBITWITHMASK(0, IsTOClessMask);
1577
0
}
1578
1579
0
bool XCOFFTracebackTable::isFloatingPointPresent() const {
1580
0
  return GETBITWITHMASK(0, IsFloatingPointPresentMask);
1581
0
}
1582
1583
0
bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
1584
0
  return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
1585
0
}
1586
1587
0
bool XCOFFTracebackTable::isInterruptHandler() const {
1588
0
  return GETBITWITHMASK(0, IsInterruptHandlerMask);
1589
0
}
1590
1591
0
bool XCOFFTracebackTable::isFuncNamePresent() const {
1592
0
  return GETBITWITHMASK(0, IsFunctionNamePresentMask);
1593
0
}
1594
1595
0
bool XCOFFTracebackTable::isAllocaUsed() const {
1596
0
  return GETBITWITHMASK(0, IsAllocaUsedMask);
1597
0
}
1598
1599
0
uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
1600
0
  return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
1601
0
                             OnConditionDirectiveShift);
1602
0
}
1603
1604
0
bool XCOFFTracebackTable::isCRSaved() const {
1605
0
  return GETBITWITHMASK(0, IsCRSavedMask);
1606
0
}
1607
1608
0
bool XCOFFTracebackTable::isLRSaved() const {
1609
0
  return GETBITWITHMASK(0, IsLRSavedMask);
1610
0
}
1611
1612
0
bool XCOFFTracebackTable::isBackChainStored() const {
1613
0
  return GETBITWITHMASK(4, IsBackChainStoredMask);
1614
0
}
1615
1616
0
bool XCOFFTracebackTable::isFixup() const {
1617
0
  return GETBITWITHMASK(4, IsFixupMask);
1618
0
}
1619
1620
0
uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
1621
0
  return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
1622
0
}
1623
1624
0
bool XCOFFTracebackTable::hasExtensionTable() const {
1625
0
  return GETBITWITHMASK(4, HasExtensionTableMask);
1626
0
}
1627
1628
0
bool XCOFFTracebackTable::hasVectorInfo() const {
1629
0
  return GETBITWITHMASK(4, HasVectorInfoMask);
1630
0
}
1631
1632
0
uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
1633
0
  return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
1634
0
}
1635
1636
0
uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
1637
0
  return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
1638
0
                             NumberOfFixedParmsShift);
1639
0
}
1640
1641
0
uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
1642
0
  return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
1643
0
                             NumberOfFloatingPointParmsShift);
1644
0
}
1645
1646
0
bool XCOFFTracebackTable::hasParmsOnStack() const {
1647
0
  return GETBITWITHMASK(4, HasParmsOnStackMask);
1648
0
}
1649
1650
#undef GETBITWITHMASK
1651
#undef GETBITWITHMASKSHIFT
1652
} // namespace object
1653
} // namespace llvm