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