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