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"
16fe013be4SDimitry 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>
getObject(MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (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 
getWithOffset(uintptr_t Base,ptrdiff_t Offset)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 
viewAs(uintptr_t in)460b57cec5SDimitry Andric template <typename T> static const T *viewAs(uintptr_t in) {
470b57cec5SDimitry Andric   return reinterpret_cast<const T *>(in);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
generateXCOFFFixedNameStringRef(const char * Name)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 
getName() const57480093f4SDimitry 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 
getSectionType() const62480093f4SDimitry 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>
isReservedSectionType() const68480093f4SDimitry Andric bool XCOFFSectionHeader<T>::isReservedSectionType() const {
69480093f4SDimitry Andric   return getSectionType() & SectionFlagsReservedMask;
70480093f4SDimitry Andric }
71480093f4SDimitry Andric 
72349cc55cSDimitry Andric template <typename AddressType>
isRelocationSigned() const73349cc55cSDimitry Andric bool XCOFFRelocation<AddressType>::isRelocationSigned() const {
748bcb0991SDimitry Andric   return Info & XR_SIGN_INDICATOR_MASK;
758bcb0991SDimitry Andric }
768bcb0991SDimitry Andric 
77349cc55cSDimitry Andric template <typename AddressType>
isFixupIndicated() const78349cc55cSDimitry Andric bool XCOFFRelocation<AddressType>::isFixupIndicated() const {
798bcb0991SDimitry Andric   return Info & XR_FIXUP_INDICATOR_MASK;
808bcb0991SDimitry Andric }
818bcb0991SDimitry Andric 
82349cc55cSDimitry Andric template <typename AddressType>
getRelocatedLength() const83349cc55cSDimitry Andric uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
848bcb0991SDimitry Andric   // The relocation encodes the bit length being relocated minus 1. Add back
858bcb0991SDimitry Andric   // the 1 to get the actual length being relocated.
868bcb0991SDimitry Andric   return (Info & XR_BIASED_LENGTH_MASK) + 1;
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
89bdd1243dSDimitry Andric template struct ExceptionSectionEntry<support::ubig32_t>;
90bdd1243dSDimitry Andric template struct ExceptionSectionEntry<support::ubig64_t>;
91bdd1243dSDimitry Andric 
92bdd1243dSDimitry Andric template <typename T>
getLoaderSecSymNameInStrTbl(const T * LoaderSecHeader,uint64_t Offset)93bdd1243dSDimitry Andric Expected<StringRef> getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader,
94bdd1243dSDimitry Andric                                                 uint64_t Offset) {
95bdd1243dSDimitry Andric   if (LoaderSecHeader->LengthOfStrTbl > Offset)
96bdd1243dSDimitry Andric     return (reinterpret_cast<const char *>(LoaderSecHeader) +
97bdd1243dSDimitry Andric             LoaderSecHeader->OffsetToStrTbl + Offset);
98bdd1243dSDimitry Andric 
99bdd1243dSDimitry Andric   return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
100bdd1243dSDimitry Andric                      " in the loader section's string table with size 0x" +
101bdd1243dSDimitry Andric                      Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) +
102bdd1243dSDimitry Andric                      " is invalid");
103bdd1243dSDimitry Andric }
104bdd1243dSDimitry Andric 
getSymbolName(const LoaderSectionHeader32 * LoaderSecHeader32) const105bdd1243dSDimitry Andric Expected<StringRef> LoaderSectionSymbolEntry32::getSymbolName(
106bdd1243dSDimitry Andric     const LoaderSectionHeader32 *LoaderSecHeader32) const {
107bdd1243dSDimitry Andric   const NameOffsetInStrTbl *NameInStrTbl =
108bdd1243dSDimitry Andric       reinterpret_cast<const NameOffsetInStrTbl *>(SymbolName);
109bdd1243dSDimitry Andric   if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
110bdd1243dSDimitry Andric     return generateXCOFFFixedNameStringRef(SymbolName);
111bdd1243dSDimitry Andric 
112bdd1243dSDimitry Andric   return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset);
113bdd1243dSDimitry Andric }
114bdd1243dSDimitry Andric 
getSymbolName(const LoaderSectionHeader64 * LoaderSecHeader64) const115bdd1243dSDimitry Andric Expected<StringRef> LoaderSectionSymbolEntry64::getSymbolName(
116bdd1243dSDimitry Andric     const LoaderSectionHeader64 *LoaderSecHeader64) const {
117bdd1243dSDimitry Andric   return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset);
118bdd1243dSDimitry Andric }
119bdd1243dSDimitry Andric 
120fe6060f1SDimitry Andric uintptr_t
getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,uint32_t Distance)121fe6060f1SDimitry Andric XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
122fe6060f1SDimitry Andric                                                uint32_t Distance) {
123fe6060f1SDimitry Andric   return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
124fe6060f1SDimitry Andric }
125fe6060f1SDimitry Andric 
126fe6060f1SDimitry Andric const XCOFF::SymbolAuxType *
getSymbolAuxType(uintptr_t AuxEntryAddress) const127fe6060f1SDimitry Andric XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
128fe6060f1SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
129fe6060f1SDimitry Andric   return viewAs<XCOFF::SymbolAuxType>(
130fe6060f1SDimitry Andric       getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
131fe6060f1SDimitry Andric }
132fe6060f1SDimitry Andric 
checkSectionAddress(uintptr_t Addr,uintptr_t TableAddress) const1330b57cec5SDimitry Andric void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
1340b57cec5SDimitry Andric                                           uintptr_t TableAddress) const {
1350b57cec5SDimitry Andric   if (Addr < TableAddress)
1360b57cec5SDimitry Andric     report_fatal_error("Section header outside of section header table.");
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   uintptr_t Offset = Addr - TableAddress;
1390b57cec5SDimitry Andric   if (Offset >= getSectionHeaderSize() * getNumberOfSections())
1400b57cec5SDimitry Andric     report_fatal_error("Section header outside of section header table.");
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   if (Offset % getSectionHeaderSize() != 0)
1430b57cec5SDimitry Andric     report_fatal_error(
1440b57cec5SDimitry Andric         "Section header pointer does not point to a valid section header.");
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric const XCOFFSectionHeader32 *
toSection32(DataRefImpl Ref) const1480b57cec5SDimitry Andric XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
1490b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
1500b57cec5SDimitry Andric #ifndef NDEBUG
1510b57cec5SDimitry Andric   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
1520b57cec5SDimitry Andric #endif
1530b57cec5SDimitry Andric   return viewAs<XCOFFSectionHeader32>(Ref.p);
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric const XCOFFSectionHeader64 *
toSection64(DataRefImpl Ref) const1570b57cec5SDimitry Andric XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
1580b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
1590b57cec5SDimitry Andric #ifndef NDEBUG
1600b57cec5SDimitry Andric   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
1610b57cec5SDimitry Andric #endif
1620b57cec5SDimitry Andric   return viewAs<XCOFFSectionHeader64>(Ref.p);
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
toSymbolRef(DataRefImpl Ref) const165fe6060f1SDimitry Andric XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
1660b57cec5SDimitry Andric   assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
1678bcb0991SDimitry Andric #ifndef NDEBUG
1688bcb0991SDimitry Andric   checkSymbolEntryPointer(Ref.p);
1698bcb0991SDimitry Andric #endif
170fe6060f1SDimitry Andric   return XCOFFSymbolRef(Ref, this);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
fileHeader32() const1730b57cec5SDimitry Andric const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
1740b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
1750b57cec5SDimitry Andric   return static_cast<const XCOFFFileHeader32 *>(FileHeader);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
fileHeader64() const1780b57cec5SDimitry Andric const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
1790b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
1800b57cec5SDimitry Andric   return static_cast<const XCOFFFileHeader64 *>(FileHeader);
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
auxiliaryHeader32() const183349cc55cSDimitry Andric const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
184349cc55cSDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
185349cc55cSDimitry Andric   return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
186349cc55cSDimitry Andric }
187349cc55cSDimitry Andric 
auxiliaryHeader64() const188349cc55cSDimitry Andric const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
189349cc55cSDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
190349cc55cSDimitry Andric   return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
191349cc55cSDimitry Andric }
192349cc55cSDimitry Andric 
sectionHeaderTable() const193349cc55cSDimitry Andric template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
194349cc55cSDimitry Andric   return static_cast<const T *>(SectionHeaderTable);
195349cc55cSDimitry Andric }
196349cc55cSDimitry Andric 
1970b57cec5SDimitry Andric const XCOFFSectionHeader32 *
sectionHeaderTable32() const1980b57cec5SDimitry Andric XCOFFObjectFile::sectionHeaderTable32() const {
1990b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
2000b57cec5SDimitry Andric   return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric const XCOFFSectionHeader64 *
sectionHeaderTable64() const2040b57cec5SDimitry Andric XCOFFObjectFile::sectionHeaderTable64() const {
2050b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
2060b57cec5SDimitry Andric   return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
moveSymbolNext(DataRefImpl & Symb) const2090b57cec5SDimitry Andric void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
210fe6060f1SDimitry Andric   uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
211fe6060f1SDimitry Andric       Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
2128bcb0991SDimitry Andric #ifndef NDEBUG
2138bcb0991SDimitry Andric   // This function is used by basic_symbol_iterator, which allows to
2148bcb0991SDimitry Andric   // point to the end-of-symbol-table address.
215fe6060f1SDimitry Andric   if (NextSymbolAddr != getEndOfSymbolTableAddress())
216fe6060f1SDimitry Andric     checkSymbolEntryPointer(NextSymbolAddr);
2178bcb0991SDimitry Andric #endif
218fe6060f1SDimitry Andric   Symb.p = NextSymbolAddr;
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
2218bcb0991SDimitry Andric Expected<StringRef>
getStringTableEntry(uint32_t Offset) const2228bcb0991SDimitry Andric XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
2238bcb0991SDimitry Andric   // The byte offset is relative to the start of the string table.
2248bcb0991SDimitry Andric   // A byte offset value of 0 is a null or zero-length symbol
2250b57cec5SDimitry Andric   // name. A byte offset in the range 1 to 3 (inclusive) points into the length
2260b57cec5SDimitry Andric   // field; as a soft-error recovery mechanism, we treat such cases as having an
2270b57cec5SDimitry Andric   // offset of 0.
2280b57cec5SDimitry Andric   if (Offset < 4)
2290b57cec5SDimitry Andric     return StringRef(nullptr, 0);
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   if (StringTable.Data != nullptr && StringTable.Size > Offset)
2320b57cec5SDimitry Andric     return (StringTable.Data + Offset);
2330b57cec5SDimitry Andric 
234349cc55cSDimitry Andric   return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
235349cc55cSDimitry Andric                      " in a string table with size 0x" +
236349cc55cSDimitry Andric                      Twine::utohexstr(StringTable.Size) + " is invalid");
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
getStringTable() const239fe6060f1SDimitry Andric StringRef XCOFFObjectFile::getStringTable() const {
240349cc55cSDimitry Andric   // If the size is less than or equal to 4, then the string table contains no
241349cc55cSDimitry Andric   // string data.
242349cc55cSDimitry Andric   return StringRef(StringTable.Data,
243349cc55cSDimitry Andric                    StringTable.Size <= 4 ? 0 : StringTable.Size);
244fe6060f1SDimitry Andric }
245fe6060f1SDimitry Andric 
2468bcb0991SDimitry Andric Expected<StringRef>
getCFileName(const XCOFFFileAuxEnt * CFileEntPtr) const2478bcb0991SDimitry Andric XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
248fe6060f1SDimitry Andric   if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
2498bcb0991SDimitry Andric     return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
2508bcb0991SDimitry Andric   return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
2518bcb0991SDimitry Andric }
2528bcb0991SDimitry Andric 
getSymbolName(DataRefImpl Symb) const2538bcb0991SDimitry Andric Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
254fe6060f1SDimitry Andric   return toSymbolRef(Symb).getName();
2558bcb0991SDimitry Andric }
2568bcb0991SDimitry Andric 
getSymbolAddress(DataRefImpl Symb) const2570b57cec5SDimitry Andric Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
258fe6060f1SDimitry Andric   return toSymbolRef(Symb).getValue();
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
getSymbolValueImpl(DataRefImpl Symb) const2610b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
262fe6060f1SDimitry Andric   return toSymbolRef(Symb).getValue();
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
getSymbolAlignment(DataRefImpl Symb) const265349cc55cSDimitry Andric uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
266349cc55cSDimitry Andric   uint64_t Result = 0;
267349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
268349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
269349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
270349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
271349cc55cSDimitry Andric     if (!CsectAuxRefOrError)
272349cc55cSDimitry Andric       // TODO: report the error up the stack.
273349cc55cSDimitry Andric       consumeError(CsectAuxRefOrError.takeError());
274349cc55cSDimitry Andric     else
275349cc55cSDimitry Andric       Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2();
276349cc55cSDimitry Andric   }
277349cc55cSDimitry Andric   return Result;
278349cc55cSDimitry Andric }
279349cc55cSDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Symb) const2800b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
2810b57cec5SDimitry Andric   uint64_t Result = 0;
282349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
283349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
284349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
285349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
286349cc55cSDimitry Andric     if (!CsectAuxRefOrError)
287349cc55cSDimitry Andric       // TODO: report the error up the stack.
288349cc55cSDimitry Andric       consumeError(CsectAuxRefOrError.takeError());
289349cc55cSDimitry Andric     else {
290349cc55cSDimitry Andric       XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
291349cc55cSDimitry Andric       assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM);
292349cc55cSDimitry Andric       Result = CsectAuxRef.getSectionOrLength();
293349cc55cSDimitry Andric     }
294349cc55cSDimitry Andric   }
2950b57cec5SDimitry Andric   return Result;
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const2990b57cec5SDimitry Andric XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
300349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
301349cc55cSDimitry Andric 
302*c9157d92SDimitry Andric   Expected<bool> IsFunction = XCOFFSym.isFunction();
303*c9157d92SDimitry Andric   if (!IsFunction)
304*c9157d92SDimitry Andric     return IsFunction.takeError();
305*c9157d92SDimitry Andric 
306*c9157d92SDimitry Andric   if (*IsFunction)
307349cc55cSDimitry Andric     return SymbolRef::ST_Function;
308349cc55cSDimitry Andric 
309349cc55cSDimitry Andric   if (XCOFF::C_FILE == XCOFFSym.getStorageClass())
310349cc55cSDimitry Andric     return SymbolRef::ST_File;
311349cc55cSDimitry Andric 
312349cc55cSDimitry Andric   int16_t SecNum = XCOFFSym.getSectionNumber();
313349cc55cSDimitry Andric   if (SecNum <= 0)
314349cc55cSDimitry Andric     return SymbolRef::ST_Other;
315349cc55cSDimitry Andric 
316349cc55cSDimitry Andric   Expected<DataRefImpl> SecDRIOrErr =
317349cc55cSDimitry Andric       getSectionByNum(XCOFFSym.getSectionNumber());
318349cc55cSDimitry Andric 
319349cc55cSDimitry Andric   if (!SecDRIOrErr)
320349cc55cSDimitry Andric     return SecDRIOrErr.takeError();
321349cc55cSDimitry Andric 
322349cc55cSDimitry Andric   DataRefImpl SecDRI = SecDRIOrErr.get();
323349cc55cSDimitry Andric 
324349cc55cSDimitry Andric   Expected<StringRef> SymNameOrError = XCOFFSym.getName();
325349cc55cSDimitry Andric   if (SymNameOrError) {
326349cc55cSDimitry Andric     // The "TOC" symbol is treated as SymbolRef::ST_Other.
327349cc55cSDimitry Andric     if (SymNameOrError.get() == "TOC")
328349cc55cSDimitry Andric       return SymbolRef::ST_Other;
329349cc55cSDimitry Andric 
330349cc55cSDimitry Andric     // The symbol for a section name is treated as SymbolRef::ST_Other.
331349cc55cSDimitry Andric     StringRef SecName;
332349cc55cSDimitry Andric     if (is64Bit())
333349cc55cSDimitry Andric       SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName();
334349cc55cSDimitry Andric     else
335349cc55cSDimitry Andric       SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName();
336349cc55cSDimitry Andric 
337349cc55cSDimitry Andric     if (SecName == SymNameOrError.get())
338349cc55cSDimitry Andric       return SymbolRef::ST_Other;
339349cc55cSDimitry Andric   } else
340349cc55cSDimitry Andric     return SymNameOrError.takeError();
341349cc55cSDimitry Andric 
342349cc55cSDimitry Andric   if (isSectionData(SecDRI) || isSectionBSS(SecDRI))
343349cc55cSDimitry Andric     return SymbolRef::ST_Data;
344349cc55cSDimitry Andric 
345349cc55cSDimitry Andric   if (isDebugSection(SecDRI))
346349cc55cSDimitry Andric     return SymbolRef::ST_Debug;
347349cc55cSDimitry Andric 
3480b57cec5SDimitry Andric   return SymbolRef::ST_Other;
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const3520b57cec5SDimitry Andric XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
353fe6060f1SDimitry Andric   const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   if (isReservedSectionNumber(SectNum))
3560b57cec5SDimitry Andric     return section_end();
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
3590b57cec5SDimitry Andric   if (!ExpSec)
3600b57cec5SDimitry Andric     return ExpSec.takeError();
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   return section_iterator(SectionRef(ExpSec.get(), this));
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
moveSectionNext(DataRefImpl & Sec) const3650b57cec5SDimitry Andric void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
3660b57cec5SDimitry Andric   const char *Ptr = reinterpret_cast<const char *>(Sec.p);
3670b57cec5SDimitry Andric   Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
getSectionName(DataRefImpl Sec) const3700b57cec5SDimitry Andric Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
3718bcb0991SDimitry Andric   return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
getSectionAddress(DataRefImpl Sec) const3740b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
3750b57cec5SDimitry Andric   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
3760b57cec5SDimitry Andric   // with MSVC.
3770b57cec5SDimitry Andric   if (is64Bit())
3780b57cec5SDimitry Andric     return toSection64(Sec)->VirtualAddress;
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   return toSection32(Sec)->VirtualAddress;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
getSectionIndex(DataRefImpl Sec) const3830b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
3840b57cec5SDimitry Andric   // Section numbers in XCOFF are numbered beginning at 1. A section number of
3850b57cec5SDimitry Andric   // zero is used to indicate that a symbol is being imported or is undefined.
3860b57cec5SDimitry Andric   if (is64Bit())
3870b57cec5SDimitry Andric     return toSection64(Sec) - sectionHeaderTable64() + 1;
3880b57cec5SDimitry Andric   else
3890b57cec5SDimitry Andric     return toSection32(Sec) - sectionHeaderTable32() + 1;
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric 
getSectionSize(DataRefImpl Sec) const3920b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
3930b57cec5SDimitry Andric   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
3940b57cec5SDimitry Andric   // with MSVC.
3950b57cec5SDimitry Andric   if (is64Bit())
3960b57cec5SDimitry Andric     return toSection64(Sec)->SectionSize;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   return toSection32(Sec)->SectionSize;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const4020b57cec5SDimitry Andric XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
403480093f4SDimitry Andric   if (isSectionVirtual(Sec))
404480093f4SDimitry Andric     return ArrayRef<uint8_t>();
405480093f4SDimitry Andric 
406480093f4SDimitry Andric   uint64_t OffsetToRaw;
407480093f4SDimitry Andric   if (is64Bit())
408480093f4SDimitry Andric     OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
409480093f4SDimitry Andric   else
410480093f4SDimitry Andric     OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
411480093f4SDimitry Andric 
412480093f4SDimitry Andric   const uint8_t * ContentStart = base() + OffsetToRaw;
413480093f4SDimitry Andric   uint64_t SectionSize = getSectionSize(Sec);
414349cc55cSDimitry Andric   if (Error E = Binary::checkOffset(
415349cc55cSDimitry Andric           Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
416349cc55cSDimitry Andric     return createError(
417349cc55cSDimitry Andric         toString(std::move(E)) + ": section data with offset 0x" +
418349cc55cSDimitry Andric         Twine::utohexstr(OffsetToRaw) + " and size 0x" +
419349cc55cSDimitry Andric         Twine::utohexstr(SectionSize) + " goes past the end of the file");
420480093f4SDimitry Andric 
421bdd1243dSDimitry Andric   return ArrayRef(ContentStart, SectionSize);
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
getSectionAlignment(DataRefImpl Sec) const4240b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
4250b57cec5SDimitry Andric   uint64_t Result = 0;
4260b57cec5SDimitry Andric   llvm_unreachable("Not yet implemented!");
4270b57cec5SDimitry Andric   return Result;
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
getSectionFileOffsetToRawData(DataRefImpl Sec) const430bdd1243dSDimitry Andric uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const {
431bdd1243dSDimitry Andric   if (is64Bit())
432bdd1243dSDimitry Andric     return toSection64(Sec)->FileOffsetToRawData;
433349cc55cSDimitry Andric 
434bdd1243dSDimitry Andric   return toSection32(Sec)->FileOffsetToRawData;
435349cc55cSDimitry Andric }
436349cc55cSDimitry Andric 
getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const437bdd1243dSDimitry Andric Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData(
438bdd1243dSDimitry Andric     XCOFF::SectionTypeFlags SectType) const {
439bdd1243dSDimitry Andric   DataRefImpl DRI = getSectionByType(SectType);
440bdd1243dSDimitry Andric 
441bdd1243dSDimitry Andric   if (DRI.p == 0) // No section is not an error.
442349cc55cSDimitry Andric     return 0;
443349cc55cSDimitry Andric 
444bdd1243dSDimitry Andric   uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI);
445bdd1243dSDimitry Andric   uint64_t SizeOfSection = getSectionSize(DRI);
446349cc55cSDimitry Andric 
447bdd1243dSDimitry Andric   uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset);
448bdd1243dSDimitry Andric   if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) {
449bdd1243dSDimitry Andric     SmallString<32> UnknownType;
450bdd1243dSDimitry Andric     Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">")
451bdd1243dSDimitry Andric         .toVector(UnknownType);
452bdd1243dSDimitry Andric     const char *SectionName = UnknownType.c_str();
453bdd1243dSDimitry Andric 
454bdd1243dSDimitry Andric     switch (SectType) {
455bdd1243dSDimitry Andric #define ECASE(Value, String)                                                   \
456bdd1243dSDimitry Andric   case XCOFF::Value:                                                           \
457bdd1243dSDimitry Andric     SectionName = String;                                                      \
458bdd1243dSDimitry Andric     break
459bdd1243dSDimitry Andric 
460bdd1243dSDimitry Andric       ECASE(STYP_PAD, "pad");
461bdd1243dSDimitry Andric       ECASE(STYP_DWARF, "dwarf");
462bdd1243dSDimitry Andric       ECASE(STYP_TEXT, "text");
463bdd1243dSDimitry Andric       ECASE(STYP_DATA, "data");
464bdd1243dSDimitry Andric       ECASE(STYP_BSS, "bss");
465bdd1243dSDimitry Andric       ECASE(STYP_EXCEPT, "expect");
466bdd1243dSDimitry Andric       ECASE(STYP_INFO, "info");
467bdd1243dSDimitry Andric       ECASE(STYP_TDATA, "tdata");
468bdd1243dSDimitry Andric       ECASE(STYP_TBSS, "tbss");
469bdd1243dSDimitry Andric       ECASE(STYP_LOADER, "loader");
470bdd1243dSDimitry Andric       ECASE(STYP_DEBUG, "debug");
471bdd1243dSDimitry Andric       ECASE(STYP_TYPCHK, "typchk");
472bdd1243dSDimitry Andric       ECASE(STYP_OVRFLO, "ovrflo");
473bdd1243dSDimitry Andric #undef ECASE
474bdd1243dSDimitry Andric     }
475bdd1243dSDimitry Andric     return createError(toString(std::move(E)) + ": " + SectionName +
476bdd1243dSDimitry Andric                        " section with offset 0x" +
477bdd1243dSDimitry Andric                        Twine::utohexstr(SectionOffset) + " and size 0x" +
478bdd1243dSDimitry Andric                        Twine::utohexstr(SizeOfSection) +
479bdd1243dSDimitry Andric                        " goes past the end of the file");
480bdd1243dSDimitry Andric   }
481bdd1243dSDimitry Andric   return SectionStart;
482349cc55cSDimitry Andric }
483349cc55cSDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const4840b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
485fe6060f1SDimitry Andric   return false;
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric 
isSectionText(DataRefImpl Sec) const4880b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
4890b57cec5SDimitry Andric   return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric 
isSectionData(DataRefImpl Sec) const4920b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
4930b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(Sec);
4940b57cec5SDimitry Andric   return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric 
isSectionBSS(DataRefImpl Sec) const4970b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
4980b57cec5SDimitry Andric   uint32_t Flags = getSectionFlags(Sec);
4990b57cec5SDimitry Andric   return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
5000b57cec5SDimitry Andric }
5010b57cec5SDimitry Andric 
isDebugSection(DataRefImpl Sec) const502fe6060f1SDimitry Andric bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const {
503fe6060f1SDimitry Andric   uint32_t Flags = getSectionFlags(Sec);
504fe6060f1SDimitry Andric   return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF);
505fe6060f1SDimitry Andric }
506fe6060f1SDimitry Andric 
isSectionVirtual(DataRefImpl Sec) const5070b57cec5SDimitry Andric bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
508480093f4SDimitry Andric   return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
509480093f4SDimitry Andric                    : toSection32(Sec)->FileOffsetToRawData == 0;
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric 
section_rel_begin(DataRefImpl Sec) const5120b57cec5SDimitry Andric relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
5135ffd83dbSDimitry Andric   DataRefImpl Ret;
514349cc55cSDimitry Andric   if (is64Bit()) {
515349cc55cSDimitry Andric     const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
516349cc55cSDimitry Andric     auto RelocationsOrErr =
517349cc55cSDimitry Andric         relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
518349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
519349cc55cSDimitry Andric       // TODO: report the error up the stack.
520349cc55cSDimitry Andric       consumeError(std::move(E));
521349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
522349cc55cSDimitry Andric     }
5235ffd83dbSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
524349cc55cSDimitry Andric   } else {
525349cc55cSDimitry Andric     const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
526349cc55cSDimitry Andric     auto RelocationsOrErr =
527349cc55cSDimitry Andric         relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
528349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
529349cc55cSDimitry Andric       // TODO: report the error up the stack.
530349cc55cSDimitry Andric       consumeError(std::move(E));
531349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
532349cc55cSDimitry Andric     }
533349cc55cSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
534349cc55cSDimitry Andric   }
5355ffd83dbSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
section_rel_end(DataRefImpl Sec) const5380b57cec5SDimitry Andric relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
5395ffd83dbSDimitry Andric   DataRefImpl Ret;
540349cc55cSDimitry Andric   if (is64Bit()) {
541349cc55cSDimitry Andric     const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
542349cc55cSDimitry Andric     auto RelocationsOrErr =
543349cc55cSDimitry Andric         relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
544349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
545349cc55cSDimitry Andric       // TODO: report the error up the stack.
546349cc55cSDimitry Andric       consumeError(std::move(E));
547349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
548349cc55cSDimitry Andric     }
5495ffd83dbSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
550349cc55cSDimitry Andric   } else {
551349cc55cSDimitry Andric     const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
552349cc55cSDimitry Andric     auto RelocationsOrErr =
553349cc55cSDimitry Andric         relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
554349cc55cSDimitry Andric     if (Error E = RelocationsOrErr.takeError()) {
555349cc55cSDimitry Andric       // TODO: report the error up the stack.
556349cc55cSDimitry Andric       consumeError(std::move(E));
557349cc55cSDimitry Andric       return relocation_iterator(RelocationRef());
558349cc55cSDimitry Andric     }
559349cc55cSDimitry Andric     Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
560349cc55cSDimitry Andric   }
5615ffd83dbSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const5640b57cec5SDimitry Andric void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
565349cc55cSDimitry Andric   if (is64Bit())
566349cc55cSDimitry Andric     Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1);
567349cc55cSDimitry Andric   else
5685ffd83dbSDimitry Andric     Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
getRelocationOffset(DataRefImpl Rel) const5710b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
572349cc55cSDimitry Andric   if (is64Bit()) {
573349cc55cSDimitry Andric     const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
574349cc55cSDimitry Andric     const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64();
575349cc55cSDimitry Andric     const uint64_t RelocAddress = Reloc->VirtualAddress;
576349cc55cSDimitry Andric     const uint16_t NumberOfSections = getNumberOfSections();
577349cc55cSDimitry Andric     for (uint16_t I = 0; I < NumberOfSections; ++I) {
578349cc55cSDimitry Andric       // Find which section this relocation belongs to, and get the
579349cc55cSDimitry Andric       // relocation offset relative to the start of the section.
580349cc55cSDimitry Andric       if (Sec64->VirtualAddress <= RelocAddress &&
581349cc55cSDimitry Andric           RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) {
582349cc55cSDimitry Andric         return RelocAddress - Sec64->VirtualAddress;
583349cc55cSDimitry Andric       }
584349cc55cSDimitry Andric       ++Sec64;
585349cc55cSDimitry Andric     }
586349cc55cSDimitry Andric   } else {
5875ffd83dbSDimitry Andric     const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
5885ffd83dbSDimitry Andric     const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
5895ffd83dbSDimitry Andric     const uint32_t RelocAddress = Reloc->VirtualAddress;
5905ffd83dbSDimitry Andric     const uint16_t NumberOfSections = getNumberOfSections();
591349cc55cSDimitry Andric     for (uint16_t I = 0; I < NumberOfSections; ++I) {
592349cc55cSDimitry Andric       // Find which section this relocation belongs to, and get the
5935ffd83dbSDimitry Andric       // relocation offset relative to the start of the section.
5945ffd83dbSDimitry Andric       if (Sec32->VirtualAddress <= RelocAddress &&
5955ffd83dbSDimitry Andric           RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
5965ffd83dbSDimitry Andric         return RelocAddress - Sec32->VirtualAddress;
5975ffd83dbSDimitry Andric       }
5985ffd83dbSDimitry Andric       ++Sec32;
5995ffd83dbSDimitry Andric     }
600349cc55cSDimitry Andric   }
6015ffd83dbSDimitry Andric   return InvalidRelocOffset;
6020b57cec5SDimitry Andric }
6030b57cec5SDimitry Andric 
getRelocationSymbol(DataRefImpl Rel) const6040b57cec5SDimitry Andric symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
605349cc55cSDimitry Andric   uint32_t Index;
606349cc55cSDimitry Andric   if (is64Bit()) {
607349cc55cSDimitry Andric     const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
608349cc55cSDimitry Andric     Index = Reloc->SymbolIndex;
609349cc55cSDimitry Andric 
610349cc55cSDimitry Andric     if (Index >= getNumberOfSymbolTableEntries64())
611349cc55cSDimitry Andric       return symbol_end();
612349cc55cSDimitry Andric   } else {
6135ffd83dbSDimitry Andric     const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
614349cc55cSDimitry Andric     Index = Reloc->SymbolIndex;
6155ffd83dbSDimitry Andric 
6165ffd83dbSDimitry Andric     if (Index >= getLogicalNumberOfSymbolTableEntries32())
6175ffd83dbSDimitry Andric       return symbol_end();
618349cc55cSDimitry Andric   }
6195ffd83dbSDimitry Andric   DataRefImpl SymDRI;
620fe6060f1SDimitry Andric   SymDRI.p = getSymbolEntryAddressByIndex(Index);
6215ffd83dbSDimitry Andric   return symbol_iterator(SymbolRef(SymDRI, this));
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
getRelocationType(DataRefImpl Rel) const6240b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
6255ffd83dbSDimitry Andric   if (is64Bit())
626349cc55cSDimitry Andric     return viewAs<XCOFFRelocation64>(Rel.p)->Type;
6275ffd83dbSDimitry Andric   return viewAs<XCOFFRelocation32>(Rel.p)->Type;
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const6300b57cec5SDimitry Andric void XCOFFObjectFile::getRelocationTypeName(
6310b57cec5SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
632349cc55cSDimitry Andric   StringRef Res;
633349cc55cSDimitry Andric   if (is64Bit()) {
634349cc55cSDimitry Andric     const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
635349cc55cSDimitry Andric     Res = XCOFF::getRelocationTypeString(Reloc->Type);
636349cc55cSDimitry Andric   } else {
6375ffd83dbSDimitry Andric     const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
638349cc55cSDimitry Andric     Res = XCOFF::getRelocationTypeString(Reloc->Type);
639349cc55cSDimitry Andric   }
6405ffd83dbSDimitry Andric   Result.append(Res.begin(), Res.end());
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric 
getSymbolFlags(DataRefImpl Symb) const6435ffd83dbSDimitry Andric Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
644349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
645349cc55cSDimitry Andric   uint32_t Result = SymbolRef::SF_None;
646349cc55cSDimitry Andric 
647349cc55cSDimitry Andric   if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS)
648349cc55cSDimitry Andric     Result |= SymbolRef::SF_Absolute;
649349cc55cSDimitry Andric 
650349cc55cSDimitry Andric   XCOFF::StorageClass SC = XCOFFSym.getStorageClass();
651349cc55cSDimitry Andric   if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC)
652349cc55cSDimitry Andric     Result |= SymbolRef::SF_Global;
653349cc55cSDimitry Andric 
654349cc55cSDimitry Andric   if (XCOFF::C_WEAKEXT == SC)
655349cc55cSDimitry Andric     Result |= SymbolRef::SF_Weak;
656349cc55cSDimitry Andric 
657349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
658349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr =
659349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
660349cc55cSDimitry Andric     if (CsectAuxEntOrErr) {
661349cc55cSDimitry Andric       if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM)
662349cc55cSDimitry Andric         Result |= SymbolRef::SF_Common;
663349cc55cSDimitry Andric     } else
664349cc55cSDimitry Andric       return CsectAuxEntOrErr.takeError();
665349cc55cSDimitry Andric   }
666349cc55cSDimitry Andric 
667349cc55cSDimitry Andric   if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF)
668349cc55cSDimitry Andric     Result |= SymbolRef::SF_Undefined;
669349cc55cSDimitry Andric 
67081ad6265SDimitry Andric   // There is no visibility in old 32 bit XCOFF object file interpret.
67181ad6265SDimitry Andric   if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() ==
67281ad6265SDimitry Andric                                             NEW_XCOFF_INTERPRET))) {
67381ad6265SDimitry Andric     uint16_t SymType = XCOFFSym.getSymbolType();
67481ad6265SDimitry Andric     if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN)
67581ad6265SDimitry Andric       Result |= SymbolRef::SF_Hidden;
67681ad6265SDimitry Andric 
67781ad6265SDimitry Andric     if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED)
67881ad6265SDimitry Andric       Result |= SymbolRef::SF_Exported;
67981ad6265SDimitry Andric   }
6800b57cec5SDimitry Andric   return Result;
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric 
symbol_begin() const6830b57cec5SDimitry Andric basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
6840b57cec5SDimitry Andric   DataRefImpl SymDRI;
6850b57cec5SDimitry Andric   SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
6860b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(SymDRI, this));
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric 
symbol_end() const6890b57cec5SDimitry Andric basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
6900b57cec5SDimitry Andric   DataRefImpl SymDRI;
691fe6060f1SDimitry Andric   const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
692fe6060f1SDimitry Andric   SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
6930b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(SymDRI, this));
6940b57cec5SDimitry Andric }
6950b57cec5SDimitry Andric 
symbols() const696*c9157d92SDimitry Andric XCOFFObjectFile::xcoff_symbol_iterator_range XCOFFObjectFile::symbols() const {
697*c9157d92SDimitry Andric   return xcoff_symbol_iterator_range(symbol_begin(), symbol_end());
698*c9157d92SDimitry Andric }
699*c9157d92SDimitry Andric 
section_begin() const7000b57cec5SDimitry Andric section_iterator XCOFFObjectFile::section_begin() const {
7010b57cec5SDimitry Andric   DataRefImpl DRI;
7020b57cec5SDimitry Andric   DRI.p = getSectionHeaderTableAddress();
7030b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric 
section_end() const7060b57cec5SDimitry Andric section_iterator XCOFFObjectFile::section_end() const {
7070b57cec5SDimitry Andric   DataRefImpl DRI;
7080b57cec5SDimitry Andric   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
7090b57cec5SDimitry Andric                         getNumberOfSections() * getSectionHeaderSize());
7100b57cec5SDimitry Andric   return section_iterator(SectionRef(DRI, this));
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric 
getBytesInAddress() const7130b57cec5SDimitry Andric uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
7140b57cec5SDimitry Andric 
getFileFormatName() const7150b57cec5SDimitry Andric StringRef XCOFFObjectFile::getFileFormatName() const {
7160b57cec5SDimitry Andric   return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
getArch() const7190b57cec5SDimitry Andric Triple::ArchType XCOFFObjectFile::getArch() const {
7200b57cec5SDimitry Andric   return is64Bit() ? Triple::ppc64 : Triple::ppc;
7210b57cec5SDimitry Andric }
7220b57cec5SDimitry Andric 
getFeatures() const723bdd1243dSDimitry Andric Expected<SubtargetFeatures> XCOFFObjectFile::getFeatures() const {
7240b57cec5SDimitry Andric   return SubtargetFeatures();
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
isRelocatableObject() const7270b57cec5SDimitry Andric bool XCOFFObjectFile::isRelocatableObject() const {
7285ffd83dbSDimitry Andric   if (is64Bit())
729fe6060f1SDimitry Andric     return !(fileHeader64()->Flags & NoRelMask);
7305ffd83dbSDimitry Andric   return !(fileHeader32()->Flags & NoRelMask);
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric 
getStartAddress() const7330b57cec5SDimitry Andric Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
7340b57cec5SDimitry Andric   // TODO FIXME Should get from auxiliary_header->o_entry when support for the
7350b57cec5SDimitry Andric   // auxiliary_header is added.
7360b57cec5SDimitry Andric   return 0;
7370b57cec5SDimitry Andric }
7380b57cec5SDimitry Andric 
mapDebugSectionName(StringRef Name) const739fe6060f1SDimitry Andric StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
740fe6060f1SDimitry Andric   return StringSwitch<StringRef>(Name)
741fe6060f1SDimitry Andric       .Case("dwinfo", "debug_info")
742fe6060f1SDimitry Andric       .Case("dwline", "debug_line")
743fe6060f1SDimitry Andric       .Case("dwpbnms", "debug_pubnames")
744fe6060f1SDimitry Andric       .Case("dwpbtyp", "debug_pubtypes")
745fe6060f1SDimitry Andric       .Case("dwarnge", "debug_aranges")
746fe6060f1SDimitry Andric       .Case("dwabrev", "debug_abbrev")
747fe6060f1SDimitry Andric       .Case("dwstr", "debug_str")
748fe6060f1SDimitry Andric       .Case("dwrnges", "debug_ranges")
749fe6060f1SDimitry Andric       .Case("dwloc", "debug_loc")
750fe6060f1SDimitry Andric       .Case("dwframe", "debug_frame")
751fe6060f1SDimitry Andric       .Case("dwmac", "debug_macinfo")
752fe6060f1SDimitry Andric       .Default(Name);
753fe6060f1SDimitry Andric }
754fe6060f1SDimitry Andric 
getFileHeaderSize() const7550b57cec5SDimitry Andric size_t XCOFFObjectFile::getFileHeaderSize() const {
7560b57cec5SDimitry Andric   return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
7570b57cec5SDimitry Andric }
7580b57cec5SDimitry Andric 
getSectionHeaderSize() const7590b57cec5SDimitry Andric size_t XCOFFObjectFile::getSectionHeaderSize() const {
7600b57cec5SDimitry Andric   return is64Bit() ? sizeof(XCOFFSectionHeader64) :
7610b57cec5SDimitry Andric                      sizeof(XCOFFSectionHeader32);
7620b57cec5SDimitry Andric }
7630b57cec5SDimitry Andric 
is64Bit() const7640b57cec5SDimitry Andric bool XCOFFObjectFile::is64Bit() const {
7650b57cec5SDimitry Andric   return Binary::ID_XCOFF64 == getType();
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric 
getRawData(const char * Start,uint64_t Size,StringRef Name) const76881ad6265SDimitry Andric Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start,
76981ad6265SDimitry Andric                                                 uint64_t Size,
77081ad6265SDimitry Andric                                                 StringRef Name) const {
77181ad6265SDimitry Andric   uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start);
77281ad6265SDimitry Andric   // TODO: this path is untested.
77381ad6265SDimitry Andric   if (Error E = Binary::checkOffset(Data, StartPtr, Size))
77481ad6265SDimitry Andric     return createError(toString(std::move(E)) + ": " + Name.data() +
77581ad6265SDimitry Andric                        " data with offset 0x" + Twine::utohexstr(StartPtr) +
77681ad6265SDimitry Andric                        " and size 0x" + Twine::utohexstr(Size) +
77781ad6265SDimitry Andric                        " goes past the end of the file");
77881ad6265SDimitry Andric   return StringRef(Start, Size);
77981ad6265SDimitry Andric }
78081ad6265SDimitry Andric 
getMagic() const7810b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getMagic() const {
7820b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
getSectionByNum(int16_t Num) const7850b57cec5SDimitry Andric Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
7860b57cec5SDimitry Andric   if (Num <= 0 || Num > getNumberOfSections())
787349cc55cSDimitry Andric     return createStringError(object_error::invalid_section_index,
788349cc55cSDimitry Andric                              "the section index (" + Twine(Num) +
789349cc55cSDimitry Andric                                  ") is invalid");
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   DataRefImpl DRI;
7920b57cec5SDimitry Andric   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
7930b57cec5SDimitry Andric                         getSectionHeaderSize() * (Num - 1));
7940b57cec5SDimitry Andric   return DRI;
7950b57cec5SDimitry Andric }
7960b57cec5SDimitry Andric 
797bdd1243dSDimitry Andric DataRefImpl
getSectionByType(XCOFF::SectionTypeFlags SectType) const798bdd1243dSDimitry Andric XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const {
799bdd1243dSDimitry Andric   DataRefImpl DRI;
800bdd1243dSDimitry Andric   auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t {
801bdd1243dSDimitry Andric     for (const auto &Sec : Sections)
802bdd1243dSDimitry Andric       if (Sec.getSectionType() == SectType)
803bdd1243dSDimitry Andric         return reinterpret_cast<uintptr_t>(&Sec);
804bdd1243dSDimitry Andric     return uintptr_t(0);
805bdd1243dSDimitry Andric   };
806bdd1243dSDimitry Andric   if (is64Bit())
807bdd1243dSDimitry Andric     DRI.p = GetSectionAddr(sections64());
808bdd1243dSDimitry Andric   else
809bdd1243dSDimitry Andric     DRI.p = GetSectionAddr(sections32());
810bdd1243dSDimitry Andric   return DRI;
811bdd1243dSDimitry Andric }
812bdd1243dSDimitry Andric 
8130b57cec5SDimitry Andric Expected<StringRef>
getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const814fe6060f1SDimitry Andric XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
815fe6060f1SDimitry Andric   const int16_t SectionNum = SymEntPtr.getSectionNumber();
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric   switch (SectionNum) {
8180b57cec5SDimitry Andric   case XCOFF::N_DEBUG:
8190b57cec5SDimitry Andric     return "N_DEBUG";
8200b57cec5SDimitry Andric   case XCOFF::N_ABS:
8210b57cec5SDimitry Andric     return "N_ABS";
8220b57cec5SDimitry Andric   case XCOFF::N_UNDEF:
8230b57cec5SDimitry Andric     return "N_UNDEF";
8240b57cec5SDimitry Andric   default:
8250b57cec5SDimitry Andric     Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
8260b57cec5SDimitry Andric     if (SecRef)
8278bcb0991SDimitry Andric       return generateXCOFFFixedNameStringRef(
8288bcb0991SDimitry Andric           getSectionNameInternal(SecRef.get()));
8290b57cec5SDimitry Andric     return SecRef.takeError();
8300b57cec5SDimitry Andric   }
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric 
getSymbolSectionID(SymbolRef Sym) const833fe6060f1SDimitry Andric unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
834fe6060f1SDimitry Andric   XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this);
835fe6060f1SDimitry Andric   return XCOFFSymRef.getSectionNumber();
836fe6060f1SDimitry Andric }
837fe6060f1SDimitry Andric 
isReservedSectionNumber(int16_t SectionNumber)8380b57cec5SDimitry Andric bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
8390b57cec5SDimitry Andric   return (SectionNumber <= 0 && SectionNumber >= -2);
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric 
getNumberOfSections() const8420b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getNumberOfSections() const {
8430b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->NumberOfSections
8440b57cec5SDimitry Andric                    : fileHeader32()->NumberOfSections;
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
getTimeStamp() const8470b57cec5SDimitry Andric int32_t XCOFFObjectFile::getTimeStamp() const {
8480b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric 
getOptionalHeaderSize() const8510b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
8520b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->AuxHeaderSize
8530b57cec5SDimitry Andric                    : fileHeader32()->AuxHeaderSize;
8540b57cec5SDimitry Andric }
8550b57cec5SDimitry Andric 
getSymbolTableOffset32() const8560b57cec5SDimitry Andric uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
8570b57cec5SDimitry Andric   return fileHeader32()->SymbolTableOffset;
8580b57cec5SDimitry Andric }
8590b57cec5SDimitry Andric 
getRawNumberOfSymbolTableEntries32() const8600b57cec5SDimitry Andric int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
8610b57cec5SDimitry Andric   // As far as symbol table size is concerned, if this field is negative it is
8620b57cec5SDimitry Andric   // to be treated as a 0. However since this field is also used for printing we
8630b57cec5SDimitry Andric   // don't want to truncate any negative values.
8640b57cec5SDimitry Andric   return fileHeader32()->NumberOfSymTableEntries;
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric 
getLogicalNumberOfSymbolTableEntries32() const8670b57cec5SDimitry Andric uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
8680b57cec5SDimitry Andric   return (fileHeader32()->NumberOfSymTableEntries >= 0
8690b57cec5SDimitry Andric               ? fileHeader32()->NumberOfSymTableEntries
8700b57cec5SDimitry Andric               : 0);
8710b57cec5SDimitry Andric }
8720b57cec5SDimitry Andric 
getSymbolTableOffset64() const8730b57cec5SDimitry Andric uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
8740b57cec5SDimitry Andric   return fileHeader64()->SymbolTableOffset;
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
getNumberOfSymbolTableEntries64() const8770b57cec5SDimitry Andric uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
8780b57cec5SDimitry Andric   return fileHeader64()->NumberOfSymTableEntries;
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
getNumberOfSymbolTableEntries() const881fe6060f1SDimitry Andric uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
882fe6060f1SDimitry Andric   return is64Bit() ? getNumberOfSymbolTableEntries64()
8838bcb0991SDimitry Andric                    : getLogicalNumberOfSymbolTableEntries32();
884fe6060f1SDimitry Andric }
885fe6060f1SDimitry Andric 
getEndOfSymbolTableAddress() const886fe6060f1SDimitry Andric uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
887fe6060f1SDimitry Andric   const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
8888bcb0991SDimitry Andric   return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
8898bcb0991SDimitry Andric                        XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
8908bcb0991SDimitry Andric }
8918bcb0991SDimitry Andric 
checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const8928bcb0991SDimitry Andric void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
8938bcb0991SDimitry Andric   if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
8948bcb0991SDimitry Andric     report_fatal_error("Symbol table entry is outside of symbol table.");
8958bcb0991SDimitry Andric 
8968bcb0991SDimitry Andric   if (SymbolEntPtr >= getEndOfSymbolTableAddress())
8978bcb0991SDimitry Andric     report_fatal_error("Symbol table entry is outside of symbol table.");
8988bcb0991SDimitry Andric 
8998bcb0991SDimitry Andric   ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
9008bcb0991SDimitry Andric                      reinterpret_cast<const char *>(SymbolTblPtr);
9018bcb0991SDimitry Andric 
9028bcb0991SDimitry Andric   if (Offset % XCOFF::SymbolTableEntrySize != 0)
9038bcb0991SDimitry Andric     report_fatal_error(
9048bcb0991SDimitry Andric         "Symbol table entry position is not valid inside of symbol table.");
9058bcb0991SDimitry Andric }
9068bcb0991SDimitry Andric 
getSymbolIndex(uintptr_t SymbolEntPtr) const9078bcb0991SDimitry Andric uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
9088bcb0991SDimitry Andric   return (reinterpret_cast<const char *>(SymbolEntPtr) -
9098bcb0991SDimitry Andric           reinterpret_cast<const char *>(SymbolTblPtr)) /
9108bcb0991SDimitry Andric          XCOFF::SymbolTableEntrySize;
9118bcb0991SDimitry Andric }
9128bcb0991SDimitry Andric 
getSymbolSize(DataRefImpl Symb) const913349cc55cSDimitry Andric uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
914349cc55cSDimitry Andric   uint64_t Result = 0;
915349cc55cSDimitry Andric   XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
916349cc55cSDimitry Andric   if (XCOFFSym.isCsectSymbol()) {
917349cc55cSDimitry Andric     Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
918349cc55cSDimitry Andric         XCOFFSym.getXCOFFCsectAuxRef();
919349cc55cSDimitry Andric     if (!CsectAuxRefOrError)
920349cc55cSDimitry Andric       // TODO: report the error up the stack.
921349cc55cSDimitry Andric       consumeError(CsectAuxRefOrError.takeError());
922349cc55cSDimitry Andric     else {
923349cc55cSDimitry Andric       XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
924349cc55cSDimitry Andric       uint8_t SymType = CsectAuxRef.getSymbolType();
925349cc55cSDimitry Andric       if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM)
926349cc55cSDimitry Andric         Result = CsectAuxRef.getSectionOrLength();
927349cc55cSDimitry Andric     }
928349cc55cSDimitry Andric   }
929349cc55cSDimitry Andric   return Result;
930349cc55cSDimitry Andric }
931349cc55cSDimitry Andric 
getSymbolEntryAddressByIndex(uint32_t Index) const932fe6060f1SDimitry Andric uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
933fe6060f1SDimitry Andric   return getAdvancedSymbolEntryAddress(
934fe6060f1SDimitry Andric       reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
935fe6060f1SDimitry Andric }
936fe6060f1SDimitry Andric 
9378bcb0991SDimitry Andric Expected<StringRef>
getSymbolNameByIndex(uint32_t Index) const9388bcb0991SDimitry Andric XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
939fe6060f1SDimitry Andric   const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
9408bcb0991SDimitry Andric 
941fe6060f1SDimitry Andric   if (Index >= NumberOfSymTableEntries)
942349cc55cSDimitry Andric     return createError("symbol index " + Twine(Index) +
943349cc55cSDimitry Andric                        " exceeds symbol count " +
944349cc55cSDimitry Andric                        Twine(NumberOfSymTableEntries));
9458bcb0991SDimitry Andric 
9468bcb0991SDimitry Andric   DataRefImpl SymDRI;
947fe6060f1SDimitry Andric   SymDRI.p = getSymbolEntryAddressByIndex(Index);
9488bcb0991SDimitry Andric   return getSymbolName(SymDRI);
9498bcb0991SDimitry Andric }
9508bcb0991SDimitry Andric 
getFlags() const9510b57cec5SDimitry Andric uint16_t XCOFFObjectFile::getFlags() const {
9520b57cec5SDimitry Andric   return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric 
getSectionNameInternal(DataRefImpl Sec) const9550b57cec5SDimitry Andric const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
9560b57cec5SDimitry Andric   return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
9570b57cec5SDimitry Andric }
9580b57cec5SDimitry Andric 
getSectionHeaderTableAddress() const9590b57cec5SDimitry Andric uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
9600b57cec5SDimitry Andric   return reinterpret_cast<uintptr_t>(SectionHeaderTable);
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric 
getSectionFlags(DataRefImpl Sec) const9630b57cec5SDimitry Andric int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
9640b57cec5SDimitry Andric   return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric 
XCOFFObjectFile(unsigned int Type,MemoryBufferRef Object)9670b57cec5SDimitry Andric XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
9680b57cec5SDimitry Andric     : ObjectFile(Type, Object) {
9690b57cec5SDimitry Andric   assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
sections64() const9720b57cec5SDimitry Andric ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
9730b57cec5SDimitry Andric   assert(is64Bit() && "64-bit interface called for non 64-bit file.");
9740b57cec5SDimitry Andric   const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
9750b57cec5SDimitry Andric   return ArrayRef<XCOFFSectionHeader64>(TablePtr,
9760b57cec5SDimitry Andric                                         TablePtr + getNumberOfSections());
9770b57cec5SDimitry Andric }
9780b57cec5SDimitry Andric 
sections32() const9790b57cec5SDimitry Andric ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
9800b57cec5SDimitry Andric   assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
9810b57cec5SDimitry Andric   const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
9820b57cec5SDimitry Andric   return ArrayRef<XCOFFSectionHeader32>(TablePtr,
9830b57cec5SDimitry Andric                                         TablePtr + getNumberOfSections());
9840b57cec5SDimitry Andric }
9850b57cec5SDimitry Andric 
9868bcb0991SDimitry Andric // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
9878bcb0991SDimitry Andric // section header contains the actual count of relocation entries in the s_paddr
9888bcb0991SDimitry Andric // field. STYP_OVRFLO headers contain the section index of their corresponding
9898bcb0991SDimitry Andric // sections as their raw "NumberOfRelocations" field value.
990349cc55cSDimitry Andric template <typename T>
getNumberOfRelocationEntries(const XCOFFSectionHeader<T> & Sec) const991349cc55cSDimitry Andric Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries(
992349cc55cSDimitry Andric     const XCOFFSectionHeader<T> &Sec) const {
993349cc55cSDimitry Andric   const T &Section = static_cast<const T &>(Sec);
994349cc55cSDimitry Andric   if (is64Bit())
995349cc55cSDimitry Andric     return Section.NumberOfRelocations;
9968bcb0991SDimitry Andric 
997349cc55cSDimitry Andric   uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1;
998349cc55cSDimitry Andric   if (Section.NumberOfRelocations < XCOFF::RelocOverflow)
999349cc55cSDimitry Andric     return Section.NumberOfRelocations;
10008bcb0991SDimitry Andric   for (const auto &Sec : sections32()) {
10018bcb0991SDimitry Andric     if (Sec.Flags == XCOFF::STYP_OVRFLO &&
10028bcb0991SDimitry Andric         Sec.NumberOfRelocations == SectionIndex)
10038bcb0991SDimitry Andric       return Sec.PhysicalAddress;
10048bcb0991SDimitry Andric   }
10058bcb0991SDimitry Andric   return errorCodeToError(object_error::parse_failed);
10068bcb0991SDimitry Andric }
10078bcb0991SDimitry Andric 
1008349cc55cSDimitry Andric template <typename Shdr, typename Reloc>
relocations(const Shdr & Sec) const1009349cc55cSDimitry Andric Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
10108bcb0991SDimitry Andric   uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
10118bcb0991SDimitry Andric                                       Sec.FileOffsetToRelocationInfo);
1012349cc55cSDimitry Andric   auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec);
10138bcb0991SDimitry Andric   if (Error E = NumRelocEntriesOrErr.takeError())
10148bcb0991SDimitry Andric     return std::move(E);
10158bcb0991SDimitry Andric 
10168bcb0991SDimitry Andric   uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
1017349cc55cSDimitry Andric   static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 ||
1018349cc55cSDimitry Andric                  sizeof(Reloc) == XCOFF::RelocationSerializationSize32),
1019349cc55cSDimitry Andric                 "Relocation structure is incorrect");
10208bcb0991SDimitry Andric   auto RelocationOrErr =
1021349cc55cSDimitry Andric       getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
1022349cc55cSDimitry Andric                        NumRelocEntries * sizeof(Reloc));
1023349cc55cSDimitry Andric   if (!RelocationOrErr)
1024349cc55cSDimitry Andric     return createError(
1025349cc55cSDimitry Andric         toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" +
1026349cc55cSDimitry Andric         Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" +
1027349cc55cSDimitry Andric         Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) +
1028349cc55cSDimitry Andric         " go past the end of the file");
10298bcb0991SDimitry Andric 
1030349cc55cSDimitry Andric   const Reloc *StartReloc = RelocationOrErr.get();
10318bcb0991SDimitry Andric 
1032349cc55cSDimitry Andric   return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
10338bcb0991SDimitry Andric }
10348bcb0991SDimitry Andric 
1035bdd1243dSDimitry Andric template <typename ExceptEnt>
getExceptionEntries() const1036bdd1243dSDimitry Andric Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const {
1037bdd1243dSDimitry Andric   assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) ||
1038bdd1243dSDimitry Andric          (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32)));
1039bdd1243dSDimitry Andric 
1040bdd1243dSDimitry Andric   Expected<uintptr_t> ExceptionSectOrErr =
1041bdd1243dSDimitry Andric       getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT);
1042bdd1243dSDimitry Andric   if (!ExceptionSectOrErr)
1043bdd1243dSDimitry Andric     return ExceptionSectOrErr.takeError();
1044bdd1243dSDimitry Andric 
1045bdd1243dSDimitry Andric   DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT);
1046bdd1243dSDimitry Andric   if (DRI.p == 0)
1047bdd1243dSDimitry Andric     return ArrayRef<ExceptEnt>();
1048bdd1243dSDimitry Andric 
1049bdd1243dSDimitry Andric   ExceptEnt *ExceptEntStart =
1050bdd1243dSDimitry Andric       reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr);
1051bdd1243dSDimitry Andric   return ArrayRef<ExceptEnt>(
1052bdd1243dSDimitry Andric       ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt));
1053bdd1243dSDimitry Andric }
1054bdd1243dSDimitry Andric 
1055bdd1243dSDimitry Andric template Expected<ArrayRef<ExceptionSectionEntry32>>
1056bdd1243dSDimitry Andric XCOFFObjectFile::getExceptionEntries() const;
1057bdd1243dSDimitry Andric template Expected<ArrayRef<ExceptionSectionEntry64>>
1058bdd1243dSDimitry Andric XCOFFObjectFile::getExceptionEntries() const;
1059bdd1243dSDimitry Andric 
10600b57cec5SDimitry Andric Expected<XCOFFStringTable>
parseStringTable(const XCOFFObjectFile * Obj,uint64_t Offset)10610b57cec5SDimitry Andric XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
10620b57cec5SDimitry Andric   // If there is a string table, then the buffer must contain at least 4 bytes
10630b57cec5SDimitry Andric   // for the string table's size. Not having a string table is not an error.
10645ffd83dbSDimitry Andric   if (Error E = Binary::checkOffset(
10655ffd83dbSDimitry Andric           Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
10665ffd83dbSDimitry Andric     consumeError(std::move(E));
10670b57cec5SDimitry Andric     return XCOFFStringTable{0, nullptr};
10685ffd83dbSDimitry Andric   }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric   // Read the size out of the buffer.
10710b57cec5SDimitry Andric   uint32_t Size = support::endian::read32be(Obj->base() + Offset);
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   // If the size is less then 4, then the string table is just a size and no
10740b57cec5SDimitry Andric   // string data.
10750b57cec5SDimitry Andric   if (Size <= 4)
10760b57cec5SDimitry Andric     return XCOFFStringTable{4, nullptr};
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   auto StringTableOrErr =
10790b57cec5SDimitry Andric       getObject<char>(Obj->Data, Obj->base() + Offset, Size);
1080349cc55cSDimitry Andric   if (!StringTableOrErr)
1081349cc55cSDimitry Andric     return createError(toString(StringTableOrErr.takeError()) +
1082349cc55cSDimitry Andric                        ": string table with offset 0x" +
1083349cc55cSDimitry Andric                        Twine::utohexstr(Offset) + " and size 0x" +
1084349cc55cSDimitry Andric                        Twine::utohexstr(Size) +
1085349cc55cSDimitry Andric                        " goes past the end of the file");
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric   const char *StringTablePtr = StringTableOrErr.get();
10880b57cec5SDimitry Andric   if (StringTablePtr[Size - 1] != '\0')
10890b57cec5SDimitry Andric     return errorCodeToError(object_error::string_table_non_null_end);
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   return XCOFFStringTable{Size, StringTablePtr};
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric 
1094349cc55cSDimitry Andric // This function returns the import file table. Each entry in the import file
1095349cc55cSDimitry Andric // table consists of: "path_name\0base_name\0archive_member_name\0".
getImportFileTable() const1096349cc55cSDimitry Andric Expected<StringRef> XCOFFObjectFile::getImportFileTable() const {
1097bdd1243dSDimitry Andric   Expected<uintptr_t> LoaderSectionAddrOrError =
1098bdd1243dSDimitry Andric       getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
1099349cc55cSDimitry Andric   if (!LoaderSectionAddrOrError)
1100349cc55cSDimitry Andric     return LoaderSectionAddrOrError.takeError();
1101349cc55cSDimitry Andric 
1102349cc55cSDimitry Andric   uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
1103349cc55cSDimitry Andric   if (!LoaderSectionAddr)
1104349cc55cSDimitry Andric     return StringRef();
1105349cc55cSDimitry Andric 
1106349cc55cSDimitry Andric   uint64_t OffsetToImportFileTable = 0;
1107349cc55cSDimitry Andric   uint64_t LengthOfImportFileTable = 0;
1108349cc55cSDimitry Andric   if (is64Bit()) {
1109349cc55cSDimitry Andric     const LoaderSectionHeader64 *LoaderSec64 =
1110349cc55cSDimitry Andric         viewAs<LoaderSectionHeader64>(LoaderSectionAddr);
1111349cc55cSDimitry Andric     OffsetToImportFileTable = LoaderSec64->OffsetToImpid;
1112349cc55cSDimitry Andric     LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl;
1113349cc55cSDimitry Andric   } else {
1114349cc55cSDimitry Andric     const LoaderSectionHeader32 *LoaderSec32 =
1115349cc55cSDimitry Andric         viewAs<LoaderSectionHeader32>(LoaderSectionAddr);
1116349cc55cSDimitry Andric     OffsetToImportFileTable = LoaderSec32->OffsetToImpid;
1117349cc55cSDimitry Andric     LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl;
1118349cc55cSDimitry Andric   }
1119349cc55cSDimitry Andric 
1120349cc55cSDimitry Andric   auto ImportTableOrErr = getObject<char>(
1121349cc55cSDimitry Andric       Data,
1122349cc55cSDimitry Andric       reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable),
1123349cc55cSDimitry Andric       LengthOfImportFileTable);
1124349cc55cSDimitry Andric   if (!ImportTableOrErr)
1125349cc55cSDimitry Andric     return createError(
1126349cc55cSDimitry Andric         toString(ImportTableOrErr.takeError()) +
1127349cc55cSDimitry Andric         ": import file table with offset 0x" +
1128349cc55cSDimitry Andric         Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1129349cc55cSDimitry Andric         " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1130349cc55cSDimitry Andric         " goes past the end of the file");
1131349cc55cSDimitry Andric 
1132349cc55cSDimitry Andric   const char *ImportTablePtr = ImportTableOrErr.get();
1133349cc55cSDimitry Andric   if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0')
1134349cc55cSDimitry Andric     return createError(
1135349cc55cSDimitry Andric         ": import file name table with offset 0x" +
1136349cc55cSDimitry Andric         Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1137349cc55cSDimitry Andric         " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1138349cc55cSDimitry Andric         " must end with a null terminator");
1139349cc55cSDimitry Andric 
1140349cc55cSDimitry Andric   return StringRef(ImportTablePtr, LengthOfImportFileTable);
1141349cc55cSDimitry Andric }
1142349cc55cSDimitry Andric 
11430b57cec5SDimitry Andric Expected<std::unique_ptr<XCOFFObjectFile>>
create(unsigned Type,MemoryBufferRef MBR)11440b57cec5SDimitry Andric XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
11458bcb0991SDimitry Andric   // Can't use std::make_unique because of the private constructor.
11460b57cec5SDimitry Andric   std::unique_ptr<XCOFFObjectFile> Obj;
11470b57cec5SDimitry Andric   Obj.reset(new XCOFFObjectFile(Type, MBR));
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   uint64_t CurOffset = 0;
11500b57cec5SDimitry Andric   const auto *Base = Obj->base();
11510b57cec5SDimitry Andric   MemoryBufferRef Data = Obj->Data;
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric   // Parse file header.
11540b57cec5SDimitry Andric   auto FileHeaderOrErr =
11550b57cec5SDimitry Andric       getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
11560b57cec5SDimitry Andric   if (Error E = FileHeaderOrErr.takeError())
11570b57cec5SDimitry Andric     return std::move(E);
11580b57cec5SDimitry Andric   Obj->FileHeader = FileHeaderOrErr.get();
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric   CurOffset += Obj->getFileHeaderSize();
1161349cc55cSDimitry Andric 
1162349cc55cSDimitry Andric   if (Obj->getOptionalHeaderSize()) {
1163349cc55cSDimitry Andric     auto AuxiliaryHeaderOrErr =
1164349cc55cSDimitry Andric         getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize());
1165349cc55cSDimitry Andric     if (Error E = AuxiliaryHeaderOrErr.takeError())
1166349cc55cSDimitry Andric       return std::move(E);
1167349cc55cSDimitry Andric     Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get();
1168349cc55cSDimitry Andric   }
1169349cc55cSDimitry Andric 
11700b57cec5SDimitry Andric   CurOffset += Obj->getOptionalHeaderSize();
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric   // Parse the section header table if it is present.
11730b57cec5SDimitry Andric   if (Obj->getNumberOfSections()) {
1174349cc55cSDimitry Andric     uint64_t SectionHeadersSize =
1175349cc55cSDimitry Andric         Obj->getNumberOfSections() * Obj->getSectionHeaderSize();
1176349cc55cSDimitry Andric     auto SecHeadersOrErr =
1177349cc55cSDimitry Andric         getObject<void>(Data, Base + CurOffset, SectionHeadersSize);
1178349cc55cSDimitry Andric     if (!SecHeadersOrErr)
1179349cc55cSDimitry Andric       return createError(toString(SecHeadersOrErr.takeError()) +
1180349cc55cSDimitry Andric                          ": section headers with offset 0x" +
1181349cc55cSDimitry Andric                          Twine::utohexstr(CurOffset) + " and size 0x" +
1182349cc55cSDimitry Andric                          Twine::utohexstr(SectionHeadersSize) +
1183349cc55cSDimitry Andric                          " go past the end of the file");
1184349cc55cSDimitry Andric 
11850b57cec5SDimitry Andric     Obj->SectionHeaderTable = SecHeadersOrErr.get();
11860b57cec5SDimitry Andric   }
11870b57cec5SDimitry Andric 
1188fe6060f1SDimitry Andric   const uint32_t NumberOfSymbolTableEntries =
1189fe6060f1SDimitry Andric       Obj->getNumberOfSymbolTableEntries();
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric   // If there is no symbol table we are done parsing the memory buffer.
1192fe6060f1SDimitry Andric   if (NumberOfSymbolTableEntries == 0)
11930b57cec5SDimitry Andric     return std::move(Obj);
11940b57cec5SDimitry Andric 
11950b57cec5SDimitry Andric   // Parse symbol table.
1196fe6060f1SDimitry Andric   CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
1197fe6060f1SDimitry Andric                              : Obj->getSymbolTableOffset32();
1198fe6060f1SDimitry Andric   const uint64_t SymbolTableSize =
1199fe6060f1SDimitry Andric       static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
1200fe6060f1SDimitry Andric       NumberOfSymbolTableEntries;
12010b57cec5SDimitry Andric   auto SymTableOrErr =
1202fe6060f1SDimitry Andric       getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
1203349cc55cSDimitry Andric   if (!SymTableOrErr)
1204349cc55cSDimitry Andric     return createError(
1205349cc55cSDimitry Andric         toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" +
1206349cc55cSDimitry Andric         Twine::utohexstr(CurOffset) + " and size 0x" +
1207349cc55cSDimitry Andric         Twine::utohexstr(SymbolTableSize) + " goes past the end of the file");
1208349cc55cSDimitry Andric 
12090b57cec5SDimitry Andric   Obj->SymbolTblPtr = SymTableOrErr.get();
12100b57cec5SDimitry Andric   CurOffset += SymbolTableSize;
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric   // Parse String table.
12130b57cec5SDimitry Andric   Expected<XCOFFStringTable> StringTableOrErr =
12140b57cec5SDimitry Andric       parseStringTable(Obj.get(), CurOffset);
12150b57cec5SDimitry Andric   if (Error E = StringTableOrErr.takeError())
12160b57cec5SDimitry Andric     return std::move(E);
12170b57cec5SDimitry Andric   Obj->StringTable = StringTableOrErr.get();
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry Andric   return std::move(Obj);
12200b57cec5SDimitry Andric }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>>
createXCOFFObjectFile(MemoryBufferRef MemBufRef,unsigned FileType)12230b57cec5SDimitry Andric ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
12240b57cec5SDimitry Andric                                   unsigned FileType) {
12250b57cec5SDimitry Andric   return XCOFFObjectFile::create(FileType, MemBufRef);
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
tryGetCPUName() const1228fe013be4SDimitry Andric std::optional<StringRef> XCOFFObjectFile::tryGetCPUName() const {
1229fe013be4SDimitry Andric   return StringRef("future");
1230fe013be4SDimitry Andric }
1231fe013be4SDimitry Andric 
isFunction() const1232*c9157d92SDimitry Andric Expected<bool> XCOFFSymbolRef::isFunction() const {
1233fe6060f1SDimitry Andric   if (!isCsectSymbol())
1234fe6060f1SDimitry Andric     return false;
1235fe6060f1SDimitry Andric 
1236fe6060f1SDimitry Andric   if (getSymbolType() & FunctionSym)
1237fe6060f1SDimitry Andric     return true;
1238fe6060f1SDimitry Andric 
1239fe6060f1SDimitry Andric   Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
1240*c9157d92SDimitry Andric   if (!ExpCsectAuxEnt)
1241*c9157d92SDimitry Andric     return ExpCsectAuxEnt.takeError();
1242fe6060f1SDimitry Andric 
1243fe6060f1SDimitry Andric   const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
1244fe6060f1SDimitry Andric 
1245*c9157d92SDimitry Andric   if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR &&
1246*c9157d92SDimitry Andric       CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_GL)
1247fe6060f1SDimitry Andric     return false;
1248fe6060f1SDimitry Andric 
1249*c9157d92SDimitry Andric   // A function definition should not be a common type symbol or an external
1250*c9157d92SDimitry Andric   // symbol.
1251*c9157d92SDimitry Andric   if (CsectAuxRef.getSymbolType() == XCOFF::XTY_CM ||
1252*c9157d92SDimitry Andric       CsectAuxRef.getSymbolType() == XCOFF::XTY_ER)
1253fe6060f1SDimitry Andric     return false;
1254fe6060f1SDimitry Andric 
1255*c9157d92SDimitry Andric   // If the next symbol is an XTY_LD type symbol with the same address, this
1256*c9157d92SDimitry Andric   // XTY_SD symbol is not a function. Otherwise this is a function symbol for
1257*c9157d92SDimitry Andric   // -ffunction-sections.
1258*c9157d92SDimitry Andric   if (CsectAuxRef.getSymbolType() == XCOFF::XTY_SD) {
1259*c9157d92SDimitry Andric     // If this is a csect with size 0, it won't be a function definition.
1260*c9157d92SDimitry Andric     // This is used to work around the fact that LLVM always generates below
1261*c9157d92SDimitry Andric     // symbol for -ffunction-sections:
1262*c9157d92SDimitry Andric     // m   0x00000000     .text     1  unamex                    **No Symbol**
1263*c9157d92SDimitry Andric     // a4  0x00000000       0    0     SD       PR    0    0
1264*c9157d92SDimitry Andric     // FIXME: remove or replace this meaningless symbol.
1265*c9157d92SDimitry Andric     if (getSize() == 0)
1266fe6060f1SDimitry Andric       return false;
1267*c9157d92SDimitry Andric 
1268*c9157d92SDimitry Andric     xcoff_symbol_iterator NextIt(this);
1269*c9157d92SDimitry Andric     // If this is the last main symbol table entry, there won't be an XTY_LD
1270*c9157d92SDimitry Andric     // type symbol below.
1271*c9157d92SDimitry Andric     if (++NextIt == getObject()->symbol_end())
1272*c9157d92SDimitry Andric       return true;
1273*c9157d92SDimitry Andric 
1274*c9157d92SDimitry Andric     if (cantFail(getAddress()) != cantFail(NextIt->getAddress()))
1275*c9157d92SDimitry Andric       return true;
1276*c9157d92SDimitry Andric 
1277*c9157d92SDimitry Andric     // Check next symbol is XTY_LD. If so, this symbol is not a function.
1278*c9157d92SDimitry Andric     Expected<XCOFFCsectAuxRef> NextCsectAuxEnt = NextIt->getXCOFFCsectAuxRef();
1279*c9157d92SDimitry Andric     if (!NextCsectAuxEnt)
1280*c9157d92SDimitry Andric       return NextCsectAuxEnt.takeError();
1281*c9157d92SDimitry Andric 
1282*c9157d92SDimitry Andric     if (NextCsectAuxEnt.get().getSymbolType() == XCOFF::XTY_LD)
1283*c9157d92SDimitry Andric       return false;
1284*c9157d92SDimitry Andric 
1285*c9157d92SDimitry Andric     return true;
12868bcb0991SDimitry Andric   }
12878bcb0991SDimitry Andric 
1288*c9157d92SDimitry Andric   if (CsectAuxRef.getSymbolType() == XCOFF::XTY_LD)
1289*c9157d92SDimitry Andric     return true;
1290*c9157d92SDimitry Andric 
1291*c9157d92SDimitry Andric   return createError(
1292*c9157d92SDimitry Andric       "symbol csect aux entry with index " +
1293*c9157d92SDimitry Andric       Twine(getObject()->getSymbolIndex(CsectAuxRef.getEntryAddress())) +
1294*c9157d92SDimitry Andric       " has invalid symbol type " +
1295*c9157d92SDimitry Andric       Twine::utohexstr(CsectAuxRef.getSymbolType()));
12968bcb0991SDimitry Andric }
12978bcb0991SDimitry Andric 
isCsectSymbol() const1298fe6060f1SDimitry Andric bool XCOFFSymbolRef::isCsectSymbol() const {
12998bcb0991SDimitry Andric   XCOFF::StorageClass SC = getStorageClass();
13008bcb0991SDimitry Andric   return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
13018bcb0991SDimitry Andric           SC == XCOFF::C_HIDEXT);
13028bcb0991SDimitry Andric }
13038bcb0991SDimitry Andric 
getXCOFFCsectAuxRef() const1304fe6060f1SDimitry Andric Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
1305fe6060f1SDimitry Andric   assert(isCsectSymbol() &&
1306fe6060f1SDimitry Andric          "Calling csect symbol interface with a non-csect symbol.");
13078bcb0991SDimitry Andric 
1308fe6060f1SDimitry Andric   uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
13098bcb0991SDimitry Andric 
1310fe6060f1SDimitry Andric   Expected<StringRef> NameOrErr = getName();
1311fe6060f1SDimitry Andric   if (auto Err = NameOrErr.takeError())
1312fe6060f1SDimitry Andric     return std::move(Err);
13138bcb0991SDimitry Andric 
1314*c9157d92SDimitry Andric   uint32_t SymbolIdx = getObject()->getSymbolIndex(getEntryAddress());
1315fe6060f1SDimitry Andric   if (!NumberOfAuxEntries) {
1316349cc55cSDimitry Andric     return createError("csect symbol \"" + *NameOrErr + "\" with index " +
1317349cc55cSDimitry Andric                        Twine(SymbolIdx) + " contains no auxiliary entry");
1318fe6060f1SDimitry Andric   }
13198bcb0991SDimitry Andric 
1320*c9157d92SDimitry Andric   if (!getObject()->is64Bit()) {
1321fe6060f1SDimitry Andric     // In XCOFF32, the csect auxilliary entry is always the last auxiliary
1322fe6060f1SDimitry Andric     // entry for the symbol.
1323fe6060f1SDimitry Andric     uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1324fe6060f1SDimitry Andric         getEntryAddress(), NumberOfAuxEntries);
1325fe6060f1SDimitry Andric     return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
1326fe6060f1SDimitry Andric   }
13278bcb0991SDimitry Andric 
1328fe6060f1SDimitry Andric   // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
1329fe6060f1SDimitry Andric   // We need to iterate through all the auxiliary entries to find it.
1330fe6060f1SDimitry Andric   for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
1331fe6060f1SDimitry Andric     uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1332fe6060f1SDimitry Andric         getEntryAddress(), Index);
1333*c9157d92SDimitry Andric     if (*getObject()->getSymbolAuxType(AuxAddr) ==
1334fe6060f1SDimitry Andric         XCOFF::SymbolAuxType::AUX_CSECT) {
1335fe6060f1SDimitry Andric #ifndef NDEBUG
1336*c9157d92SDimitry Andric       getObject()->checkSymbolEntryPointer(AuxAddr);
1337fe6060f1SDimitry Andric #endif
1338fe6060f1SDimitry Andric       return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
1339fe6060f1SDimitry Andric     }
1340fe6060f1SDimitry Andric   }
13418bcb0991SDimitry Andric 
1342349cc55cSDimitry Andric   return createError(
1343349cc55cSDimitry Andric       "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr +
1344349cc55cSDimitry Andric       "\" with index " + Twine(SymbolIdx));
1345fe6060f1SDimitry Andric }
13468bcb0991SDimitry Andric 
getName() const1347fe6060f1SDimitry Andric Expected<StringRef> XCOFFSymbolRef::getName() const {
1348fe6060f1SDimitry Andric   // A storage class value with the high-order bit on indicates that the name is
1349fe6060f1SDimitry Andric   // a symbolic debugger stabstring.
1350fe6060f1SDimitry Andric   if (getStorageClass() & 0x80)
1351fe6060f1SDimitry Andric     return StringRef("Unimplemented Debug Name");
1352fe6060f1SDimitry Andric 
1353*c9157d92SDimitry Andric   if (!getObject()->is64Bit()) {
1354*c9157d92SDimitry Andric     if (getSymbol32()->NameInStrTbl.Magic !=
1355*c9157d92SDimitry Andric         XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
1356*c9157d92SDimitry Andric       return generateXCOFFFixedNameStringRef(getSymbol32()->SymbolName);
1357fe6060f1SDimitry Andric 
1358*c9157d92SDimitry Andric     return getObject()->getStringTableEntry(getSymbol32()->NameInStrTbl.Offset);
1359fe6060f1SDimitry Andric   }
1360fe6060f1SDimitry Andric 
1361*c9157d92SDimitry Andric   return getObject()->getStringTableEntry(getSymbol64()->Offset);
13620b57cec5SDimitry Andric }
13630b57cec5SDimitry Andric 
1364480093f4SDimitry Andric // Explictly instantiate template classes.
1365480093f4SDimitry Andric template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
1366480093f4SDimitry Andric template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
1367480093f4SDimitry Andric 
1368349cc55cSDimitry Andric template struct XCOFFRelocation<llvm::support::ubig32_t>;
1369349cc55cSDimitry Andric template struct XCOFFRelocation<llvm::support::ubig64_t>;
1370349cc55cSDimitry Andric 
1371349cc55cSDimitry Andric template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>>
1372349cc55cSDimitry Andric llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64,
1373349cc55cSDimitry Andric                                            llvm::object::XCOFFRelocation64>(
1374349cc55cSDimitry Andric     llvm::object::XCOFFSectionHeader64 const &) const;
1375349cc55cSDimitry Andric template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>>
1376349cc55cSDimitry Andric llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32,
1377349cc55cSDimitry Andric                                            llvm::object::XCOFFRelocation32>(
1378349cc55cSDimitry Andric     llvm::object::XCOFFSectionHeader32 const &) const;
1379349cc55cSDimitry Andric 
doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes)1380e8d8bef9SDimitry Andric bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
1381e8d8bef9SDimitry Andric   if (Bytes.size() < 4)
1382e8d8bef9SDimitry Andric     return false;
1383e8d8bef9SDimitry Andric 
1384e8d8bef9SDimitry Andric   return support::endian::read32be(Bytes.data()) == 0;
1385e8d8bef9SDimitry Andric }
1386e8d8bef9SDimitry Andric 
1387e8d8bef9SDimitry Andric #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
1388e8d8bef9SDimitry Andric #define GETVALUEWITHMASKSHIFT(X, S)                                            \
1389e8d8bef9SDimitry Andric   ((Data & (TracebackTable::X)) >> (TracebackTable::S))
1390fe6060f1SDimitry Andric 
create(StringRef TBvectorStrRef)1391fe6060f1SDimitry Andric Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) {
1392fe6060f1SDimitry Andric   Error Err = Error::success();
1393fe6060f1SDimitry Andric   TBVectorExt TBTVecExt(TBvectorStrRef, Err);
1394fe6060f1SDimitry Andric   if (Err)
1395fe6060f1SDimitry Andric     return std::move(Err);
1396fe6060f1SDimitry Andric   return TBTVecExt;
1397fe6060f1SDimitry Andric }
1398fe6060f1SDimitry Andric 
TBVectorExt(StringRef TBvectorStrRef,Error & Err)1399fe6060f1SDimitry Andric TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) {
1400fe6060f1SDimitry Andric   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
1401fe6060f1SDimitry Andric   Data = support::endian::read16be(Ptr);
1402fe6060f1SDimitry Andric   uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
1403fe6060f1SDimitry Andric   unsigned ParmsNum =
1404fe6060f1SDimitry Andric       GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);
1405fe6060f1SDimitry Andric 
1406fe6060f1SDimitry Andric   ErrorAsOutParameter EAO(&Err);
1407fe6060f1SDimitry Andric   Expected<SmallString<32>> VecParmsTypeOrError =
1408fe6060f1SDimitry Andric       parseVectorParmsType(VecParmsTypeValue, ParmsNum);
1409fe6060f1SDimitry Andric   if (!VecParmsTypeOrError)
1410fe6060f1SDimitry Andric     Err = VecParmsTypeOrError.takeError();
1411fe6060f1SDimitry Andric   else
1412fe6060f1SDimitry Andric     VecParmsInfo = VecParmsTypeOrError.get();
1413fe6060f1SDimitry Andric }
1414fe6060f1SDimitry Andric 
getNumberOfVRSaved() const1415e8d8bef9SDimitry Andric uint8_t TBVectorExt::getNumberOfVRSaved() const {
1416e8d8bef9SDimitry Andric   return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
1417e8d8bef9SDimitry Andric }
1418e8d8bef9SDimitry Andric 
isVRSavedOnStack() const1419e8d8bef9SDimitry Andric bool TBVectorExt::isVRSavedOnStack() const {
1420e8d8bef9SDimitry Andric   return GETVALUEWITHMASK(IsVRSavedOnStackMask);
1421e8d8bef9SDimitry Andric }
1422e8d8bef9SDimitry Andric 
hasVarArgs() const1423e8d8bef9SDimitry Andric bool TBVectorExt::hasVarArgs() const {
1424e8d8bef9SDimitry Andric   return GETVALUEWITHMASK(HasVarArgsMask);
1425e8d8bef9SDimitry Andric }
1426fe6060f1SDimitry Andric 
getNumberOfVectorParms() const1427e8d8bef9SDimitry Andric uint8_t TBVectorExt::getNumberOfVectorParms() const {
1428e8d8bef9SDimitry Andric   return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
1429e8d8bef9SDimitry Andric                                NumberOfVectorParmsShift);
1430e8d8bef9SDimitry Andric }
1431e8d8bef9SDimitry Andric 
hasVMXInstruction() const1432e8d8bef9SDimitry Andric bool TBVectorExt::hasVMXInstruction() const {
1433e8d8bef9SDimitry Andric   return GETVALUEWITHMASK(HasVMXInstructionMask);
1434e8d8bef9SDimitry Andric }
1435e8d8bef9SDimitry Andric #undef GETVALUEWITHMASK
1436e8d8bef9SDimitry Andric #undef GETVALUEWITHMASKSHIFT
1437e8d8bef9SDimitry Andric 
1438fe013be4SDimitry Andric Expected<XCOFFTracebackTable>
create(const uint8_t * Ptr,uint64_t & Size,bool Is64Bit)1439fe013be4SDimitry Andric XCOFFTracebackTable::create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bit) {
1440e8d8bef9SDimitry Andric   Error Err = Error::success();
1441fe013be4SDimitry Andric   XCOFFTracebackTable TBT(Ptr, Size, Err, Is64Bit);
1442e8d8bef9SDimitry Andric   if (Err)
1443e8d8bef9SDimitry Andric     return std::move(Err);
1444e8d8bef9SDimitry Andric   return TBT;
1445e8d8bef9SDimitry Andric }
1446e8d8bef9SDimitry Andric 
XCOFFTracebackTable(const uint8_t * Ptr,uint64_t & Size,Error & Err,bool Is64Bit)1447e8d8bef9SDimitry Andric XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
1448fe013be4SDimitry Andric                                          Error &Err, bool Is64Bit)
1449fe013be4SDimitry Andric     : TBPtr(Ptr), Is64BitObj(Is64Bit) {
1450e8d8bef9SDimitry Andric   ErrorAsOutParameter EAO(&Err);
1451e8d8bef9SDimitry Andric   DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
1452e8d8bef9SDimitry Andric                    /*AddressSize=*/0);
1453e8d8bef9SDimitry Andric   DataExtractor::Cursor Cur(/*Offset=*/0);
1454e8d8bef9SDimitry Andric 
1455e8d8bef9SDimitry Andric   // Skip 8 bytes of mandatory fields.
1456e8d8bef9SDimitry Andric   DE.getU64(Cur);
1457e8d8bef9SDimitry Andric 
1458fe6060f1SDimitry Andric   unsigned FixedParmsNum = getNumberOfFixedParms();
1459fe6060f1SDimitry Andric   unsigned FloatingParmsNum = getNumberOfFPParms();
1460fe6060f1SDimitry Andric   uint32_t ParamsTypeValue = 0;
1461e8d8bef9SDimitry Andric 
1462fe6060f1SDimitry Andric   // Begin to parse optional fields.
1463fe6060f1SDimitry Andric   if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
1464fe6060f1SDimitry Andric     ParamsTypeValue = DE.getU32(Cur);
1465e8d8bef9SDimitry Andric 
1466e8d8bef9SDimitry Andric   if (Cur && hasTraceBackTableOffset())
1467e8d8bef9SDimitry Andric     TraceBackTableOffset = DE.getU32(Cur);
1468e8d8bef9SDimitry Andric 
1469e8d8bef9SDimitry Andric   if (Cur && isInterruptHandler())
1470e8d8bef9SDimitry Andric     HandlerMask = DE.getU32(Cur);
1471e8d8bef9SDimitry Andric 
1472e8d8bef9SDimitry Andric   if (Cur && hasControlledStorage()) {
1473e8d8bef9SDimitry Andric     NumOfCtlAnchors = DE.getU32(Cur);
1474e8d8bef9SDimitry Andric     if (Cur && NumOfCtlAnchors) {
1475e8d8bef9SDimitry Andric       SmallVector<uint32_t, 8> Disp;
147681ad6265SDimitry Andric       Disp.reserve(*NumOfCtlAnchors);
1477e8d8bef9SDimitry Andric       for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
1478e8d8bef9SDimitry Andric         Disp.push_back(DE.getU32(Cur));
1479e8d8bef9SDimitry Andric       if (Cur)
1480e8d8bef9SDimitry Andric         ControlledStorageInfoDisp = std::move(Disp);
1481e8d8bef9SDimitry Andric     }
1482e8d8bef9SDimitry Andric   }
1483e8d8bef9SDimitry Andric 
1484e8d8bef9SDimitry Andric   if (Cur && isFuncNamePresent()) {
1485e8d8bef9SDimitry Andric     uint16_t FunctionNameLen = DE.getU16(Cur);
1486e8d8bef9SDimitry Andric     if (Cur)
1487e8d8bef9SDimitry Andric       FunctionName = DE.getBytes(Cur, FunctionNameLen);
1488e8d8bef9SDimitry Andric   }
1489e8d8bef9SDimitry Andric 
1490e8d8bef9SDimitry Andric   if (Cur && isAllocaUsed())
1491e8d8bef9SDimitry Andric     AllocaRegister = DE.getU8(Cur);
1492e8d8bef9SDimitry Andric 
1493fe6060f1SDimitry Andric   unsigned VectorParmsNum = 0;
1494e8d8bef9SDimitry Andric   if (Cur && hasVectorInfo()) {
1495e8d8bef9SDimitry Andric     StringRef VectorExtRef = DE.getBytes(Cur, 6);
1496fe6060f1SDimitry Andric     if (Cur) {
1497fe6060f1SDimitry Andric       Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
1498fe6060f1SDimitry Andric       if (!TBVecExtOrErr) {
1499fe6060f1SDimitry Andric         Err = TBVecExtOrErr.takeError();
1500fe6060f1SDimitry Andric         return;
1501fe6060f1SDimitry Andric       }
1502fe6060f1SDimitry Andric       VecExt = TBVecExtOrErr.get();
150381ad6265SDimitry Andric       VectorParmsNum = VecExt->getNumberOfVectorParms();
1504fe013be4SDimitry Andric       // Skip two bytes of padding after vector info.
1505fe013be4SDimitry Andric       DE.skip(Cur, 2);
1506fe6060f1SDimitry Andric     }
1507fe6060f1SDimitry Andric   }
1508fe6060f1SDimitry Andric 
1509fe6060f1SDimitry Andric   // As long as there is no fixed-point or floating-point parameter, this
1510fe6060f1SDimitry Andric   // field remains not present even when hasVectorInfo gives true and
1511fe6060f1SDimitry Andric   // indicates the presence of vector parameters.
1512fe6060f1SDimitry Andric   if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
1513fe6060f1SDimitry Andric     Expected<SmallString<32>> ParmsTypeOrError =
1514fe6060f1SDimitry Andric         hasVectorInfo()
1515fe6060f1SDimitry Andric             ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
1516fe6060f1SDimitry Andric                                         FloatingParmsNum, VectorParmsNum)
1517fe6060f1SDimitry Andric             : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);
1518fe6060f1SDimitry Andric 
1519fe6060f1SDimitry Andric     if (!ParmsTypeOrError) {
1520fe6060f1SDimitry Andric       Err = ParmsTypeOrError.takeError();
1521fe6060f1SDimitry Andric       return;
1522fe6060f1SDimitry Andric     }
1523fe6060f1SDimitry Andric     ParmsType = ParmsTypeOrError.get();
1524e8d8bef9SDimitry Andric   }
1525e8d8bef9SDimitry Andric 
1526fe013be4SDimitry Andric   if (Cur && hasExtensionTable()) {
1527e8d8bef9SDimitry Andric     ExtensionTable = DE.getU8(Cur);
1528e8d8bef9SDimitry Andric 
1529fe013be4SDimitry Andric     if (*ExtensionTable & ExtendedTBTableFlag::TB_EH_INFO) {
1530fe013be4SDimitry Andric       // eh_info displacement must be 4-byte aligned.
1531fe013be4SDimitry Andric       Cur.seek(alignTo(Cur.tell(), 4));
1532fe013be4SDimitry Andric       EhInfoDisp = Is64BitObj ? DE.getU64(Cur) : DE.getU32(Cur);
1533fe013be4SDimitry Andric     }
1534fe013be4SDimitry Andric   }
1535e8d8bef9SDimitry Andric   if (!Cur)
1536e8d8bef9SDimitry Andric     Err = Cur.takeError();
1537fe6060f1SDimitry Andric 
1538e8d8bef9SDimitry Andric   Size = Cur.tell();
1539e8d8bef9SDimitry Andric }
1540e8d8bef9SDimitry Andric 
1541e8d8bef9SDimitry Andric #define GETBITWITHMASK(P, X)                                                   \
1542e8d8bef9SDimitry Andric   (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
1543e8d8bef9SDimitry Andric #define GETBITWITHMASKSHIFT(P, X, S)                                           \
1544e8d8bef9SDimitry Andric   ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >>           \
1545e8d8bef9SDimitry Andric    (TracebackTable::S))
1546e8d8bef9SDimitry Andric 
getVersion() const1547e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getVersion() const {
1548e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
1549e8d8bef9SDimitry Andric }
1550e8d8bef9SDimitry Andric 
getLanguageID() const1551e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getLanguageID() const {
1552e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
1553e8d8bef9SDimitry Andric }
1554e8d8bef9SDimitry Andric 
isGlobalLinkage() const1555e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isGlobalLinkage() const {
1556e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsGlobaLinkageMask);
1557e8d8bef9SDimitry Andric }
1558e8d8bef9SDimitry Andric 
isOutOfLineEpilogOrPrologue() const1559e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
1560e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
1561e8d8bef9SDimitry Andric }
1562e8d8bef9SDimitry Andric 
hasTraceBackTableOffset() const1563e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
1564e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
1565e8d8bef9SDimitry Andric }
1566e8d8bef9SDimitry Andric 
isInternalProcedure() const1567e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isInternalProcedure() const {
1568e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsInternalProcedureMask);
1569e8d8bef9SDimitry Andric }
1570e8d8bef9SDimitry Andric 
hasControlledStorage() const1571e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasControlledStorage() const {
1572e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, HasControlledStorageMask);
1573e8d8bef9SDimitry Andric }
1574e8d8bef9SDimitry Andric 
isTOCless() const1575e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isTOCless() const {
1576e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsTOClessMask);
1577e8d8bef9SDimitry Andric }
1578e8d8bef9SDimitry Andric 
isFloatingPointPresent() const1579e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFloatingPointPresent() const {
1580e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsFloatingPointPresentMask);
1581e8d8bef9SDimitry Andric }
1582e8d8bef9SDimitry Andric 
isFloatingPointOperationLogOrAbortEnabled() const1583e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
1584e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
1585e8d8bef9SDimitry Andric }
1586e8d8bef9SDimitry Andric 
isInterruptHandler() const1587e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isInterruptHandler() const {
1588e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsInterruptHandlerMask);
1589e8d8bef9SDimitry Andric }
1590e8d8bef9SDimitry Andric 
isFuncNamePresent() const1591e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFuncNamePresent() const {
1592e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsFunctionNamePresentMask);
1593e8d8bef9SDimitry Andric }
1594e8d8bef9SDimitry Andric 
isAllocaUsed() const1595e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isAllocaUsed() const {
1596e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsAllocaUsedMask);
1597e8d8bef9SDimitry Andric }
1598e8d8bef9SDimitry Andric 
getOnConditionDirective() const1599e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
1600e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
1601e8d8bef9SDimitry Andric                              OnConditionDirectiveShift);
1602e8d8bef9SDimitry Andric }
1603e8d8bef9SDimitry Andric 
isCRSaved() const1604e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isCRSaved() const {
1605e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsCRSavedMask);
1606e8d8bef9SDimitry Andric }
1607e8d8bef9SDimitry Andric 
isLRSaved() const1608e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isLRSaved() const {
1609e8d8bef9SDimitry Andric   return GETBITWITHMASK(0, IsLRSavedMask);
1610e8d8bef9SDimitry Andric }
1611e8d8bef9SDimitry Andric 
isBackChainStored() const1612e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isBackChainStored() const {
1613e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, IsBackChainStoredMask);
1614e8d8bef9SDimitry Andric }
1615e8d8bef9SDimitry Andric 
isFixup() const1616e8d8bef9SDimitry Andric bool XCOFFTracebackTable::isFixup() const {
1617e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, IsFixupMask);
1618e8d8bef9SDimitry Andric }
1619e8d8bef9SDimitry Andric 
getNumOfFPRsSaved() const1620e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
1621e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
1622e8d8bef9SDimitry Andric }
1623e8d8bef9SDimitry Andric 
hasExtensionTable() const1624e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasExtensionTable() const {
1625e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, HasExtensionTableMask);
1626e8d8bef9SDimitry Andric }
1627e8d8bef9SDimitry Andric 
hasVectorInfo() const1628e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasVectorInfo() const {
1629e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, HasVectorInfoMask);
1630e8d8bef9SDimitry Andric }
1631e8d8bef9SDimitry Andric 
getNumOfGPRsSaved() const1632e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
1633e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
1634e8d8bef9SDimitry Andric }
1635e8d8bef9SDimitry Andric 
getNumberOfFixedParms() const1636e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
1637e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
1638e8d8bef9SDimitry Andric                              NumberOfFixedParmsShift);
1639e8d8bef9SDimitry Andric }
1640e8d8bef9SDimitry Andric 
getNumberOfFPParms() const1641e8d8bef9SDimitry Andric uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
1642e8d8bef9SDimitry Andric   return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
1643e8d8bef9SDimitry Andric                              NumberOfFloatingPointParmsShift);
1644e8d8bef9SDimitry Andric }
1645e8d8bef9SDimitry Andric 
hasParmsOnStack() const1646e8d8bef9SDimitry Andric bool XCOFFTracebackTable::hasParmsOnStack() const {
1647e8d8bef9SDimitry Andric   return GETBITWITHMASK(4, HasParmsOnStackMask);
1648e8d8bef9SDimitry Andric }
1649e8d8bef9SDimitry Andric 
1650e8d8bef9SDimitry Andric #undef GETBITWITHMASK
1651e8d8bef9SDimitry Andric #undef GETBITWITHMASKSHIFT
16520b57cec5SDimitry Andric } // namespace object
16530b57cec5SDimitry Andric } // namespace llvm
1654