xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the XCOFFObjectFile class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Object/XCOFFObjectFile.h"
14fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
15e8d8bef9SDimitry Andric #include "llvm/Support/DataExtractor.h"
1606c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
170b57cec5SDimitry Andric #include <cstddef>
180b57cec5SDimitry Andric #include <cstring>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace llvm {
21e8d8bef9SDimitry Andric 
22e8d8bef9SDimitry Andric using namespace XCOFF;
23e8d8bef9SDimitry Andric 
240b57cec5SDimitry Andric namespace object {
250b57cec5SDimitry Andric 
265ffd83dbSDimitry Andric static const uint8_t FunctionSym = 0x20;
275ffd83dbSDimitry Andric static const uint16_t NoRelMask = 0x0001;
28fe6060f1SDimitry Andric static const size_t SymbolAuxTypeOffset = 17;
298bcb0991SDimitry Andric 
300b57cec5SDimitry Andric // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
310b57cec5SDimitry Andric // 'M'. Returns a pointer to the underlying object on success.
320b57cec5SDimitry Andric template <typename T>
330b57cec5SDimitry Andric static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
340b57cec5SDimitry Andric                                      const uint64_t Size = sizeof(T)) {
35e8d8bef9SDimitry Andric   uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
365ffd83dbSDimitry Andric   if (Error E = Binary::checkOffset(M, Addr, Size))
375ffd83dbSDimitry Andric     return std::move(E);
380b57cec5SDimitry Andric   return reinterpret_cast<const T *>(Addr);
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
420b57cec5SDimitry Andric   return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
430b57cec5SDimitry Andric                                      Offset);
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric template <typename T> static const T *viewAs(uintptr_t in) {
470b57cec5SDimitry Andric   return reinterpret_cast<const T *>(in);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
508bcb0991SDimitry Andric static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
518bcb0991SDimitry Andric   auto NulCharPtr =
528bcb0991SDimitry Andric       static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
530b57cec5SDimitry Andric   return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
548bcb0991SDimitry Andric                     : StringRef(Name, XCOFF::NameSize);
558bcb0991SDimitry Andric }
568bcb0991SDimitry Andric 
57480093f4SDimitry Andric template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
58480093f4SDimitry Andric   const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
59480093f4SDimitry Andric   return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
60480093f4SDimitry Andric }
61480093f4SDimitry Andric 
62480093f4SDimitry Andric template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
63480093f4SDimitry Andric   const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
64480093f4SDimitry Andric   return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
65480093f4SDimitry Andric }
66480093f4SDimitry Andric 
67480093f4SDimitry Andric template <typename T>
68*0fca6ea1SDimitry Andric uint32_t XCOFFSectionHeader<T>::getSectionSubtype() const {
69*0fca6ea1SDimitry Andric   const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
70*0fca6ea1SDimitry Andric   return DerivedXCOFFSectionHeader.Flags & ~SectionFlagsTypeMask;
71*0fca6ea1SDimitry Andric }
72*0fca6ea1SDimitry Andric 
73*0fca6ea1SDimitry Andric template <typename T>
74480093f4SDimitry Andric bool XCOFFSectionHeader<T>::isReservedSectionType() const {
75480093f4SDimitry Andric   return getSectionType() & SectionFlagsReservedMask;
76480093f4SDimitry Andric }
77480093f4SDimitry Andric 
78349cc55cSDimitry Andric template <typename AddressType>
79349cc55cSDimitry Andric bool XCOFFRelocation<AddressType>::isRelocationSigned() const {
808bcb0991SDimitry Andric   return Info & XR_SIGN_INDICATOR_MASK;
818bcb0991SDimitry Andric }
828bcb0991SDimitry Andric 
83349cc55cSDimitry Andric template <typename AddressType>
84349cc55cSDimitry Andric bool XCOFFRelocation<AddressType>::isFixupIndicated() const {
858bcb0991SDimitry Andric   return Info & XR_FIXUP_INDICATOR_MASK;
868bcb0991SDimitry Andric }
878bcb0991SDimitry Andric 
88349cc55cSDimitry Andric template <typename AddressType>
89349cc55cSDimitry Andric uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
908bcb0991SDimitry Andric   // The relocation encodes the bit length being relocated minus 1. Add back
918bcb0991SDimitry Andric   // the 1 to get the actual length being relocated.
928bcb0991SDimitry Andric   return (Info & XR_BIASED_LENGTH_MASK) + 1;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
95bdd1243dSDimitry Andric template struct ExceptionSectionEntry<support::ubig32_t>;
96bdd1243dSDimitry Andric template struct ExceptionSectionEntry<support::ubig64_t>;
97bdd1243dSDimitry Andric 
98bdd1243dSDimitry Andric template <typename T>
99bdd1243dSDimitry Andric Expected<StringRef> getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader,
100bdd1243dSDimitry Andric                                                 uint64_t Offset) {
101bdd1243dSDimitry Andric   if (LoaderSecHeader->LengthOfStrTbl > Offset)
102bdd1243dSDimitry Andric     return (reinterpret_cast<const char *>(LoaderSecHeader) +
103bdd1243dSDimitry Andric             LoaderSecHeader->OffsetToStrTbl + Offset);
104bdd1243dSDimitry Andric 
105bdd1243dSDimitry Andric   return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
106bdd1243dSDimitry Andric                      " in the loader section's string table with size 0x" +
107bdd1243dSDimitry Andric                      Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) +
108bdd1243dSDimitry Andric                      " is invalid");
109bdd1243dSDimitry Andric }
110bdd1243dSDimitry Andric 
111bdd1243dSDimitry Andric Expected<StringRef> LoaderSectionSymbolEntry32::getSymbolName(
112bdd1243dSDimitry Andric     const LoaderSectionHeader32 *LoaderSecHeader32) const {
113bdd1243dSDimitry Andric   const NameOffsetInStrTbl *NameInStrTbl =
114bdd1243dSDimitry Andric       reinterpret_cast<const NameOffsetInStrTbl *>(SymbolName);
115bdd1243dSDimitry Andric   if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
116bdd1243dSDimitry Andric     return generateXCOFFFixedNameStringRef(SymbolName);
117bdd1243dSDimitry Andric 
118bdd1243dSDimitry Andric   return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset);
119bdd1243dSDimitry Andric }
120bdd1243dSDimitry Andric 
121bdd1243dSDimitry Andric Expected<StringRef> LoaderSectionSymbolEntry64::getSymbolName(
122bdd1243dSDimitry Andric     const LoaderSectionHeader64 *LoaderSecHeader64) const {
123bdd1243dSDimitry Andric   return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset);
124bdd1243dSDimitry Andric }
125bdd1243dSDimitry Andric 
126fe6060f1SDimitry Andric uintptr_t
127fe6060f1SDimitry Andric XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
128fe6060f1SDimitry Andric                                                uint32_t Distance) {
129fe6060f1SDimitry Andric   return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
130fe6060f1SDimitry Andric }
131fe6060f1SDimitry Andric 
132fe6060f1SDimitry Andric const XCOFF::SymbolAuxType *
133fe6060f1SDimitry Andric XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
134fe6060f1SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
135fe6060f1SDimitry Andric   return viewAs<XCOFF::SymbolAuxType>(
136fe6060f1SDimitry Andric       getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
137fe6060f1SDimitry Andric }
138fe6060f1SDimitry Andric 
1390b57cec5SDimitry Andric void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
1400b57cec5SDimitry Andric                                           uintptr_t TableAddress) const {
1410b57cec5SDimitry Andric   if (Addr < TableAddress)
1420b57cec5SDimitry Andric     report_fatal_error("Section header outside of section header table.");
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   uintptr_t Offset = Addr - TableAddress;
1450b57cec5SDimitry Andric   if (Offset >= getSectionHeaderSize() * getNumberOfSections())
1460b57cec5SDimitry Andric     report_fatal_error("Section header outside of section header table.");
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   if (Offset % getSectionHeaderSize() != 0)
1490b57cec5SDimitry Andric     report_fatal_error(
1500b57cec5SDimitry Andric         "Section header pointer does not point to a valid section header.");
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric const XCOFFSectionHeader32 *
1540b57cec5SDimitry Andric XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
1550b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
1560b57cec5SDimitry Andric #ifndef NDEBUG
1570b57cec5SDimitry Andric   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
1580b57cec5SDimitry Andric #endif
1590b57cec5SDimitry Andric   return viewAs<XCOFFSectionHeader32>(Ref.p);
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric const XCOFFSectionHeader64 *
1630b57cec5SDimitry Andric XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
1640b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
1650b57cec5SDimitry Andric #ifndef NDEBUG
1660b57cec5SDimitry Andric   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
1670b57cec5SDimitry Andric #endif
1680b57cec5SDimitry Andric   return viewAs<XCOFFSectionHeader64>(Ref.p);
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
171fe6060f1SDimitry Andric XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
1720b57cec5SDimitry Andric   assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
1738bcb0991SDimitry Andric #ifndef NDEBUG
1748bcb0991SDimitry Andric   checkSymbolEntryPointer(Ref.p);
1758bcb0991SDimitry Andric #endif
176fe6060f1SDimitry Andric   return XCOFFSymbolRef(Ref, this);
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
1800b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
1810b57cec5SDimitry Andric   return static_cast<const XCOFFFileHeader32 *>(FileHeader);
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
1850b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
1860b57cec5SDimitry Andric   return static_cast<const XCOFFFileHeader64 *>(FileHeader);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
189349cc55cSDimitry Andric const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
190349cc55cSDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
191349cc55cSDimitry Andric   return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
192349cc55cSDimitry Andric }
193349cc55cSDimitry Andric 
194349cc55cSDimitry Andric const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
195349cc55cSDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
196349cc55cSDimitry Andric   return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
197349cc55cSDimitry Andric }
198349cc55cSDimitry Andric 
199349cc55cSDimitry Andric template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
200349cc55cSDimitry Andric   return static_cast<const T *>(SectionHeaderTable);
201349cc55cSDimitry Andric }
202349cc55cSDimitry Andric 
2030b57cec5SDimitry Andric const XCOFFSectionHeader32 *
2040b57cec5SDimitry Andric XCOFFObjectFile::sectionHeaderTable32() const {
2050b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
2060b57cec5SDimitry Andric   return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric const XCOFFSectionHeader64 *
2100b57cec5SDimitry Andric XCOFFObjectFile::sectionHeaderTable64() const {
2110b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
2120b57cec5SDimitry Andric   return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
216fe6060f1SDimitry Andric   uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
217fe6060f1SDimitry Andric       Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
2188bcb0991SDimitry Andric #ifndef NDEBUG
2198bcb0991SDimitry Andric   // This function is used by basic_symbol_iterator, which allows to
2208bcb0991SDimitry Andric   // point to the end-of-symbol-table address.
221fe6060f1SDimitry Andric   if (NextSymbolAddr != getEndOfSymbolTableAddress())
222fe6060f1SDimitry Andric     checkSymbolEntryPointer(NextSymbolAddr);
2238bcb0991SDimitry Andric #endif
224fe6060f1SDimitry Andric   Symb.p = NextSymbolAddr;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2278bcb0991SDimitry Andric Expected<StringRef>
2288bcb0991SDimitry Andric XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
2298bcb0991SDimitry Andric   // The byte offset is relative to the start of the string table.
2308bcb0991SDimitry Andric   // A byte offset value of 0 is a null or zero-length symbol
2310b57cec5SDimitry Andric   // name. A byte offset in the range 1 to 3 (inclusive) points into the length
2320b57cec5SDimitry Andric   // field; as a soft-error recovery mechanism, we treat such cases as having an
2330b57cec5SDimitry Andric   // offset of 0.
2340b57cec5SDimitry Andric   if (Offset < 4)
2350b57cec5SDimitry Andric     return StringRef(nullptr, 0);
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   if (StringTable.Data != nullptr && StringTable.Size > Offset)
2380b57cec5SDimitry Andric     return (StringTable.Data + Offset);
2390b57cec5SDimitry Andric 
240349cc55cSDimitry Andric   return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
241349cc55cSDimitry Andric                      " in a string table with size 0x" +
242349cc55cSDimitry Andric                      Twine::utohexstr(StringTable.Size) + " is invalid");
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
245fe6060f1SDimitry Andric StringRef XCOFFObjectFile::getStringTable() const {
246349cc55cSDimitry Andric   // If the size is less than or equal to 4, then the string table contains no
247349cc55cSDimitry Andric   // string data.
248349cc55cSDimitry Andric   return StringRef(StringTable.Data,
249349cc55cSDimitry Andric                    StringTable.Size <= 4 ? 0 : StringTable.Size);
250fe6060f1SDimitry Andric }
251fe6060f1SDimitry Andric 
2528bcb0991SDimitry Andric Expected<StringRef>
2538bcb0991SDimitry Andric XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
254fe6060f1SDimitry Andric   if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
2558bcb0991SDimitry Andric     return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
2568bcb0991SDimitry Andric   return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
2578bcb0991SDimitry Andric }
2588bcb0991SDimitry Andric 
2598bcb0991SDimitry Andric Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
260fe6060f1SDimitry Andric   return toSymbolRef(Symb).getName();
2618bcb0991SDimitry Andric }
2628bcb0991SDimitry Andric 
2630b57cec5SDimitry Andric Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
264fe6060f1SDimitry Andric   return toSymbolRef(Symb).getValue();
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
268fe6060f1SDimitry Andric   return toSymbolRef(Symb).getValue();
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
271349cc55cSDimitry Andric uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
272349cc55cSDimitry Andric   uint64_t Result = 0;
273349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
274349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
275349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
276349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
277349cc55cSDimitry Andric     if (!CsectAuxRefOrError)
278349cc55cSDimitry Andric       // TODO: report the error up the stack.
279349cc55cSDimitry Andric       consumeError(CsectAuxRefOrError.takeError());
280349cc55cSDimitry Andric     else
281349cc55cSDimitry Andric       Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2();
282349cc55cSDimitry Andric   }
283349cc55cSDimitry Andric   return Result;
284349cc55cSDimitry Andric }
285349cc55cSDimitry Andric 
2860b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
2870b57cec5SDimitry Andric   uint64_t Result = 0;
288349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
289349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
290349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
291349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
292349cc55cSDimitry Andric     if (!CsectAuxRefOrError)
293349cc55cSDimitry Andric       // TODO: report the error up the stack.
294349cc55cSDimitry Andric       consumeError(CsectAuxRefOrError.takeError());
295349cc55cSDimitry Andric     else {
296349cc55cSDimitry Andric       XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
297349cc55cSDimitry Andric       assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM);
298349cc55cSDimitry Andric       Result = CsectAuxRef.getSectionOrLength();
299349cc55cSDimitry Andric     }
300349cc55cSDimitry Andric   }
3010b57cec5SDimitry Andric   return Result;
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric Expected<SymbolRef::Type>
3050b57cec5SDimitry Andric XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
306349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
307349cc55cSDimitry Andric 
3085f757f3fSDimitry Andric   Expected<bool> IsFunction = XCOFFSym.isFunction();
3095f757f3fSDimitry Andric   if (!IsFunction)
3105f757f3fSDimitry Andric     return IsFunction.takeError();
3115f757f3fSDimitry Andric 
3125f757f3fSDimitry Andric   if (*IsFunction)
313349cc55cSDimitry Andric     return SymbolRef::ST_Function;
314349cc55cSDimitry Andric 
315349cc55cSDimitry Andric   if (XCOFF::C_FILE == XCOFFSym.getStorageClass())
316349cc55cSDimitry Andric     return SymbolRef::ST_File;
317349cc55cSDimitry Andric 
318349cc55cSDimitry Andric   int16_t SecNum = XCOFFSym.getSectionNumber();
319349cc55cSDimitry Andric   if (SecNum <= 0)
320349cc55cSDimitry Andric     return SymbolRef::ST_Other;
321349cc55cSDimitry Andric 
322349cc55cSDimitry Andric   Expected<DataRefImpl> SecDRIOrErr =
323349cc55cSDimitry Andric       getSectionByNum(XCOFFSym.getSectionNumber());
324349cc55cSDimitry Andric 
325349cc55cSDimitry Andric   if (!SecDRIOrErr)
326349cc55cSDimitry Andric     return SecDRIOrErr.takeError();
327349cc55cSDimitry Andric 
328349cc55cSDimitry Andric   DataRefImpl SecDRI = SecDRIOrErr.get();
329349cc55cSDimitry Andric 
330349cc55cSDimitry Andric   Expected<StringRef> SymNameOrError = XCOFFSym.getName();
331349cc55cSDimitry Andric   if (SymNameOrError) {
332349cc55cSDimitry Andric     // The "TOC" symbol is treated as SymbolRef::ST_Other.
333349cc55cSDimitry Andric     if (SymNameOrError.get() == "TOC")
334349cc55cSDimitry Andric       return SymbolRef::ST_Other;
335349cc55cSDimitry Andric 
336349cc55cSDimitry Andric     // The symbol for a section name is treated as SymbolRef::ST_Other.
337349cc55cSDimitry Andric     StringRef SecName;
338349cc55cSDimitry Andric     if (is64Bit())
339349cc55cSDimitry Andric       SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName();
340349cc55cSDimitry Andric     else
341349cc55cSDimitry Andric       SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName();
342349cc55cSDimitry Andric 
343349cc55cSDimitry Andric     if (SecName == SymNameOrError.get())
344349cc55cSDimitry Andric       return SymbolRef::ST_Other;
345349cc55cSDimitry Andric   } else
346349cc55cSDimitry Andric     return SymNameOrError.takeError();
347349cc55cSDimitry Andric 
348349cc55cSDimitry Andric   if (isSectionData(SecDRI) || isSectionBSS(SecDRI))
349349cc55cSDimitry Andric     return SymbolRef::ST_Data;
350349cc55cSDimitry Andric 
351349cc55cSDimitry Andric   if (isDebugSection(SecDRI))
352349cc55cSDimitry Andric     return SymbolRef::ST_Debug;
353349cc55cSDimitry Andric 
3540b57cec5SDimitry Andric   return SymbolRef::ST_Other;
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric Expected<section_iterator>
3580b57cec5SDimitry Andric XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
359fe6060f1SDimitry Andric   const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   if (isReservedSectionNumber(SectNum))
3620b57cec5SDimitry Andric     return section_end();
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
3650b57cec5SDimitry Andric   if (!ExpSec)
3660b57cec5SDimitry Andric     return ExpSec.takeError();
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   return section_iterator(SectionRef(ExpSec.get(), this));
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
3720b57cec5SDimitry Andric   const char *Ptr = reinterpret_cast<const char *>(Sec.p);
3730b57cec5SDimitry Andric   Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
3778bcb0991SDimitry Andric   return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
3810b57cec5SDimitry Andric   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
3820b57cec5SDimitry Andric   // with MSVC.
3830b57cec5SDimitry Andric   if (is64Bit())
3840b57cec5SDimitry Andric     return toSection64(Sec)->VirtualAddress;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   return toSection32(Sec)->VirtualAddress;
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
3900b57cec5SDimitry Andric   // Section numbers in XCOFF are numbered beginning at 1. A section number of
3910b57cec5SDimitry Andric   // zero is used to indicate that a symbol is being imported or is undefined.
3920b57cec5SDimitry Andric   if (is64Bit())
3930b57cec5SDimitry Andric     return toSection64(Sec) - sectionHeaderTable64() + 1;
3940b57cec5SDimitry Andric   else
3950b57cec5SDimitry Andric     return toSection32(Sec) - sectionHeaderTable32() + 1;
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
3990b57cec5SDimitry Andric   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
4000b57cec5SDimitry Andric   // with MSVC.
4010b57cec5SDimitry Andric   if (is64Bit())
4020b57cec5SDimitry Andric     return toSection64(Sec)->SectionSize;
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   return toSection32(Sec)->SectionSize;
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
4080b57cec5SDimitry Andric XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
409480093f4SDimitry Andric   if (isSectionVirtual(Sec))
410480093f4SDimitry Andric     return ArrayRef<uint8_t>();
411480093f4SDimitry Andric 
412480093f4SDimitry Andric   uint64_t OffsetToRaw;
413480093f4SDimitry Andric   if (is64Bit())
414480093f4SDimitry Andric     OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
415480093f4SDimitry Andric   else
416480093f4SDimitry Andric     OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
417480093f4SDimitry Andric 
418480093f4SDimitry Andric   const uint8_t * ContentStart = base() + OffsetToRaw;
419480093f4SDimitry Andric   uint64_t SectionSize = getSectionSize(Sec);
420349cc55cSDimitry Andric   if (Error E = Binary::checkOffset(
421349cc55cSDimitry Andric           Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
422349cc55cSDimitry Andric     return createError(
423349cc55cSDimitry Andric         toString(std::move(E)) + ": section data with offset 0x" +
424349cc55cSDimitry Andric         Twine::utohexstr(OffsetToRaw) + " and size 0x" +
425349cc55cSDimitry Andric         Twine::utohexstr(SectionSize) + " goes past the end of the file");
426480093f4SDimitry Andric 
427bdd1243dSDimitry Andric   return ArrayRef(ContentStart, SectionSize);
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
4310b57cec5SDimitry Andric   uint64_t Result = 0;
4320b57cec5SDimitry Andric   llvm_unreachable("Not yet implemented!");
4330b57cec5SDimitry Andric   return Result;
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric 
436bdd1243dSDimitry Andric uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const {
437bdd1243dSDimitry Andric   if (is64Bit())
438bdd1243dSDimitry Andric     return toSection64(Sec)->FileOffsetToRawData;
439349cc55cSDimitry Andric 
440bdd1243dSDimitry Andric   return toSection32(Sec)->FileOffsetToRawData;
441349cc55cSDimitry Andric }
442349cc55cSDimitry Andric 
443bdd1243dSDimitry Andric Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData(
444bdd1243dSDimitry Andric     XCOFF::SectionTypeFlags SectType) const {
445bdd1243dSDimitry Andric   DataRefImpl DRI = getSectionByType(SectType);
446bdd1243dSDimitry Andric 
447bdd1243dSDimitry Andric   if (DRI.p == 0) // No section is not an error.
448349cc55cSDimitry Andric     return 0;
449349cc55cSDimitry Andric 
450bdd1243dSDimitry Andric   uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI);
451bdd1243dSDimitry Andric   uint64_t SizeOfSection = getSectionSize(DRI);
452349cc55cSDimitry Andric 
453bdd1243dSDimitry Andric   uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset);
454bdd1243dSDimitry Andric   if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) {
455bdd1243dSDimitry Andric     SmallString<32> UnknownType;
456bdd1243dSDimitry Andric     Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">")
457bdd1243dSDimitry Andric         .toVector(UnknownType);
458bdd1243dSDimitry Andric     const char *SectionName = UnknownType.c_str();
459bdd1243dSDimitry Andric 
460bdd1243dSDimitry Andric     switch (SectType) {
461bdd1243dSDimitry Andric #define ECASE(Value, String)                                                   \
462bdd1243dSDimitry Andric   case XCOFF::Value:                                                           \
463bdd1243dSDimitry Andric     SectionName = String;                                                      \
464bdd1243dSDimitry Andric     break
465bdd1243dSDimitry Andric 
466bdd1243dSDimitry Andric       ECASE(STYP_PAD, "pad");
467bdd1243dSDimitry Andric       ECASE(STYP_DWARF, "dwarf");
468bdd1243dSDimitry Andric       ECASE(STYP_TEXT, "text");
469bdd1243dSDimitry Andric       ECASE(STYP_DATA, "data");
470bdd1243dSDimitry Andric       ECASE(STYP_BSS, "bss");
471bdd1243dSDimitry Andric       ECASE(STYP_EXCEPT, "expect");
472bdd1243dSDimitry Andric       ECASE(STYP_INFO, "info");
473bdd1243dSDimitry Andric       ECASE(STYP_TDATA, "tdata");
474bdd1243dSDimitry Andric       ECASE(STYP_TBSS, "tbss");
475bdd1243dSDimitry Andric       ECASE(STYP_LOADER, "loader");
476bdd1243dSDimitry Andric       ECASE(STYP_DEBUG, "debug");
477bdd1243dSDimitry Andric       ECASE(STYP_TYPCHK, "typchk");
478bdd1243dSDimitry Andric       ECASE(STYP_OVRFLO, "ovrflo");
479bdd1243dSDimitry Andric #undef ECASE
480bdd1243dSDimitry Andric     }
481bdd1243dSDimitry Andric     return createError(toString(std::move(E)) + ": " + SectionName +
482bdd1243dSDimitry Andric                        " section with offset 0x" +
483bdd1243dSDimitry Andric                        Twine::utohexstr(SectionOffset) + " and size 0x" +
484bdd1243dSDimitry Andric                        Twine::utohexstr(SizeOfSection) +
485bdd1243dSDimitry Andric                        " goes past the end of the file");
486bdd1243dSDimitry Andric   }
487bdd1243dSDimitry Andric   return SectionStart;
488349cc55cSDimitry Andric }
489349cc55cSDimitry Andric 
4900b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
491fe6060f1SDimitry Andric   return false;
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
4950b57cec5SDimitry Andric   return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
4990b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(Sec);
5000b57cec5SDimitry Andric   return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
5040b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(Sec);
5050b57cec5SDimitry Andric   return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric 
508fe6060f1SDimitry Andric bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const {
509fe6060f1SDimitry Andric   uint32_t Flags = getSectionFlags(Sec);
510fe6060f1SDimitry Andric   return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF);
511fe6060f1SDimitry Andric }
512fe6060f1SDimitry Andric 
5130b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
514480093f4SDimitry Andric   return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
515480093f4SDimitry Andric                    : toSection32(Sec)->FileOffsetToRawData == 0;
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
5195ffd83dbSDimitry Andric   DataRefImpl Ret;
520349cc55cSDimitry Andric   if (is64Bit()) {
521349cc55cSDimitry Andric     const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
522349cc55cSDimitry Andric     auto RelocationsOrErr =
523349cc55cSDimitry Andric         relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
524349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
525349cc55cSDimitry Andric       // TODO: report the error up the stack.
526349cc55cSDimitry Andric       consumeError(std::move(E));
527349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
528349cc55cSDimitry Andric     }
5295ffd83dbSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
530349cc55cSDimitry Andric   } else {
531349cc55cSDimitry Andric     const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
532349cc55cSDimitry Andric     auto RelocationsOrErr =
533349cc55cSDimitry Andric         relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
534349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
535349cc55cSDimitry Andric       // TODO: report the error up the stack.
536349cc55cSDimitry Andric       consumeError(std::move(E));
537349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
538349cc55cSDimitry Andric     }
539349cc55cSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
540349cc55cSDimitry Andric   }
5415ffd83dbSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
5455ffd83dbSDimitry Andric   DataRefImpl Ret;
546349cc55cSDimitry Andric   if (is64Bit()) {
547349cc55cSDimitry Andric     const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
548349cc55cSDimitry Andric     auto RelocationsOrErr =
549349cc55cSDimitry Andric         relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
550349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
551349cc55cSDimitry Andric       // TODO: report the error up the stack.
552349cc55cSDimitry Andric       consumeError(std::move(E));
553349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
554349cc55cSDimitry Andric     }
5555ffd83dbSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
556349cc55cSDimitry Andric   } else {
557349cc55cSDimitry Andric     const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
558349cc55cSDimitry Andric     auto RelocationsOrErr =
559349cc55cSDimitry Andric         relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
560349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
561349cc55cSDimitry Andric       // TODO: report the error up the stack.
562349cc55cSDimitry Andric       consumeError(std::move(E));
563349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
564349cc55cSDimitry Andric     }
565349cc55cSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
566349cc55cSDimitry Andric   }
5675ffd83dbSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
571349cc55cSDimitry Andric   if (is64Bit())
572349cc55cSDimitry Andric     Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1);
573349cc55cSDimitry Andric   else
5745ffd83dbSDimitry Andric     Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
578349cc55cSDimitry Andric   if (is64Bit()) {
579349cc55cSDimitry Andric     const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
580349cc55cSDimitry Andric     const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64();
581349cc55cSDimitry Andric     const uint64_t RelocAddress = Reloc->VirtualAddress;
582349cc55cSDimitry Andric     const uint16_t NumberOfSections = getNumberOfSections();
583349cc55cSDimitry Andric     for (uint16_t I = 0; I < NumberOfSections; ++I) {
584349cc55cSDimitry Andric       // Find which section this relocation belongs to, and get the
585349cc55cSDimitry Andric       // relocation offset relative to the start of the section.
586349cc55cSDimitry Andric       if (Sec64->VirtualAddress <= RelocAddress &&
587349cc55cSDimitry Andric           RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) {
588349cc55cSDimitry Andric         return RelocAddress - Sec64->VirtualAddress;
589349cc55cSDimitry Andric       }
590349cc55cSDimitry Andric       ++Sec64;
591349cc55cSDimitry Andric     }
592349cc55cSDimitry Andric   } else {
5935ffd83dbSDimitry Andric     const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
5945ffd83dbSDimitry Andric     const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
5955ffd83dbSDimitry Andric     const uint32_t RelocAddress = Reloc->VirtualAddress;
5965ffd83dbSDimitry Andric     const uint16_t NumberOfSections = getNumberOfSections();
597349cc55cSDimitry Andric     for (uint16_t I = 0; I < NumberOfSections; ++I) {
598349cc55cSDimitry Andric       // Find which section this relocation belongs to, and get the
5995ffd83dbSDimitry Andric       // relocation offset relative to the start of the section.
6005ffd83dbSDimitry Andric       if (Sec32->VirtualAddress <= RelocAddress &&
6015ffd83dbSDimitry Andric           RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
6025ffd83dbSDimitry Andric         return RelocAddress - Sec32->VirtualAddress;
6035ffd83dbSDimitry Andric       }
6045ffd83dbSDimitry Andric       ++Sec32;
6055ffd83dbSDimitry Andric     }
606349cc55cSDimitry Andric   }
6075ffd83dbSDimitry Andric   return InvalidRelocOffset;
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
611349cc55cSDimitry Andric   uint32_t Index;
612349cc55cSDimitry Andric   if (is64Bit()) {
613349cc55cSDimitry Andric     const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
614349cc55cSDimitry Andric     Index = Reloc->SymbolIndex;
615349cc55cSDimitry Andric 
616349cc55cSDimitry Andric     if (Index >= getNumberOfSymbolTableEntries64())
617349cc55cSDimitry Andric       return symbol_end();
618349cc55cSDimitry Andric   } else {
6195ffd83dbSDimitry Andric     const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
620349cc55cSDimitry Andric     Index = Reloc->SymbolIndex;
6215ffd83dbSDimitry Andric 
6225ffd83dbSDimitry Andric     if (Index >= getLogicalNumberOfSymbolTableEntries32())
6235ffd83dbSDimitry Andric       return symbol_end();
624349cc55cSDimitry Andric   }
6255ffd83dbSDimitry Andric   DataRefImpl SymDRI;
626fe6060f1SDimitry Andric   SymDRI.p = getSymbolEntryAddressByIndex(Index);
6275ffd83dbSDimitry Andric   return symbol_iterator(SymbolRef(SymDRI, this));
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
6315ffd83dbSDimitry Andric   if (is64Bit())
632349cc55cSDimitry Andric     return viewAs<XCOFFRelocation64>(Rel.p)->Type;
6335ffd83dbSDimitry Andric   return viewAs<XCOFFRelocation32>(Rel.p)->Type;
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric void XCOFFObjectFile::getRelocationTypeName(
6370b57cec5SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
638349cc55cSDimitry Andric   StringRef Res;
639349cc55cSDimitry Andric   if (is64Bit()) {
640349cc55cSDimitry Andric     const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
641349cc55cSDimitry Andric     Res = XCOFF::getRelocationTypeString(Reloc->Type);
642349cc55cSDimitry Andric   } else {
6435ffd83dbSDimitry Andric     const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
644349cc55cSDimitry Andric     Res = XCOFF::getRelocationTypeString(Reloc->Type);
645349cc55cSDimitry Andric   }
6465ffd83dbSDimitry Andric   Result.append(Res.begin(), Res.end());
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
6495ffd83dbSDimitry Andric Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
650349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
651349cc55cSDimitry Andric   uint32_t Result = SymbolRef::SF_None;
652349cc55cSDimitry Andric 
653349cc55cSDimitry Andric   if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS)
654349cc55cSDimitry Andric     Result |= SymbolRef::SF_Absolute;
655349cc55cSDimitry Andric 
656349cc55cSDimitry Andric   XCOFF::StorageClass SC = XCOFFSym.getStorageClass();
657349cc55cSDimitry Andric   if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC)
658349cc55cSDimitry Andric     Result |= SymbolRef::SF_Global;
659349cc55cSDimitry Andric 
660349cc55cSDimitry Andric   if (XCOFF::C_WEAKEXT == SC)
661349cc55cSDimitry Andric     Result |= SymbolRef::SF_Weak;
662349cc55cSDimitry Andric 
663349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
664349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr =
665349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
666349cc55cSDimitry Andric     if (CsectAuxEntOrErr) {
667349cc55cSDimitry Andric       if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM)
668349cc55cSDimitry Andric         Result |= SymbolRef::SF_Common;
669349cc55cSDimitry Andric     } else
670349cc55cSDimitry Andric       return CsectAuxEntOrErr.takeError();
671349cc55cSDimitry Andric   }
672349cc55cSDimitry Andric 
673349cc55cSDimitry Andric   if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF)
674349cc55cSDimitry Andric     Result |= SymbolRef::SF_Undefined;
675349cc55cSDimitry Andric 
67681ad6265SDimitry Andric   // There is no visibility in old 32 bit XCOFF object file interpret.
67781ad6265SDimitry Andric   if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() ==
67881ad6265SDimitry Andric                                             NEW_XCOFF_INTERPRET))) {
67981ad6265SDimitry Andric     uint16_t SymType = XCOFFSym.getSymbolType();
68081ad6265SDimitry Andric     if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN)
68181ad6265SDimitry Andric       Result |= SymbolRef::SF_Hidden;
68281ad6265SDimitry Andric 
68381ad6265SDimitry Andric     if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED)
68481ad6265SDimitry Andric       Result |= SymbolRef::SF_Exported;
68581ad6265SDimitry Andric   }
6860b57cec5SDimitry Andric   return Result;
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
6900b57cec5SDimitry Andric   DataRefImpl SymDRI;
6910b57cec5SDimitry Andric   SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
6920b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(SymDRI, this));
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
6960b57cec5SDimitry Andric   DataRefImpl SymDRI;
697fe6060f1SDimitry Andric   const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
698fe6060f1SDimitry Andric   SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
6990b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(SymDRI, this));
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric 
7025f757f3fSDimitry Andric XCOFFObjectFile::xcoff_symbol_iterator_range XCOFFObjectFile::symbols() const {
7035f757f3fSDimitry Andric   return xcoff_symbol_iterator_range(symbol_begin(), symbol_end());
7045f757f3fSDimitry Andric }
7055f757f3fSDimitry Andric 
7060b57cec5SDimitry Andric section_iterator XCOFFObjectFile::section_begin() const {
7070b57cec5SDimitry Andric   DataRefImpl DRI;
7080b57cec5SDimitry Andric   DRI.p = getSectionHeaderTableAddress();
7090b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric section_iterator XCOFFObjectFile::section_end() const {
7130b57cec5SDimitry Andric   DataRefImpl DRI;
7140b57cec5SDimitry Andric   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
7150b57cec5SDimitry Andric                         getNumberOfSections() * getSectionHeaderSize());
7160b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric StringRef XCOFFObjectFile::getFileFormatName() const {
7220b57cec5SDimitry Andric   return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
7230b57cec5SDimitry Andric }
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric Triple::ArchType XCOFFObjectFile::getArch() const {
7260b57cec5SDimitry Andric   return is64Bit() ? Triple::ppc64 : Triple::ppc;
7270b57cec5SDimitry Andric }
7280b57cec5SDimitry Andric 
729bdd1243dSDimitry Andric Expected<SubtargetFeatures> XCOFFObjectFile::getFeatures() const {
7300b57cec5SDimitry Andric   return SubtargetFeatures();
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric bool XCOFFObjectFile::isRelocatableObject() const {
7345ffd83dbSDimitry Andric   if (is64Bit())
735fe6060f1SDimitry Andric     return !(fileHeader64()->Flags & NoRelMask);
7365ffd83dbSDimitry Andric   return !(fileHeader32()->Flags & NoRelMask);
7370b57cec5SDimitry Andric }
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
740*0fca6ea1SDimitry Andric   if (AuxiliaryHeader == nullptr)
7410b57cec5SDimitry Andric     return 0;
742*0fca6ea1SDimitry Andric 
743*0fca6ea1SDimitry Andric   return is64Bit() ? auxiliaryHeader64()->getEntryPointAddr()
744*0fca6ea1SDimitry Andric                    : auxiliaryHeader32()->getEntryPointAddr();
7450b57cec5SDimitry Andric }
7460b57cec5SDimitry Andric 
747fe6060f1SDimitry Andric StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
748fe6060f1SDimitry Andric   return StringSwitch<StringRef>(Name)
749fe6060f1SDimitry Andric       .Case("dwinfo", "debug_info")
750fe6060f1SDimitry Andric       .Case("dwline", "debug_line")
751fe6060f1SDimitry Andric       .Case("dwpbnms", "debug_pubnames")
752fe6060f1SDimitry Andric       .Case("dwpbtyp", "debug_pubtypes")
753fe6060f1SDimitry Andric       .Case("dwarnge", "debug_aranges")
754fe6060f1SDimitry Andric       .Case("dwabrev", "debug_abbrev")
755fe6060f1SDimitry Andric       .Case("dwstr", "debug_str")
756fe6060f1SDimitry Andric       .Case("dwrnges", "debug_ranges")
757fe6060f1SDimitry Andric       .Case("dwloc", "debug_loc")
758fe6060f1SDimitry Andric       .Case("dwframe", "debug_frame")
759fe6060f1SDimitry Andric       .Case("dwmac", "debug_macinfo")
760fe6060f1SDimitry Andric       .Default(Name);
761fe6060f1SDimitry Andric }
762fe6060f1SDimitry Andric 
7630b57cec5SDimitry Andric size_t XCOFFObjectFile::getFileHeaderSize() const {
7640b57cec5SDimitry Andric   return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric size_t XCOFFObjectFile::getSectionHeaderSize() const {
7680b57cec5SDimitry Andric   return is64Bit() ? sizeof(XCOFFSectionHeader64) :
7690b57cec5SDimitry Andric                      sizeof(XCOFFSectionHeader32);
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric bool XCOFFObjectFile::is64Bit() const {
7730b57cec5SDimitry Andric   return Binary::ID_XCOFF64 == getType();
7740b57cec5SDimitry Andric }
7750b57cec5SDimitry Andric 
77681ad6265SDimitry Andric Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start,
77781ad6265SDimitry Andric                                                 uint64_t Size,
77881ad6265SDimitry Andric                                                 StringRef Name) const {
77981ad6265SDimitry Andric   uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start);
78081ad6265SDimitry Andric   // TODO: this path is untested.
78181ad6265SDimitry Andric   if (Error E = Binary::checkOffset(Data, StartPtr, Size))
78281ad6265SDimitry Andric     return createError(toString(std::move(E)) + ": " + Name.data() +
78381ad6265SDimitry Andric                        " data with offset 0x" + Twine::utohexstr(StartPtr) +
78481ad6265SDimitry Andric                        " and size 0x" + Twine::utohexstr(Size) +
78581ad6265SDimitry Andric                        " goes past the end of the file");
78681ad6265SDimitry Andric   return StringRef(Start, Size);
78781ad6265SDimitry Andric }
78881ad6265SDimitry Andric 
7890b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getMagic() const {
7900b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
7910b57cec5SDimitry Andric }
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
7940b57cec5SDimitry Andric   if (Num <= 0 || Num > getNumberOfSections())
795349cc55cSDimitry Andric     return createStringError(object_error::invalid_section_index,
796349cc55cSDimitry Andric                              "the section index (" + Twine(Num) +
797349cc55cSDimitry Andric                                  ") is invalid");
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   DataRefImpl DRI;
8000b57cec5SDimitry Andric   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
8010b57cec5SDimitry Andric                         getSectionHeaderSize() * (Num - 1));
8020b57cec5SDimitry Andric   return DRI;
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric 
805bdd1243dSDimitry Andric DataRefImpl
806bdd1243dSDimitry Andric XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const {
807bdd1243dSDimitry Andric   DataRefImpl DRI;
808bdd1243dSDimitry Andric   auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t {
809bdd1243dSDimitry Andric     for (const auto &Sec : Sections)
810bdd1243dSDimitry Andric       if (Sec.getSectionType() == SectType)
811bdd1243dSDimitry Andric         return reinterpret_cast<uintptr_t>(&Sec);
812bdd1243dSDimitry Andric     return uintptr_t(0);
813bdd1243dSDimitry Andric   };
814bdd1243dSDimitry Andric   if (is64Bit())
815bdd1243dSDimitry Andric     DRI.p = GetSectionAddr(sections64());
816bdd1243dSDimitry Andric   else
817bdd1243dSDimitry Andric     DRI.p = GetSectionAddr(sections32());
818bdd1243dSDimitry Andric   return DRI;
819bdd1243dSDimitry Andric }
820bdd1243dSDimitry Andric 
8210b57cec5SDimitry Andric Expected<StringRef>
822fe6060f1SDimitry Andric XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
823fe6060f1SDimitry Andric   const int16_t SectionNum = SymEntPtr.getSectionNumber();
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric   switch (SectionNum) {
8260b57cec5SDimitry Andric   case XCOFF::N_DEBUG:
8270b57cec5SDimitry Andric     return "N_DEBUG";
8280b57cec5SDimitry Andric   case XCOFF::N_ABS:
8290b57cec5SDimitry Andric     return "N_ABS";
8300b57cec5SDimitry Andric   case XCOFF::N_UNDEF:
8310b57cec5SDimitry Andric     return "N_UNDEF";
8320b57cec5SDimitry Andric   default:
8330b57cec5SDimitry Andric     Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
8340b57cec5SDimitry Andric     if (SecRef)
8358bcb0991SDimitry Andric       return generateXCOFFFixedNameStringRef(
8368bcb0991SDimitry Andric           getSectionNameInternal(SecRef.get()));
8370b57cec5SDimitry Andric     return SecRef.takeError();
8380b57cec5SDimitry Andric   }
8390b57cec5SDimitry Andric }
8400b57cec5SDimitry Andric 
841fe6060f1SDimitry Andric unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
842fe6060f1SDimitry Andric   XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this);
843fe6060f1SDimitry Andric   return XCOFFSymRef.getSectionNumber();
844fe6060f1SDimitry Andric }
845fe6060f1SDimitry Andric 
8460b57cec5SDimitry Andric bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
8470b57cec5SDimitry Andric   return (SectionNumber <= 0 && SectionNumber >= -2);
8480b57cec5SDimitry Andric }
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getNumberOfSections() const {
8510b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->NumberOfSections
8520b57cec5SDimitry Andric                    : fileHeader32()->NumberOfSections;
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric int32_t XCOFFObjectFile::getTimeStamp() const {
8560b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
8600b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->AuxHeaderSize
8610b57cec5SDimitry Andric                    : fileHeader32()->AuxHeaderSize;
8620b57cec5SDimitry Andric }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
8650b57cec5SDimitry Andric   return fileHeader32()->SymbolTableOffset;
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
8690b57cec5SDimitry Andric   // As far as symbol table size is concerned, if this field is negative it is
8700b57cec5SDimitry Andric   // to be treated as a 0. However since this field is also used for printing we
8710b57cec5SDimitry Andric   // don't want to truncate any negative values.
8720b57cec5SDimitry Andric   return fileHeader32()->NumberOfSymTableEntries;
8730b57cec5SDimitry Andric }
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
8760b57cec5SDimitry Andric   return (fileHeader32()->NumberOfSymTableEntries >= 0
8770b57cec5SDimitry Andric               ? fileHeader32()->NumberOfSymTableEntries
8780b57cec5SDimitry Andric               : 0);
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
8820b57cec5SDimitry Andric   return fileHeader64()->SymbolTableOffset;
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
8860b57cec5SDimitry Andric   return fileHeader64()->NumberOfSymTableEntries;
8870b57cec5SDimitry Andric }
8880b57cec5SDimitry Andric 
889fe6060f1SDimitry Andric uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
890fe6060f1SDimitry Andric   return is64Bit() ? getNumberOfSymbolTableEntries64()
8918bcb0991SDimitry Andric                    : getLogicalNumberOfSymbolTableEntries32();
892fe6060f1SDimitry Andric }
893fe6060f1SDimitry Andric 
894fe6060f1SDimitry Andric uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
895fe6060f1SDimitry Andric   const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
8968bcb0991SDimitry Andric   return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
8978bcb0991SDimitry Andric                        XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
8988bcb0991SDimitry Andric }
8998bcb0991SDimitry Andric 
9008bcb0991SDimitry Andric void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
9018bcb0991SDimitry Andric   if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
9028bcb0991SDimitry Andric     report_fatal_error("Symbol table entry is outside of symbol table.");
9038bcb0991SDimitry Andric 
9048bcb0991SDimitry Andric   if (SymbolEntPtr >= getEndOfSymbolTableAddress())
9058bcb0991SDimitry Andric     report_fatal_error("Symbol table entry is outside of symbol table.");
9068bcb0991SDimitry Andric 
9078bcb0991SDimitry Andric   ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
9088bcb0991SDimitry Andric                      reinterpret_cast<const char *>(SymbolTblPtr);
9098bcb0991SDimitry Andric 
9108bcb0991SDimitry Andric   if (Offset % XCOFF::SymbolTableEntrySize != 0)
9118bcb0991SDimitry Andric     report_fatal_error(
9128bcb0991SDimitry Andric         "Symbol table entry position is not valid inside of symbol table.");
9138bcb0991SDimitry Andric }
9148bcb0991SDimitry Andric 
9158bcb0991SDimitry Andric uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
9168bcb0991SDimitry Andric   return (reinterpret_cast<const char *>(SymbolEntPtr) -
9178bcb0991SDimitry Andric           reinterpret_cast<const char *>(SymbolTblPtr)) /
9188bcb0991SDimitry Andric          XCOFF::SymbolTableEntrySize;
9198bcb0991SDimitry Andric }
9208bcb0991SDimitry Andric 
921349cc55cSDimitry Andric uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
922349cc55cSDimitry Andric   uint64_t Result = 0;
923349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
924349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
925349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
926349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
927349cc55cSDimitry Andric     if (!CsectAuxRefOrError)
928349cc55cSDimitry Andric       // TODO: report the error up the stack.
929349cc55cSDimitry Andric       consumeError(CsectAuxRefOrError.takeError());
930349cc55cSDimitry Andric     else {
931349cc55cSDimitry Andric       XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
932349cc55cSDimitry Andric       uint8_t SymType = CsectAuxRef.getSymbolType();
933349cc55cSDimitry Andric       if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM)
934349cc55cSDimitry Andric         Result = CsectAuxRef.getSectionOrLength();
935349cc55cSDimitry Andric     }
936349cc55cSDimitry Andric   }
937349cc55cSDimitry Andric   return Result;
938349cc55cSDimitry Andric }
939349cc55cSDimitry Andric 
940fe6060f1SDimitry Andric uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
941fe6060f1SDimitry Andric   return getAdvancedSymbolEntryAddress(
942fe6060f1SDimitry Andric       reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
943fe6060f1SDimitry Andric }
944fe6060f1SDimitry Andric 
9458bcb0991SDimitry Andric Expected<StringRef>
9468bcb0991SDimitry Andric XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
947fe6060f1SDimitry Andric   const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
9488bcb0991SDimitry Andric 
949fe6060f1SDimitry Andric   if (Index >= NumberOfSymTableEntries)
950349cc55cSDimitry Andric     return createError("symbol index " + Twine(Index) +
951349cc55cSDimitry Andric                        " exceeds symbol count " +
952349cc55cSDimitry Andric                        Twine(NumberOfSymTableEntries));
9538bcb0991SDimitry Andric 
9548bcb0991SDimitry Andric   DataRefImpl SymDRI;
955fe6060f1SDimitry Andric   SymDRI.p = getSymbolEntryAddressByIndex(Index);
9568bcb0991SDimitry Andric   return getSymbolName(SymDRI);
9578bcb0991SDimitry Andric }
9588bcb0991SDimitry Andric 
9590b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getFlags() const {
9600b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
9640b57cec5SDimitry Andric   return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
9680b57cec5SDimitry Andric   return reinterpret_cast<uintptr_t>(SectionHeaderTable);
9690b57cec5SDimitry Andric }
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
9720b57cec5SDimitry Andric   return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
9760b57cec5SDimitry Andric     : ObjectFile(Type, Object) {
9770b57cec5SDimitry Andric   assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
9780b57cec5SDimitry Andric }
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
9810b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called for non 64-bit file.");
9820b57cec5SDimitry Andric   const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
9830b57cec5SDimitry Andric   return ArrayRef<XCOFFSectionHeader64>(TablePtr,
9840b57cec5SDimitry Andric                                         TablePtr + getNumberOfSections());
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
9880b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
9890b57cec5SDimitry Andric   const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
9900b57cec5SDimitry Andric   return ArrayRef<XCOFFSectionHeader32>(TablePtr,
9910b57cec5SDimitry Andric                                         TablePtr + getNumberOfSections());
9920b57cec5SDimitry Andric }
9930b57cec5SDimitry Andric 
9948bcb0991SDimitry Andric // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
9958bcb0991SDimitry Andric // section header contains the actual count of relocation entries in the s_paddr
9968bcb0991SDimitry Andric // field. STYP_OVRFLO headers contain the section index of their corresponding
9978bcb0991SDimitry Andric // sections as their raw "NumberOfRelocations" field value.
998349cc55cSDimitry Andric template <typename T>
999349cc55cSDimitry Andric Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries(
1000349cc55cSDimitry Andric     const XCOFFSectionHeader<T> &Sec) const {
1001349cc55cSDimitry Andric   const T &Section = static_cast<const T &>(Sec);
1002349cc55cSDimitry Andric   if (is64Bit())
1003349cc55cSDimitry Andric     return Section.NumberOfRelocations;
10048bcb0991SDimitry Andric 
1005349cc55cSDimitry Andric   uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1;
1006349cc55cSDimitry Andric   if (Section.NumberOfRelocations < XCOFF::RelocOverflow)
1007349cc55cSDimitry Andric     return Section.NumberOfRelocations;
10088bcb0991SDimitry Andric   for (const auto &Sec : sections32()) {
10098bcb0991SDimitry Andric     if (Sec.Flags == XCOFF::STYP_OVRFLO &&
10108bcb0991SDimitry Andric         Sec.NumberOfRelocations == SectionIndex)
10118bcb0991SDimitry Andric       return Sec.PhysicalAddress;
10128bcb0991SDimitry Andric   }
10138bcb0991SDimitry Andric   return errorCodeToError(object_error::parse_failed);
10148bcb0991SDimitry Andric }
10158bcb0991SDimitry Andric 
1016349cc55cSDimitry Andric template <typename Shdr, typename Reloc>
1017349cc55cSDimitry Andric Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
10188bcb0991SDimitry Andric   uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
10198bcb0991SDimitry Andric                                       Sec.FileOffsetToRelocationInfo);
1020349cc55cSDimitry Andric   auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec);
10218bcb0991SDimitry Andric   if (Error E = NumRelocEntriesOrErr.takeError())
10228bcb0991SDimitry Andric     return std::move(E);
10238bcb0991SDimitry Andric 
10248bcb0991SDimitry Andric   uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
1025349cc55cSDimitry Andric   static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 ||
1026349cc55cSDimitry Andric                  sizeof(Reloc) == XCOFF::RelocationSerializationSize32),
1027349cc55cSDimitry Andric                 "Relocation structure is incorrect");
10288bcb0991SDimitry Andric   auto RelocationOrErr =
1029349cc55cSDimitry Andric       getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
1030349cc55cSDimitry Andric                        NumRelocEntries * sizeof(Reloc));
1031349cc55cSDimitry Andric   if (!RelocationOrErr)
1032349cc55cSDimitry Andric     return createError(
1033349cc55cSDimitry Andric         toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" +
1034349cc55cSDimitry Andric         Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" +
1035349cc55cSDimitry Andric         Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) +
1036349cc55cSDimitry Andric         " go past the end of the file");
10378bcb0991SDimitry Andric 
1038349cc55cSDimitry Andric   const Reloc *StartReloc = RelocationOrErr.get();
10398bcb0991SDimitry Andric 
1040349cc55cSDimitry Andric   return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
10418bcb0991SDimitry Andric }
10428bcb0991SDimitry Andric 
1043bdd1243dSDimitry Andric template <typename ExceptEnt>
1044bdd1243dSDimitry Andric Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const {
1045bdd1243dSDimitry Andric   assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) ||
1046bdd1243dSDimitry Andric          (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32)));
1047bdd1243dSDimitry Andric 
1048bdd1243dSDimitry Andric   Expected<uintptr_t> ExceptionSectOrErr =
1049bdd1243dSDimitry Andric       getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT);
1050bdd1243dSDimitry Andric   if (!ExceptionSectOrErr)
1051bdd1243dSDimitry Andric     return ExceptionSectOrErr.takeError();
1052bdd1243dSDimitry Andric 
1053bdd1243dSDimitry Andric   DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT);
1054bdd1243dSDimitry Andric   if (DRI.p == 0)
1055bdd1243dSDimitry Andric     return ArrayRef<ExceptEnt>();
1056bdd1243dSDimitry Andric 
1057bdd1243dSDimitry Andric   ExceptEnt *ExceptEntStart =
1058bdd1243dSDimitry Andric       reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr);
1059bdd1243dSDimitry Andric   return ArrayRef<ExceptEnt>(
1060bdd1243dSDimitry Andric       ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt));
1061bdd1243dSDimitry Andric }
1062bdd1243dSDimitry Andric 
1063bdd1243dSDimitry Andric template Expected<ArrayRef<ExceptionSectionEntry32>>
1064bdd1243dSDimitry Andric XCOFFObjectFile::getExceptionEntries() const;
1065bdd1243dSDimitry Andric template Expected<ArrayRef<ExceptionSectionEntry64>>
1066bdd1243dSDimitry Andric XCOFFObjectFile::getExceptionEntries() const;
1067bdd1243dSDimitry Andric 
10680b57cec5SDimitry Andric Expected<XCOFFStringTable>
10690b57cec5SDimitry Andric XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
10700b57cec5SDimitry Andric   // If there is a string table, then the buffer must contain at least 4 bytes
10710b57cec5SDimitry Andric   // for the string table's size. Not having a string table is not an error.
10725ffd83dbSDimitry Andric   if (Error E = Binary::checkOffset(
10735ffd83dbSDimitry Andric           Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
10745ffd83dbSDimitry Andric     consumeError(std::move(E));
10750b57cec5SDimitry Andric     return XCOFFStringTable{0, nullptr};
10765ffd83dbSDimitry Andric   }
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   // Read the size out of the buffer.
10790b57cec5SDimitry Andric   uint32_t Size = support::endian::read32be(Obj->base() + Offset);
10800b57cec5SDimitry Andric 
10810b57cec5SDimitry Andric   // If the size is less then 4, then the string table is just a size and no
10820b57cec5SDimitry Andric   // string data.
10830b57cec5SDimitry Andric   if (Size <= 4)
10840b57cec5SDimitry Andric     return XCOFFStringTable{4, nullptr};
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   auto StringTableOrErr =
10870b57cec5SDimitry Andric       getObject<char>(Obj->Data, Obj->base() + Offset, Size);
1088349cc55cSDimitry Andric   if (!StringTableOrErr)
1089349cc55cSDimitry Andric     return createError(toString(StringTableOrErr.takeError()) +
1090349cc55cSDimitry Andric                        ": string table with offset 0x" +
1091349cc55cSDimitry Andric                        Twine::utohexstr(Offset) + " and size 0x" +
1092349cc55cSDimitry Andric                        Twine::utohexstr(Size) +
1093349cc55cSDimitry Andric                        " goes past the end of the file");
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric   const char *StringTablePtr = StringTableOrErr.get();
10960b57cec5SDimitry Andric   if (StringTablePtr[Size - 1] != '\0')
10970b57cec5SDimitry Andric     return errorCodeToError(object_error::string_table_non_null_end);
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   return XCOFFStringTable{Size, StringTablePtr};
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric 
1102349cc55cSDimitry Andric // This function returns the import file table. Each entry in the import file
1103349cc55cSDimitry Andric // table consists of: "path_name\0base_name\0archive_member_name\0".
1104349cc55cSDimitry Andric Expected<StringRef> XCOFFObjectFile::getImportFileTable() const {
1105bdd1243dSDimitry Andric   Expected<uintptr_t> LoaderSectionAddrOrError =
1106bdd1243dSDimitry Andric       getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
1107349cc55cSDimitry Andric   if (!LoaderSectionAddrOrError)
1108349cc55cSDimitry Andric     return LoaderSectionAddrOrError.takeError();
1109349cc55cSDimitry Andric 
1110349cc55cSDimitry Andric   uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
1111349cc55cSDimitry Andric   if (!LoaderSectionAddr)
1112349cc55cSDimitry Andric     return StringRef();
1113349cc55cSDimitry Andric 
1114349cc55cSDimitry Andric   uint64_t OffsetToImportFileTable = 0;
1115349cc55cSDimitry Andric   uint64_t LengthOfImportFileTable = 0;
1116349cc55cSDimitry Andric   if (is64Bit()) {
1117349cc55cSDimitry Andric     const LoaderSectionHeader64 *LoaderSec64 =
1118349cc55cSDimitry Andric         viewAs<LoaderSectionHeader64>(LoaderSectionAddr);
1119349cc55cSDimitry Andric     OffsetToImportFileTable = LoaderSec64->OffsetToImpid;
1120349cc55cSDimitry Andric     LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl;
1121349cc55cSDimitry Andric   } else {
1122349cc55cSDimitry Andric     const LoaderSectionHeader32 *LoaderSec32 =
1123349cc55cSDimitry Andric         viewAs<LoaderSectionHeader32>(LoaderSectionAddr);
1124349cc55cSDimitry Andric     OffsetToImportFileTable = LoaderSec32->OffsetToImpid;
1125349cc55cSDimitry Andric     LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl;
1126349cc55cSDimitry Andric   }
1127349cc55cSDimitry Andric 
1128349cc55cSDimitry Andric   auto ImportTableOrErr = getObject<char>(
1129349cc55cSDimitry Andric       Data,
1130349cc55cSDimitry Andric       reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable),
1131349cc55cSDimitry Andric       LengthOfImportFileTable);
1132349cc55cSDimitry Andric   if (!ImportTableOrErr)
1133349cc55cSDimitry Andric     return createError(
1134349cc55cSDimitry Andric         toString(ImportTableOrErr.takeError()) +
1135349cc55cSDimitry Andric         ": import file table with offset 0x" +
1136349cc55cSDimitry Andric         Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1137349cc55cSDimitry Andric         " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1138349cc55cSDimitry Andric         " goes past the end of the file");
1139349cc55cSDimitry Andric 
1140349cc55cSDimitry Andric   const char *ImportTablePtr = ImportTableOrErr.get();
1141349cc55cSDimitry Andric   if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0')
1142349cc55cSDimitry Andric     return createError(
1143349cc55cSDimitry Andric         ": import file name table with offset 0x" +
1144349cc55cSDimitry Andric         Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1145349cc55cSDimitry Andric         " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1146349cc55cSDimitry Andric         " must end with a null terminator");
1147349cc55cSDimitry Andric 
1148349cc55cSDimitry Andric   return StringRef(ImportTablePtr, LengthOfImportFileTable);
1149349cc55cSDimitry Andric }
1150349cc55cSDimitry Andric 
11510b57cec5SDimitry Andric Expected<std::unique_ptr<XCOFFObjectFile>>
11520b57cec5SDimitry Andric XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
11538bcb0991SDimitry Andric   // Can't use std::make_unique because of the private constructor.
11540b57cec5SDimitry Andric   std::unique_ptr<XCOFFObjectFile> Obj;
11550b57cec5SDimitry Andric   Obj.reset(new XCOFFObjectFile(Type, MBR));
11560b57cec5SDimitry Andric 
11570b57cec5SDimitry Andric   uint64_t CurOffset = 0;
11580b57cec5SDimitry Andric   const auto *Base = Obj->base();
11590b57cec5SDimitry Andric   MemoryBufferRef Data = Obj->Data;
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric   // Parse file header.
11620b57cec5SDimitry Andric   auto FileHeaderOrErr =
11630b57cec5SDimitry Andric       getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
11640b57cec5SDimitry Andric   if (Error E = FileHeaderOrErr.takeError())
11650b57cec5SDimitry Andric     return std::move(E);
11660b57cec5SDimitry Andric   Obj->FileHeader = FileHeaderOrErr.get();
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric   CurOffset += Obj->getFileHeaderSize();
1169349cc55cSDimitry Andric 
1170349cc55cSDimitry Andric   if (Obj->getOptionalHeaderSize()) {
1171349cc55cSDimitry Andric     auto AuxiliaryHeaderOrErr =
1172349cc55cSDimitry Andric         getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize());
1173349cc55cSDimitry Andric     if (Error E = AuxiliaryHeaderOrErr.takeError())
1174349cc55cSDimitry Andric       return std::move(E);
1175349cc55cSDimitry Andric     Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get();
1176349cc55cSDimitry Andric   }
1177349cc55cSDimitry Andric 
11780b57cec5SDimitry Andric   CurOffset += Obj->getOptionalHeaderSize();
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric   // Parse the section header table if it is present.
11810b57cec5SDimitry Andric   if (Obj->getNumberOfSections()) {
1182349cc55cSDimitry Andric     uint64_t SectionHeadersSize =
1183349cc55cSDimitry Andric         Obj->getNumberOfSections() * Obj->getSectionHeaderSize();
1184349cc55cSDimitry Andric     auto SecHeadersOrErr =
1185349cc55cSDimitry Andric         getObject<void>(Data, Base + CurOffset, SectionHeadersSize);
1186349cc55cSDimitry Andric     if (!SecHeadersOrErr)
1187349cc55cSDimitry Andric       return createError(toString(SecHeadersOrErr.takeError()) +
1188349cc55cSDimitry Andric                          ": section headers with offset 0x" +
1189349cc55cSDimitry Andric                          Twine::utohexstr(CurOffset) + " and size 0x" +
1190349cc55cSDimitry Andric                          Twine::utohexstr(SectionHeadersSize) +
1191349cc55cSDimitry Andric                          " go past the end of the file");
1192349cc55cSDimitry Andric 
11930b57cec5SDimitry Andric     Obj->SectionHeaderTable = SecHeadersOrErr.get();
11940b57cec5SDimitry Andric   }
11950b57cec5SDimitry Andric 
1196fe6060f1SDimitry Andric   const uint32_t NumberOfSymbolTableEntries =
1197fe6060f1SDimitry Andric       Obj->getNumberOfSymbolTableEntries();
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric   // If there is no symbol table we are done parsing the memory buffer.
1200fe6060f1SDimitry Andric   if (NumberOfSymbolTableEntries == 0)
12010b57cec5SDimitry Andric     return std::move(Obj);
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric   // Parse symbol table.
1204fe6060f1SDimitry Andric   CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
1205fe6060f1SDimitry Andric                              : Obj->getSymbolTableOffset32();
1206fe6060f1SDimitry Andric   const uint64_t SymbolTableSize =
1207fe6060f1SDimitry Andric       static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
1208fe6060f1SDimitry Andric       NumberOfSymbolTableEntries;
12090b57cec5SDimitry Andric   auto SymTableOrErr =
1210fe6060f1SDimitry Andric       getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
1211349cc55cSDimitry Andric   if (!SymTableOrErr)
1212349cc55cSDimitry Andric     return createError(
1213349cc55cSDimitry Andric         toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" +
1214349cc55cSDimitry Andric         Twine::utohexstr(CurOffset) + " and size 0x" +
1215349cc55cSDimitry Andric         Twine::utohexstr(SymbolTableSize) + " goes past the end of the file");
1216349cc55cSDimitry Andric 
12170b57cec5SDimitry Andric   Obj->SymbolTblPtr = SymTableOrErr.get();
12180b57cec5SDimitry Andric   CurOffset += SymbolTableSize;
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric   // Parse String table.
12210b57cec5SDimitry Andric   Expected<XCOFFStringTable> StringTableOrErr =
12220b57cec5SDimitry Andric       parseStringTable(Obj.get(), CurOffset);
12230b57cec5SDimitry Andric   if (Error E = StringTableOrErr.takeError())
12240b57cec5SDimitry Andric     return std::move(E);
12250b57cec5SDimitry Andric   Obj->StringTable = StringTableOrErr.get();
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric   return std::move(Obj);
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
12310b57cec5SDimitry Andric ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
12320b57cec5SDimitry Andric                                   unsigned FileType) {
12330b57cec5SDimitry Andric   return XCOFFObjectFile::create(FileType, MemBufRef);
12340b57cec5SDimitry Andric }
12350b57cec5SDimitry Andric 
123606c3fb27SDimitry Andric std::optional<StringRef> XCOFFObjectFile::tryGetCPUName() const {
123706c3fb27SDimitry Andric   return StringRef("future");
123806c3fb27SDimitry Andric }
123906c3fb27SDimitry Andric 
12405f757f3fSDimitry Andric Expected<bool> XCOFFSymbolRef::isFunction() const {
1241fe6060f1SDimitry Andric   if (!isCsectSymbol())
1242fe6060f1SDimitry Andric     return false;
1243fe6060f1SDimitry Andric 
1244fe6060f1SDimitry Andric   if (getSymbolType() & FunctionSym)
1245fe6060f1SDimitry Andric     return true;
1246fe6060f1SDimitry Andric 
1247fe6060f1SDimitry Andric   Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
12485f757f3fSDimitry Andric   if (!ExpCsectAuxEnt)
12495f757f3fSDimitry Andric     return ExpCsectAuxEnt.takeError();
1250fe6060f1SDimitry Andric 
1251fe6060f1SDimitry Andric   const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
1252fe6060f1SDimitry Andric 
12535f757f3fSDimitry Andric   if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR &&
12545f757f3fSDimitry Andric       CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_GL)
1255fe6060f1SDimitry Andric     return false;
1256fe6060f1SDimitry Andric 
12575f757f3fSDimitry Andric   // A function definition should not be a common type symbol or an external
12585f757f3fSDimitry Andric   // symbol.
12595f757f3fSDimitry Andric   if (CsectAuxRef.getSymbolType() == XCOFF::XTY_CM ||
12605f757f3fSDimitry Andric       CsectAuxRef.getSymbolType() == XCOFF::XTY_ER)
1261fe6060f1SDimitry Andric     return false;
1262fe6060f1SDimitry Andric 
12635f757f3fSDimitry Andric   // If the next symbol is an XTY_LD type symbol with the same address, this
12645f757f3fSDimitry Andric   // XTY_SD symbol is not a function. Otherwise this is a function symbol for
12655f757f3fSDimitry Andric   // -ffunction-sections.
12665f757f3fSDimitry Andric   if (CsectAuxRef.getSymbolType() == XCOFF::XTY_SD) {
12675f757f3fSDimitry Andric     // If this is a csect with size 0, it won't be a function definition.
12685f757f3fSDimitry Andric     // This is used to work around the fact that LLVM always generates below
12695f757f3fSDimitry Andric     // symbol for -ffunction-sections:
12705f757f3fSDimitry Andric     // m   0x00000000     .text     1  unamex                    **No Symbol**
12715f757f3fSDimitry Andric     // a4  0x00000000       0    0     SD       PR    0    0
12725f757f3fSDimitry Andric     // FIXME: remove or replace this meaningless symbol.
12735f757f3fSDimitry Andric     if (getSize() == 0)
1274fe6060f1SDimitry Andric       return false;
12755f757f3fSDimitry Andric 
12765f757f3fSDimitry Andric     xcoff_symbol_iterator NextIt(this);
12775f757f3fSDimitry Andric     // If this is the last main symbol table entry, there won't be an XTY_LD
12785f757f3fSDimitry Andric     // type symbol below.
12795f757f3fSDimitry Andric     if (++NextIt == getObject()->symbol_end())
12805f757f3fSDimitry Andric       return true;
12815f757f3fSDimitry Andric 
12825f757f3fSDimitry Andric     if (cantFail(getAddress()) != cantFail(NextIt->getAddress()))
12835f757f3fSDimitry Andric       return true;
12845f757f3fSDimitry Andric 
12855f757f3fSDimitry Andric     // Check next symbol is XTY_LD. If so, this symbol is not a function.
12865f757f3fSDimitry Andric     Expected<XCOFFCsectAuxRef> NextCsectAuxEnt = NextIt->getXCOFFCsectAuxRef();
12875f757f3fSDimitry Andric     if (!NextCsectAuxEnt)
12885f757f3fSDimitry Andric       return NextCsectAuxEnt.takeError();
12895f757f3fSDimitry Andric 
12905f757f3fSDimitry Andric     if (NextCsectAuxEnt.get().getSymbolType() == XCOFF::XTY_LD)
12915f757f3fSDimitry Andric       return false;
12925f757f3fSDimitry Andric 
12935f757f3fSDimitry Andric     return true;
12948bcb0991SDimitry Andric   }
12958bcb0991SDimitry Andric 
12965f757f3fSDimitry Andric   if (CsectAuxRef.getSymbolType() == XCOFF::XTY_LD)
12975f757f3fSDimitry Andric     return true;
12985f757f3fSDimitry Andric 
12995f757f3fSDimitry Andric   return createError(
13005f757f3fSDimitry Andric       "symbol csect aux entry with index " +
13015f757f3fSDimitry Andric       Twine(getObject()->getSymbolIndex(CsectAuxRef.getEntryAddress())) +
13025f757f3fSDimitry Andric       " has invalid symbol type " +
13035f757f3fSDimitry Andric       Twine::utohexstr(CsectAuxRef.getSymbolType()));
13048bcb0991SDimitry Andric }
13058bcb0991SDimitry Andric 
1306fe6060f1SDimitry Andric bool XCOFFSymbolRef::isCsectSymbol() const {
13078bcb0991SDimitry Andric   XCOFF::StorageClass SC = getStorageClass();
13088bcb0991SDimitry Andric   return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
13098bcb0991SDimitry Andric           SC == XCOFF::C_HIDEXT);
13108bcb0991SDimitry Andric }
13118bcb0991SDimitry Andric 
1312fe6060f1SDimitry Andric Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
1313fe6060f1SDimitry Andric   assert(isCsectSymbol() &&
1314fe6060f1SDimitry Andric          "Calling csect symbol interface with a non-csect symbol.");
13158bcb0991SDimitry Andric 
1316fe6060f1SDimitry Andric   uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
13178bcb0991SDimitry Andric 
1318fe6060f1SDimitry Andric   Expected<StringRef> NameOrErr = getName();
1319fe6060f1SDimitry Andric   if (auto Err = NameOrErr.takeError())
1320fe6060f1SDimitry Andric     return std::move(Err);
13218bcb0991SDimitry Andric 
13225f757f3fSDimitry Andric   uint32_t SymbolIdx = getObject()->getSymbolIndex(getEntryAddress());
1323fe6060f1SDimitry Andric   if (!NumberOfAuxEntries) {
1324349cc55cSDimitry Andric     return createError("csect symbol \"" + *NameOrErr + "\" with index " +
1325349cc55cSDimitry Andric                        Twine(SymbolIdx) + " contains no auxiliary entry");
1326fe6060f1SDimitry Andric   }
13278bcb0991SDimitry Andric 
13285f757f3fSDimitry Andric   if (!getObject()->is64Bit()) {
1329fe6060f1SDimitry Andric     // In XCOFF32, the csect auxilliary entry is always the last auxiliary
1330fe6060f1SDimitry Andric     // entry for the symbol.
1331fe6060f1SDimitry Andric     uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1332fe6060f1SDimitry Andric         getEntryAddress(), NumberOfAuxEntries);
1333fe6060f1SDimitry Andric     return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
1334fe6060f1SDimitry Andric   }
13358bcb0991SDimitry Andric 
1336fe6060f1SDimitry Andric   // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
1337fe6060f1SDimitry Andric   // We need to iterate through all the auxiliary entries to find it.
1338fe6060f1SDimitry Andric   for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
1339fe6060f1SDimitry Andric     uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1340fe6060f1SDimitry Andric         getEntryAddress(), Index);
13415f757f3fSDimitry Andric     if (*getObject()->getSymbolAuxType(AuxAddr) ==
1342fe6060f1SDimitry Andric         XCOFF::SymbolAuxType::AUX_CSECT) {
1343fe6060f1SDimitry Andric #ifndef NDEBUG
13445f757f3fSDimitry Andric       getObject()->checkSymbolEntryPointer(AuxAddr);
1345fe6060f1SDimitry Andric #endif
1346fe6060f1SDimitry Andric       return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
1347fe6060f1SDimitry Andric     }
1348fe6060f1SDimitry Andric   }
13498bcb0991SDimitry Andric 
1350349cc55cSDimitry Andric   return createError(
1351349cc55cSDimitry Andric       "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr +
1352349cc55cSDimitry Andric       "\" with index " + Twine(SymbolIdx));
1353fe6060f1SDimitry Andric }
13548bcb0991SDimitry Andric 
1355fe6060f1SDimitry Andric Expected<StringRef> XCOFFSymbolRef::getName() const {
1356fe6060f1SDimitry Andric   // A storage class value with the high-order bit on indicates that the name is
1357fe6060f1SDimitry Andric   // a symbolic debugger stabstring.
1358fe6060f1SDimitry Andric   if (getStorageClass() & 0x80)
1359fe6060f1SDimitry Andric     return StringRef("Unimplemented Debug Name");
1360fe6060f1SDimitry Andric 
13615f757f3fSDimitry Andric   if (!getObject()->is64Bit()) {
13625f757f3fSDimitry Andric     if (getSymbol32()->NameInStrTbl.Magic !=
13635f757f3fSDimitry Andric         XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
13645f757f3fSDimitry Andric       return generateXCOFFFixedNameStringRef(getSymbol32()->SymbolName);
1365fe6060f1SDimitry Andric 
13665f757f3fSDimitry Andric     return getObject()->getStringTableEntry(getSymbol32()->NameInStrTbl.Offset);
1367fe6060f1SDimitry Andric   }
1368fe6060f1SDimitry Andric 
13695f757f3fSDimitry Andric   return getObject()->getStringTableEntry(getSymbol64()->Offset);
13700b57cec5SDimitry Andric }
13710b57cec5SDimitry Andric 
1372*0fca6ea1SDimitry Andric // Explicitly instantiate template classes.
1373480093f4SDimitry Andric template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
1374480093f4SDimitry Andric template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
1375480093f4SDimitry Andric 
1376349cc55cSDimitry Andric template struct XCOFFRelocation<llvm::support::ubig32_t>;
1377349cc55cSDimitry Andric template struct XCOFFRelocation<llvm::support::ubig64_t>;
1378349cc55cSDimitry Andric 
1379349cc55cSDimitry Andric template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>>
1380349cc55cSDimitry Andric llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64,
1381349cc55cSDimitry Andric                                            llvm::object::XCOFFRelocation64>(
1382349cc55cSDimitry Andric     llvm::object::XCOFFSectionHeader64 const &) const;
1383349cc55cSDimitry Andric template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>>
1384349cc55cSDimitry Andric llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32,
1385349cc55cSDimitry Andric                                            llvm::object::XCOFFRelocation32>(
1386349cc55cSDimitry Andric     llvm::object::XCOFFSectionHeader32 const &) const;
1387349cc55cSDimitry Andric 
1388e8d8bef9SDimitry Andric bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
1389e8d8bef9SDimitry Andric   if (Bytes.size() < 4)
1390e8d8bef9SDimitry Andric     return false;
1391e8d8bef9SDimitry Andric 
1392e8d8bef9SDimitry Andric   return support::endian::read32be(Bytes.data()) == 0;
1393e8d8bef9SDimitry Andric }
1394e8d8bef9SDimitry Andric 
1395e8d8bef9SDimitry Andric #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
1396e8d8bef9SDimitry Andric #define GETVALUEWITHMASKSHIFT(X, S)                                            \
1397e8d8bef9SDimitry Andric   ((Data & (TracebackTable::X)) >> (TracebackTable::S))
1398fe6060f1SDimitry Andric 
1399fe6060f1SDimitry Andric Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) {
1400fe6060f1SDimitry Andric   Error Err = Error::success();
1401fe6060f1SDimitry Andric   TBVectorExt TBTVecExt(TBvectorStrRef, Err);
1402fe6060f1SDimitry Andric   if (Err)
1403fe6060f1SDimitry Andric     return std::move(Err);
1404fe6060f1SDimitry Andric   return TBTVecExt;
1405fe6060f1SDimitry Andric }
1406fe6060f1SDimitry Andric 
1407fe6060f1SDimitry Andric TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) {
1408fe6060f1SDimitry Andric   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
1409fe6060f1SDimitry Andric   Data = support::endian::read16be(Ptr);
1410fe6060f1SDimitry Andric   uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
1411fe6060f1SDimitry Andric   unsigned ParmsNum =
1412fe6060f1SDimitry Andric       GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);
1413fe6060f1SDimitry Andric 
1414fe6060f1SDimitry Andric   ErrorAsOutParameter EAO(&Err);
1415fe6060f1SDimitry Andric   Expected<SmallString<32>> VecParmsTypeOrError =
1416fe6060f1SDimitry Andric       parseVectorParmsType(VecParmsTypeValue, ParmsNum);
1417fe6060f1SDimitry Andric   if (!VecParmsTypeOrError)
1418fe6060f1SDimitry Andric     Err = VecParmsTypeOrError.takeError();
1419fe6060f1SDimitry Andric   else
1420fe6060f1SDimitry Andric     VecParmsInfo = VecParmsTypeOrError.get();
1421fe6060f1SDimitry Andric }
1422fe6060f1SDimitry Andric 
1423e8d8bef9SDimitry Andric uint8_t TBVectorExt::getNumberOfVRSaved() const {
1424e8d8bef9SDimitry Andric   return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
1425e8d8bef9SDimitry Andric }
1426e8d8bef9SDimitry Andric 
1427e8d8bef9SDimitry Andric bool TBVectorExt::isVRSavedOnStack() const {
1428e8d8bef9SDimitry Andric   return GETVALUEWITHMASK(IsVRSavedOnStackMask);
1429e8d8bef9SDimitry Andric }
1430e8d8bef9SDimitry Andric 
1431e8d8bef9SDimitry Andric bool TBVectorExt::hasVarArgs() const {
1432e8d8bef9SDimitry Andric   return GETVALUEWITHMASK(HasVarArgsMask);
1433e8d8bef9SDimitry Andric }
1434fe6060f1SDimitry Andric 
1435e8d8bef9SDimitry Andric uint8_t TBVectorExt::getNumberOfVectorParms() const {
1436e8d8bef9SDimitry Andric   return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
1437e8d8bef9SDimitry Andric                                NumberOfVectorParmsShift);
1438e8d8bef9SDimitry Andric }
1439e8d8bef9SDimitry Andric 
1440e8d8bef9SDimitry Andric bool TBVectorExt::hasVMXInstruction() const {
1441e8d8bef9SDimitry Andric   return GETVALUEWITHMASK(HasVMXInstructionMask);
1442e8d8bef9SDimitry Andric }
1443e8d8bef9SDimitry Andric #undef GETVALUEWITHMASK
1444e8d8bef9SDimitry Andric #undef GETVALUEWITHMASKSHIFT
1445e8d8bef9SDimitry Andric 
144606c3fb27SDimitry Andric Expected<XCOFFTracebackTable>
144706c3fb27SDimitry Andric XCOFFTracebackTable::create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bit) {
1448e8d8bef9SDimitry Andric   Error Err = Error::success();
144906c3fb27SDimitry Andric   XCOFFTracebackTable TBT(Ptr, Size, Err, Is64Bit);
1450e8d8bef9SDimitry Andric   if (Err)
1451e8d8bef9SDimitry Andric     return std::move(Err);
1452e8d8bef9SDimitry Andric   return TBT;
1453e8d8bef9SDimitry Andric }
1454e8d8bef9SDimitry Andric 
1455e8d8bef9SDimitry Andric XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
145606c3fb27SDimitry Andric                                          Error &Err, bool Is64Bit)
145706c3fb27SDimitry Andric     : TBPtr(Ptr), Is64BitObj(Is64Bit) {
1458e8d8bef9SDimitry Andric   ErrorAsOutParameter EAO(&Err);
1459e8d8bef9SDimitry Andric   DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
1460e8d8bef9SDimitry Andric                    /*AddressSize=*/0);
1461e8d8bef9SDimitry Andric   DataExtractor::Cursor Cur(/*Offset=*/0);
1462e8d8bef9SDimitry Andric 
1463e8d8bef9SDimitry Andric   // Skip 8 bytes of mandatory fields.
1464e8d8bef9SDimitry Andric   DE.getU64(Cur);
1465e8d8bef9SDimitry Andric 
1466fe6060f1SDimitry Andric   unsigned FixedParmsNum = getNumberOfFixedParms();
1467fe6060f1SDimitry Andric   unsigned FloatingParmsNum = getNumberOfFPParms();
1468fe6060f1SDimitry Andric   uint32_t ParamsTypeValue = 0;
1469e8d8bef9SDimitry Andric 
1470fe6060f1SDimitry Andric   // Begin to parse optional fields.
1471fe6060f1SDimitry Andric   if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
1472fe6060f1SDimitry Andric     ParamsTypeValue = DE.getU32(Cur);
1473e8d8bef9SDimitry Andric 
1474e8d8bef9SDimitry Andric   if (Cur && hasTraceBackTableOffset())
1475e8d8bef9SDimitry Andric     TraceBackTableOffset = DE.getU32(Cur);
1476e8d8bef9SDimitry Andric 
1477e8d8bef9SDimitry Andric   if (Cur && isInterruptHandler())
1478e8d8bef9SDimitry Andric     HandlerMask = DE.getU32(Cur);
1479e8d8bef9SDimitry Andric 
1480e8d8bef9SDimitry Andric   if (Cur && hasControlledStorage()) {
1481e8d8bef9SDimitry Andric     NumOfCtlAnchors = DE.getU32(Cur);
1482e8d8bef9SDimitry Andric     if (Cur && NumOfCtlAnchors) {
1483e8d8bef9SDimitry Andric       SmallVector<uint32_t, 8> Disp;
148481ad6265SDimitry Andric       Disp.reserve(*NumOfCtlAnchors);
1485e8d8bef9SDimitry Andric       for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
1486e8d8bef9SDimitry Andric         Disp.push_back(DE.getU32(Cur));
1487e8d8bef9SDimitry Andric       if (Cur)
1488e8d8bef9SDimitry Andric         ControlledStorageInfoDisp = std::move(Disp);
1489e8d8bef9SDimitry Andric     }
1490e8d8bef9SDimitry Andric   }
1491e8d8bef9SDimitry Andric 
1492e8d8bef9SDimitry Andric   if (Cur && isFuncNamePresent()) {
1493e8d8bef9SDimitry Andric     uint16_t FunctionNameLen = DE.getU16(Cur);
1494e8d8bef9SDimitry Andric     if (Cur)
1495e8d8bef9SDimitry Andric       FunctionName = DE.getBytes(Cur, FunctionNameLen);
1496e8d8bef9SDimitry Andric   }
1497e8d8bef9SDimitry Andric 
1498e8d8bef9SDimitry Andric   if (Cur && isAllocaUsed())
1499e8d8bef9SDimitry Andric     AllocaRegister = DE.getU8(Cur);
1500e8d8bef9SDimitry Andric 
1501fe6060f1SDimitry Andric   unsigned VectorParmsNum = 0;
1502e8d8bef9SDimitry Andric   if (Cur && hasVectorInfo()) {
1503e8d8bef9SDimitry Andric     StringRef VectorExtRef = DE.getBytes(Cur, 6);
1504fe6060f1SDimitry Andric     if (Cur) {
1505fe6060f1SDimitry Andric       Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
1506fe6060f1SDimitry Andric       if (!TBVecExtOrErr) {
1507fe6060f1SDimitry Andric         Err = TBVecExtOrErr.takeError();
1508fe6060f1SDimitry Andric         return;
1509fe6060f1SDimitry Andric       }
1510fe6060f1SDimitry Andric       VecExt = TBVecExtOrErr.get();
151181ad6265SDimitry Andric       VectorParmsNum = VecExt->getNumberOfVectorParms();
151206c3fb27SDimitry Andric       // Skip two bytes of padding after vector info.
151306c3fb27SDimitry Andric       DE.skip(Cur, 2);
1514fe6060f1SDimitry Andric     }
1515fe6060f1SDimitry Andric   }
1516fe6060f1SDimitry Andric 
1517fe6060f1SDimitry Andric   // As long as there is no fixed-point or floating-point parameter, this
1518fe6060f1SDimitry Andric   // field remains not present even when hasVectorInfo gives true and
1519fe6060f1SDimitry Andric   // indicates the presence of vector parameters.
1520fe6060f1SDimitry Andric   if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
1521fe6060f1SDimitry Andric     Expected<SmallString<32>> ParmsTypeOrError =
1522fe6060f1SDimitry Andric         hasVectorInfo()
1523fe6060f1SDimitry Andric             ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
1524fe6060f1SDimitry Andric                                         FloatingParmsNum, VectorParmsNum)
1525fe6060f1SDimitry Andric             : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);
1526fe6060f1SDimitry Andric 
1527fe6060f1SDimitry Andric     if (!ParmsTypeOrError) {
1528fe6060f1SDimitry Andric       Err = ParmsTypeOrError.takeError();
1529fe6060f1SDimitry Andric       return;
1530fe6060f1SDimitry Andric     }
1531fe6060f1SDimitry Andric     ParmsType = ParmsTypeOrError.get();
1532e8d8bef9SDimitry Andric   }
1533e8d8bef9SDimitry Andric 
153406c3fb27SDimitry Andric   if (Cur && hasExtensionTable()) {
1535e8d8bef9SDimitry Andric     ExtensionTable = DE.getU8(Cur);
1536e8d8bef9SDimitry Andric 
153706c3fb27SDimitry Andric     if (*ExtensionTable & ExtendedTBTableFlag::TB_EH_INFO) {
153806c3fb27SDimitry Andric       // eh_info displacement must be 4-byte aligned.
153906c3fb27SDimitry Andric       Cur.seek(alignTo(Cur.tell(), 4));
154006c3fb27SDimitry Andric       EhInfoDisp = Is64BitObj ? DE.getU64(Cur) : DE.getU32(Cur);
154106c3fb27SDimitry Andric     }
154206c3fb27SDimitry Andric   }
1543e8d8bef9SDimitry Andric   if (!Cur)
1544e8d8bef9SDimitry Andric     Err = Cur.takeError();
1545fe6060f1SDimitry Andric 
1546e8d8bef9SDimitry Andric   Size = Cur.tell();
1547e8d8bef9SDimitry Andric }
1548e8d8bef9SDimitry Andric 
1549e8d8bef9SDimitry Andric #define GETBITWITHMASK(P, X)                                                   \
1550e8d8bef9SDimitry Andric   (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
1551e8d8bef9SDimitry Andric #define GETBITWITHMASKSHIFT(P, X, S)                                           \
1552e8d8bef9SDimitry Andric   ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >>           \
1553e8d8bef9SDimitry Andric    (TracebackTable::S))
1554e8d8bef9SDimitry Andric 
1555e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getVersion() const {
1556e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
1557e8d8bef9SDimitry Andric }
1558e8d8bef9SDimitry Andric 
1559e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getLanguageID() const {
1560e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
1561e8d8bef9SDimitry Andric }
1562e8d8bef9SDimitry Andric 
1563e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isGlobalLinkage() const {
1564e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsGlobaLinkageMask);
1565e8d8bef9SDimitry Andric }
1566e8d8bef9SDimitry Andric 
1567e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
1568e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
1569e8d8bef9SDimitry Andric }
1570e8d8bef9SDimitry Andric 
1571e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
1572e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
1573e8d8bef9SDimitry Andric }
1574e8d8bef9SDimitry Andric 
1575e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isInternalProcedure() const {
1576e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsInternalProcedureMask);
1577e8d8bef9SDimitry Andric }
1578e8d8bef9SDimitry Andric 
1579e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasControlledStorage() const {
1580e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, HasControlledStorageMask);
1581e8d8bef9SDimitry Andric }
1582e8d8bef9SDimitry Andric 
1583e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isTOCless() const {
1584e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsTOClessMask);
1585e8d8bef9SDimitry Andric }
1586e8d8bef9SDimitry Andric 
1587e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFloatingPointPresent() const {
1588e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsFloatingPointPresentMask);
1589e8d8bef9SDimitry Andric }
1590e8d8bef9SDimitry Andric 
1591e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
1592e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
1593e8d8bef9SDimitry Andric }
1594e8d8bef9SDimitry Andric 
1595e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isInterruptHandler() const {
1596e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsInterruptHandlerMask);
1597e8d8bef9SDimitry Andric }
1598e8d8bef9SDimitry Andric 
1599e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFuncNamePresent() const {
1600e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsFunctionNamePresentMask);
1601e8d8bef9SDimitry Andric }
1602e8d8bef9SDimitry Andric 
1603e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isAllocaUsed() const {
1604e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsAllocaUsedMask);
1605e8d8bef9SDimitry Andric }
1606e8d8bef9SDimitry Andric 
1607e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
1608e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
1609e8d8bef9SDimitry Andric                              OnConditionDirectiveShift);
1610e8d8bef9SDimitry Andric }
1611e8d8bef9SDimitry Andric 
1612e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isCRSaved() const {
1613e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsCRSavedMask);
1614e8d8bef9SDimitry Andric }
1615e8d8bef9SDimitry Andric 
1616e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isLRSaved() const {
1617e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsLRSavedMask);
1618e8d8bef9SDimitry Andric }
1619e8d8bef9SDimitry Andric 
1620e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isBackChainStored() const {
1621e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, IsBackChainStoredMask);
1622e8d8bef9SDimitry Andric }
1623e8d8bef9SDimitry Andric 
1624e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFixup() const {
1625e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, IsFixupMask);
1626e8d8bef9SDimitry Andric }
1627e8d8bef9SDimitry Andric 
1628e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
1629e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
1630e8d8bef9SDimitry Andric }
1631e8d8bef9SDimitry Andric 
1632e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasExtensionTable() const {
1633e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, HasExtensionTableMask);
1634e8d8bef9SDimitry Andric }
1635e8d8bef9SDimitry Andric 
1636e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasVectorInfo() const {
1637e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, HasVectorInfoMask);
1638e8d8bef9SDimitry Andric }
1639e8d8bef9SDimitry Andric 
1640e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
1641e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
1642e8d8bef9SDimitry Andric }
1643e8d8bef9SDimitry Andric 
1644e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
1645e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
1646e8d8bef9SDimitry Andric                              NumberOfFixedParmsShift);
1647e8d8bef9SDimitry Andric }
1648e8d8bef9SDimitry Andric 
1649e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
1650e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
1651e8d8bef9SDimitry Andric                              NumberOfFloatingPointParmsShift);
1652e8d8bef9SDimitry Andric }
1653e8d8bef9SDimitry Andric 
1654e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasParmsOnStack() const {
1655e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, HasParmsOnStackMask);
1656e8d8bef9SDimitry Andric }
1657e8d8bef9SDimitry Andric 
1658e8d8bef9SDimitry Andric #undef GETBITWITHMASK
1659e8d8bef9SDimitry Andric #undef GETBITWITHMASKSHIFT
16600b57cec5SDimitry Andric } // namespace object
16610b57cec5SDimitry Andric } // namespace llvm
1662