1ab2eb2bfSHubert Tong //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===// 2ab2eb2bfSHubert Tong // 3ab2eb2bfSHubert Tong // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ab2eb2bfSHubert Tong // See https://llvm.org/LICENSE.txt for license information. 5ab2eb2bfSHubert Tong // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ab2eb2bfSHubert Tong // 7ab2eb2bfSHubert Tong //===----------------------------------------------------------------------===// 8ab2eb2bfSHubert Tong // 9ab2eb2bfSHubert Tong // This file defines the XCOFFObjectFile class. 10ab2eb2bfSHubert Tong // 11ab2eb2bfSHubert Tong //===----------------------------------------------------------------------===// 12ab2eb2bfSHubert Tong 13ab2eb2bfSHubert Tong #include "llvm/Object/XCOFFObjectFile.h" 14d33b016aSChen Zheng #include "llvm/ADT/StringSwitch.h" 150865d414SSimon Pilgrim #include "llvm/MC/SubtargetFeature.h" 162f0d755dSdiggerlin #include "llvm/Support/DataExtractor.h" 17ab2eb2bfSHubert Tong #include <cstddef> 18ab2eb2bfSHubert Tong #include <cstring> 19ab2eb2bfSHubert Tong 20ab2eb2bfSHubert Tong namespace llvm { 212f0d755dSdiggerlin 222f0d755dSdiggerlin using namespace XCOFF; 232f0d755dSdiggerlin 24ab2eb2bfSHubert Tong namespace object { 25ab2eb2bfSHubert Tong 26d60d7d69Sjasonliu static const uint8_t FunctionSym = 0x20; 27d60d7d69Sjasonliu static const uint16_t NoRelMask = 0x0001; 288e84311aSjasonliu static const size_t SymbolAuxTypeOffset = 17; 297c72e82bSJason Liu 30837ae69fSSean Fertile // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer 31837ae69fSSean Fertile // 'M'. Returns a pointer to the underlying object on success. 32ab2eb2bfSHubert Tong template <typename T> 33837ae69fSSean Fertile static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, 34ab2eb2bfSHubert Tong const uint64_t Size = sizeof(T)) { 3522cf54a7SArthur O'Dwyer uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr); 36e03a135bSReid Kleckner if (Error E = Binary::checkOffset(M, Addr, Size)) 37e03a135bSReid Kleckner return std::move(E); 38837ae69fSSean Fertile return reinterpret_cast<const T *>(Addr); 39837ae69fSSean Fertile } 40837ae69fSSean Fertile 41837ae69fSSean Fertile static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) { 42837ae69fSSean Fertile return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) + 43837ae69fSSean Fertile Offset); 44ab2eb2bfSHubert Tong } 45ab2eb2bfSHubert Tong 46a93a33cbSSean Fertile template <typename T> static const T *viewAs(uintptr_t in) { 47a93a33cbSSean Fertile return reinterpret_cast<const T *>(in); 48a93a33cbSSean Fertile } 49a93a33cbSSean Fertile 507c72e82bSJason Liu static StringRef generateXCOFFFixedNameStringRef(const char *Name) { 5129141da7SSean Fertile auto NulCharPtr = 5229141da7SSean Fertile static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize)); 539212206dSJason Liu return NulCharPtr ? StringRef(Name, NulCharPtr - Name) 5429141da7SSean Fertile : StringRef(Name, XCOFF::NameSize); 559212206dSJason Liu } 569212206dSJason Liu 57c63c1a72Sdiggerlin template <typename T> StringRef XCOFFSectionHeader<T>::getName() const { 58c63c1a72Sdiggerlin const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); 59c63c1a72Sdiggerlin return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name); 60c63c1a72Sdiggerlin } 61c63c1a72Sdiggerlin 62c63c1a72Sdiggerlin template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const { 63c63c1a72Sdiggerlin const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); 64c63c1a72Sdiggerlin return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask; 65c63c1a72Sdiggerlin } 66c63c1a72Sdiggerlin 67c63c1a72Sdiggerlin template <typename T> 68c63c1a72Sdiggerlin bool XCOFFSectionHeader<T>::isReservedSectionType() const { 69c63c1a72Sdiggerlin return getSectionType() & SectionFlagsReservedMask; 70c63c1a72Sdiggerlin } 71c63c1a72Sdiggerlin 72*2cdfd0b2SMaryam Benimmar template <typename AddressType> 73*2cdfd0b2SMaryam Benimmar bool XCOFFRelocation<AddressType>::isRelocationSigned() const { 7434d4bff3SDigger Lin return Info & XR_SIGN_INDICATOR_MASK; 7534d4bff3SDigger Lin } 7634d4bff3SDigger Lin 77*2cdfd0b2SMaryam Benimmar template <typename AddressType> 78*2cdfd0b2SMaryam Benimmar bool XCOFFRelocation<AddressType>::isFixupIndicated() const { 7934d4bff3SDigger Lin return Info & XR_FIXUP_INDICATOR_MASK; 8034d4bff3SDigger Lin } 8134d4bff3SDigger Lin 82*2cdfd0b2SMaryam Benimmar template <typename AddressType> 83*2cdfd0b2SMaryam Benimmar uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const { 8434d4bff3SDigger Lin // The relocation encodes the bit length being relocated minus 1. Add back 8534d4bff3SDigger Lin // the 1 to get the actual length being relocated. 8634d4bff3SDigger Lin return (Info & XR_BIASED_LENGTH_MASK) + 1; 8734d4bff3SDigger Lin } 8834d4bff3SDigger Lin 898e84311aSjasonliu uintptr_t 908e84311aSjasonliu XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, 918e84311aSjasonliu uint32_t Distance) { 928e84311aSjasonliu return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize); 938e84311aSjasonliu } 948e84311aSjasonliu 958e84311aSjasonliu const XCOFF::SymbolAuxType * 968e84311aSjasonliu XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const { 978e84311aSjasonliu assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 988e84311aSjasonliu return viewAs<XCOFF::SymbolAuxType>( 998e84311aSjasonliu getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset)); 1008e84311aSjasonliu } 1018e84311aSjasonliu 102837ae69fSSean Fertile void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, 103837ae69fSSean Fertile uintptr_t TableAddress) const { 104837ae69fSSean Fertile if (Addr < TableAddress) 105a93a33cbSSean Fertile report_fatal_error("Section header outside of section header table."); 106a93a33cbSSean Fertile 107837ae69fSSean Fertile uintptr_t Offset = Addr - TableAddress; 108837ae69fSSean Fertile if (Offset >= getSectionHeaderSize() * getNumberOfSections()) 109837ae69fSSean Fertile report_fatal_error("Section header outside of section header table."); 110837ae69fSSean Fertile 111a93a33cbSSean Fertile if (Offset % getSectionHeaderSize() != 0) 112a93a33cbSSean Fertile report_fatal_error( 113a93a33cbSSean Fertile "Section header pointer does not point to a valid section header."); 114837ae69fSSean Fertile } 115837ae69fSSean Fertile 116837ae69fSSean Fertile const XCOFFSectionHeader32 * 117837ae69fSSean Fertile XCOFFObjectFile::toSection32(DataRefImpl Ref) const { 118837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 119837ae69fSSean Fertile #ifndef NDEBUG 120837ae69fSSean Fertile checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 121a93a33cbSSean Fertile #endif 122837ae69fSSean Fertile return viewAs<XCOFFSectionHeader32>(Ref.p); 123837ae69fSSean Fertile } 124837ae69fSSean Fertile 125837ae69fSSean Fertile const XCOFFSectionHeader64 * 126837ae69fSSean Fertile XCOFFObjectFile::toSection64(DataRefImpl Ref) const { 127837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 128837ae69fSSean Fertile #ifndef NDEBUG 129837ae69fSSean Fertile checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 130837ae69fSSean Fertile #endif 131837ae69fSSean Fertile return viewAs<XCOFFSectionHeader64>(Ref.p); 132a93a33cbSSean Fertile } 133a93a33cbSSean Fertile 1348e84311aSjasonliu XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const { 1359212206dSJason Liu assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); 1367c72e82bSJason Liu #ifndef NDEBUG 1377c72e82bSJason Liu checkSymbolEntryPointer(Ref.p); 1387c72e82bSJason Liu #endif 1398e84311aSjasonliu return XCOFFSymbolRef(Ref, this); 1409212206dSJason Liu } 1419212206dSJason Liu 142837ae69fSSean Fertile const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { 143837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 144837ae69fSSean Fertile return static_cast<const XCOFFFileHeader32 *>(FileHeader); 145a93a33cbSSean Fertile } 146a93a33cbSSean Fertile 147837ae69fSSean Fertile const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { 148837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 149837ae69fSSean Fertile return static_cast<const XCOFFFileHeader64 *>(FileHeader); 150a93a33cbSSean Fertile } 151a93a33cbSSean Fertile 152*2cdfd0b2SMaryam Benimmar template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const { 153*2cdfd0b2SMaryam Benimmar return static_cast<const T *>(SectionHeaderTable); 154*2cdfd0b2SMaryam Benimmar } 155*2cdfd0b2SMaryam Benimmar 156837ae69fSSean Fertile const XCOFFSectionHeader32 * 157837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable32() const { 158837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 159837ae69fSSean Fertile return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable); 160837ae69fSSean Fertile } 161837ae69fSSean Fertile 162837ae69fSSean Fertile const XCOFFSectionHeader64 * 163837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable64() const { 164837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 165837ae69fSSean Fertile return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable); 166837ae69fSSean Fertile } 1679212206dSJason Liu 168ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1698e84311aSjasonliu uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress( 1708e84311aSjasonliu Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1); 1717c72e82bSJason Liu #ifndef NDEBUG 1727c72e82bSJason Liu // This function is used by basic_symbol_iterator, which allows to 1737c72e82bSJason Liu // point to the end-of-symbol-table address. 1748e84311aSjasonliu if (NextSymbolAddr != getEndOfSymbolTableAddress()) 1758e84311aSjasonliu checkSymbolEntryPointer(NextSymbolAddr); 1767c72e82bSJason Liu #endif 1778e84311aSjasonliu Symb.p = NextSymbolAddr; 178ab2eb2bfSHubert Tong } 179ab2eb2bfSHubert Tong 1807c72e82bSJason Liu Expected<StringRef> 1817c72e82bSJason Liu XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { 1827c72e82bSJason Liu // The byte offset is relative to the start of the string table. 1837c72e82bSJason Liu // A byte offset value of 0 is a null or zero-length symbol 1849212206dSJason Liu // name. A byte offset in the range 1 to 3 (inclusive) points into the length 1859212206dSJason Liu // field; as a soft-error recovery mechanism, we treat such cases as having an 1869212206dSJason Liu // offset of 0. 1879212206dSJason Liu if (Offset < 4) 1889212206dSJason Liu return StringRef(nullptr, 0); 1899212206dSJason Liu 1909212206dSJason Liu if (StringTable.Data != nullptr && StringTable.Size > Offset) 1919212206dSJason Liu return (StringTable.Data + Offset); 1929212206dSJason Liu 1937c72e82bSJason Liu return make_error<GenericBinaryError>("Bad offset for string table entry", 1949212206dSJason Liu object_error::parse_failed); 195ab2eb2bfSHubert Tong } 196ab2eb2bfSHubert Tong 1970dad3f6eSEsme-Yi StringRef XCOFFObjectFile::getStringTable() const { 19869396896SEsme-Yi // If the size is less than or equal to 4, then the string table contains no 19969396896SEsme-Yi // string data. 20069396896SEsme-Yi return StringRef(StringTable.Data, 20169396896SEsme-Yi StringTable.Size <= 4 ? 0 : StringTable.Size); 2020dad3f6eSEsme-Yi } 2030dad3f6eSEsme-Yi 2047c72e82bSJason Liu Expected<StringRef> 2057c72e82bSJason Liu XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { 2068e84311aSjasonliu if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 2077c72e82bSJason Liu return generateXCOFFFixedNameStringRef(CFileEntPtr->Name); 2087c72e82bSJason Liu return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset); 2097c72e82bSJason Liu } 2107c72e82bSJason Liu 2117c72e82bSJason Liu Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 2128e84311aSjasonliu return toSymbolRef(Symb).getName(); 2137c72e82bSJason Liu } 2147c72e82bSJason Liu 215ab2eb2bfSHubert Tong Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 2168e84311aSjasonliu return toSymbolRef(Symb).getValue(); 217ab2eb2bfSHubert Tong } 218ab2eb2bfSHubert Tong 219ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 2208e84311aSjasonliu return toSymbolRef(Symb).getValue(); 221ab2eb2bfSHubert Tong } 222ab2eb2bfSHubert Tong 223ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 224ab2eb2bfSHubert Tong uint64_t Result = 0; 225ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 226ab2eb2bfSHubert Tong return Result; 227ab2eb2bfSHubert Tong } 228ab2eb2bfSHubert Tong 229ab2eb2bfSHubert Tong Expected<SymbolRef::Type> 230ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 2318a23f74eSEsme-Yi // TODO: Return the correct symbol type. 232ab2eb2bfSHubert Tong return SymbolRef::ST_Other; 233ab2eb2bfSHubert Tong } 234ab2eb2bfSHubert Tong 235ab2eb2bfSHubert Tong Expected<section_iterator> 236ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 2378e84311aSjasonliu const int16_t SectNum = toSymbolRef(Symb).getSectionNumber(); 2389212206dSJason Liu 2399212206dSJason Liu if (isReservedSectionNumber(SectNum)) 2409212206dSJason Liu return section_end(); 2419212206dSJason Liu 242837ae69fSSean Fertile Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum); 243837ae69fSSean Fertile if (!ExpSec) 244837ae69fSSean Fertile return ExpSec.takeError(); 2459212206dSJason Liu 246837ae69fSSean Fertile return section_iterator(SectionRef(ExpSec.get(), this)); 247ab2eb2bfSHubert Tong } 248ab2eb2bfSHubert Tong 249ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 250a93a33cbSSean Fertile const char *Ptr = reinterpret_cast<const char *>(Sec.p); 251a93a33cbSSean Fertile Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); 252ab2eb2bfSHubert Tong } 253ab2eb2bfSHubert Tong 2548be28cdcSFangrui Song Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { 2557c72e82bSJason Liu return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec)); 256ab2eb2bfSHubert Tong } 257ab2eb2bfSHubert Tong 258ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 259210314aeSSean Fertile // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 260210314aeSSean Fertile // with MSVC. 261210314aeSSean Fertile if (is64Bit()) 262210314aeSSean Fertile return toSection64(Sec)->VirtualAddress; 263210314aeSSean Fertile 264210314aeSSean Fertile return toSection32(Sec)->VirtualAddress; 265ab2eb2bfSHubert Tong } 266ab2eb2bfSHubert Tong 267ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 268a93a33cbSSean Fertile // Section numbers in XCOFF are numbered beginning at 1. A section number of 269a93a33cbSSean Fertile // zero is used to indicate that a symbol is being imported or is undefined. 270837ae69fSSean Fertile if (is64Bit()) 271837ae69fSSean Fertile return toSection64(Sec) - sectionHeaderTable64() + 1; 272837ae69fSSean Fertile else 273837ae69fSSean Fertile return toSection32(Sec) - sectionHeaderTable32() + 1; 274ab2eb2bfSHubert Tong } 275ab2eb2bfSHubert Tong 276ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 277210314aeSSean Fertile // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 278210314aeSSean Fertile // with MSVC. 279210314aeSSean Fertile if (is64Bit()) 280210314aeSSean Fertile return toSection64(Sec)->SectionSize; 281210314aeSSean Fertile 282210314aeSSean Fertile return toSection32(Sec)->SectionSize; 283ab2eb2bfSHubert Tong } 284ab2eb2bfSHubert Tong 285e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>> 286e1cb2c0fSFangrui Song XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { 287b91f798fSdiggerlin if (isSectionVirtual(Sec)) 288b91f798fSdiggerlin return ArrayRef<uint8_t>(); 289b91f798fSdiggerlin 290ea13683fSdiggerlin uint64_t OffsetToRaw; 291ea13683fSdiggerlin if (is64Bit()) 292ea13683fSdiggerlin OffsetToRaw = toSection64(Sec)->FileOffsetToRawData; 293ea13683fSdiggerlin else 294ea13683fSdiggerlin OffsetToRaw = toSection32(Sec)->FileOffsetToRawData; 295b91f798fSdiggerlin 296b91f798fSdiggerlin const uint8_t * ContentStart = base() + OffsetToRaw; 297b91f798fSdiggerlin uint64_t SectionSize = getSectionSize(Sec); 29822cf54a7SArthur O'Dwyer if (checkOffset(Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize)) 299b91f798fSdiggerlin return make_error<BinaryError>(); 300b91f798fSdiggerlin 301b91f798fSdiggerlin return makeArrayRef(ContentStart,SectionSize); 302ab2eb2bfSHubert Tong } 303ab2eb2bfSHubert Tong 304ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 305ab2eb2bfSHubert Tong uint64_t Result = 0; 306ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 307ab2eb2bfSHubert Tong return Result; 308ab2eb2bfSHubert Tong } 309ab2eb2bfSHubert Tong 310ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 311d33b016aSChen Zheng return false; 312ab2eb2bfSHubert Tong } 313ab2eb2bfSHubert Tong 314ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { 315837ae69fSSean Fertile return getSectionFlags(Sec) & XCOFF::STYP_TEXT; 316ab2eb2bfSHubert Tong } 317ab2eb2bfSHubert Tong 318ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { 319837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec); 320a93a33cbSSean Fertile return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); 321ab2eb2bfSHubert Tong } 322ab2eb2bfSHubert Tong 323ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { 324837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec); 325a93a33cbSSean Fertile return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); 326ab2eb2bfSHubert Tong } 327ab2eb2bfSHubert Tong 328c8e980abSEsme-Yi bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const { 329c8e980abSEsme-Yi uint32_t Flags = getSectionFlags(Sec); 330c8e980abSEsme-Yi return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF); 331c8e980abSEsme-Yi } 332c8e980abSEsme-Yi 333ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { 334b91f798fSdiggerlin return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0 335b91f798fSdiggerlin : toSection32(Sec)->FileOffsetToRawData == 0; 336ab2eb2bfSHubert Tong } 337ab2eb2bfSHubert Tong 338ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 339d60d7d69Sjasonliu DataRefImpl Ret; 340*2cdfd0b2SMaryam Benimmar if (is64Bit()) { 341*2cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); 342*2cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 343*2cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); 344*2cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 345*2cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 346*2cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 347*2cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 348*2cdfd0b2SMaryam Benimmar } 349d60d7d69Sjasonliu Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); 350*2cdfd0b2SMaryam Benimmar } else { 351*2cdfd0b2SMaryam Benimmar const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 352*2cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 353*2cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); 354*2cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 355*2cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 356*2cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 357*2cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 358*2cdfd0b2SMaryam Benimmar } 359*2cdfd0b2SMaryam Benimmar Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); 360*2cdfd0b2SMaryam Benimmar } 361d60d7d69Sjasonliu return relocation_iterator(RelocationRef(Ret, this)); 362ab2eb2bfSHubert Tong } 363ab2eb2bfSHubert Tong 364ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { 365d60d7d69Sjasonliu DataRefImpl Ret; 366*2cdfd0b2SMaryam Benimmar if (is64Bit()) { 367*2cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); 368*2cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 369*2cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); 370*2cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 371*2cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 372*2cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 373*2cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 374*2cdfd0b2SMaryam Benimmar } 375d60d7d69Sjasonliu Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); 376*2cdfd0b2SMaryam Benimmar } else { 377*2cdfd0b2SMaryam Benimmar const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 378*2cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 379*2cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); 380*2cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 381*2cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 382*2cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 383*2cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 384*2cdfd0b2SMaryam Benimmar } 385*2cdfd0b2SMaryam Benimmar Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); 386*2cdfd0b2SMaryam Benimmar } 387d60d7d69Sjasonliu return relocation_iterator(RelocationRef(Ret, this)); 388ab2eb2bfSHubert Tong } 389ab2eb2bfSHubert Tong 390ab2eb2bfSHubert Tong void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 391*2cdfd0b2SMaryam Benimmar if (is64Bit()) 392*2cdfd0b2SMaryam Benimmar Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1); 393*2cdfd0b2SMaryam Benimmar else 394d60d7d69Sjasonliu Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); 395ab2eb2bfSHubert Tong } 396ab2eb2bfSHubert Tong 397ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 398*2cdfd0b2SMaryam Benimmar if (is64Bit()) { 399*2cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 400*2cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64(); 401*2cdfd0b2SMaryam Benimmar const uint64_t RelocAddress = Reloc->VirtualAddress; 402*2cdfd0b2SMaryam Benimmar const uint16_t NumberOfSections = getNumberOfSections(); 403*2cdfd0b2SMaryam Benimmar for (uint16_t I = 0; I < NumberOfSections; ++I) { 404*2cdfd0b2SMaryam Benimmar // Find which section this relocation belongs to, and get the 405*2cdfd0b2SMaryam Benimmar // relocation offset relative to the start of the section. 406*2cdfd0b2SMaryam Benimmar if (Sec64->VirtualAddress <= RelocAddress && 407*2cdfd0b2SMaryam Benimmar RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) { 408*2cdfd0b2SMaryam Benimmar return RelocAddress - Sec64->VirtualAddress; 409*2cdfd0b2SMaryam Benimmar } 410*2cdfd0b2SMaryam Benimmar ++Sec64; 411*2cdfd0b2SMaryam Benimmar } 412*2cdfd0b2SMaryam Benimmar } else { 413d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 414d60d7d69Sjasonliu const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); 415d60d7d69Sjasonliu const uint32_t RelocAddress = Reloc->VirtualAddress; 416d60d7d69Sjasonliu const uint16_t NumberOfSections = getNumberOfSections(); 417*2cdfd0b2SMaryam Benimmar for (uint16_t I = 0; I < NumberOfSections; ++I) { 418*2cdfd0b2SMaryam Benimmar // Find which section this relocation belongs to, and get the 419d60d7d69Sjasonliu // relocation offset relative to the start of the section. 420d60d7d69Sjasonliu if (Sec32->VirtualAddress <= RelocAddress && 421d60d7d69Sjasonliu RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { 422d60d7d69Sjasonliu return RelocAddress - Sec32->VirtualAddress; 423d60d7d69Sjasonliu } 424d60d7d69Sjasonliu ++Sec32; 425d60d7d69Sjasonliu } 426*2cdfd0b2SMaryam Benimmar } 427d60d7d69Sjasonliu return InvalidRelocOffset; 428ab2eb2bfSHubert Tong } 429ab2eb2bfSHubert Tong 430ab2eb2bfSHubert Tong symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 431*2cdfd0b2SMaryam Benimmar uint32_t Index; 432*2cdfd0b2SMaryam Benimmar if (is64Bit()) { 433*2cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 434*2cdfd0b2SMaryam Benimmar Index = Reloc->SymbolIndex; 435*2cdfd0b2SMaryam Benimmar 436*2cdfd0b2SMaryam Benimmar if (Index >= getNumberOfSymbolTableEntries64()) 437*2cdfd0b2SMaryam Benimmar return symbol_end(); 438*2cdfd0b2SMaryam Benimmar } else { 439d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 440*2cdfd0b2SMaryam Benimmar Index = Reloc->SymbolIndex; 441d60d7d69Sjasonliu 442d60d7d69Sjasonliu if (Index >= getLogicalNumberOfSymbolTableEntries32()) 443d60d7d69Sjasonliu return symbol_end(); 444*2cdfd0b2SMaryam Benimmar } 445d60d7d69Sjasonliu DataRefImpl SymDRI; 4468e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(Index); 447d60d7d69Sjasonliu return symbol_iterator(SymbolRef(SymDRI, this)); 448ab2eb2bfSHubert Tong } 449ab2eb2bfSHubert Tong 450ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { 451d60d7d69Sjasonliu if (is64Bit()) 452*2cdfd0b2SMaryam Benimmar return viewAs<XCOFFRelocation64>(Rel.p)->Type; 453d60d7d69Sjasonliu return viewAs<XCOFFRelocation32>(Rel.p)->Type; 454ab2eb2bfSHubert Tong } 455ab2eb2bfSHubert Tong 456ab2eb2bfSHubert Tong void XCOFFObjectFile::getRelocationTypeName( 457ab2eb2bfSHubert Tong DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 458*2cdfd0b2SMaryam Benimmar StringRef Res; 459*2cdfd0b2SMaryam Benimmar if (is64Bit()) { 460*2cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 461*2cdfd0b2SMaryam Benimmar Res = XCOFF::getRelocationTypeString(Reloc->Type); 462*2cdfd0b2SMaryam Benimmar } else { 463d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 464*2cdfd0b2SMaryam Benimmar Res = XCOFF::getRelocationTypeString(Reloc->Type); 465*2cdfd0b2SMaryam Benimmar } 466d60d7d69Sjasonliu Result.append(Res.begin(), Res.end()); 467ab2eb2bfSHubert Tong } 468ab2eb2bfSHubert Tong 469ac00376aSvgxbj Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 470ab2eb2bfSHubert Tong uint32_t Result = 0; 4718a23f74eSEsme-Yi // TODO: Return correct symbol flags. 472ab2eb2bfSHubert Tong return Result; 473ab2eb2bfSHubert Tong } 474ab2eb2bfSHubert Tong 475ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { 4769212206dSJason Liu DataRefImpl SymDRI; 4779212206dSJason Liu SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); 4789212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this)); 479ab2eb2bfSHubert Tong } 480ab2eb2bfSHubert Tong 481ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_end() const { 4829212206dSJason Liu DataRefImpl SymDRI; 4838e84311aSjasonliu const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries(); 4848e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries); 4859212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this)); 486ab2eb2bfSHubert Tong } 487ab2eb2bfSHubert Tong 488ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_begin() const { 489a93a33cbSSean Fertile DataRefImpl DRI; 490837ae69fSSean Fertile DRI.p = getSectionHeaderTableAddress(); 491a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this)); 492ab2eb2bfSHubert Tong } 493ab2eb2bfSHubert Tong 494ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_end() const { 495a93a33cbSSean Fertile DataRefImpl DRI; 496837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(), 497837ae69fSSean Fertile getNumberOfSections() * getSectionHeaderSize()); 498a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this)); 499ab2eb2bfSHubert Tong } 500ab2eb2bfSHubert Tong 501837ae69fSSean Fertile uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } 502ab2eb2bfSHubert Tong 503ab2eb2bfSHubert Tong StringRef XCOFFObjectFile::getFileFormatName() const { 504837ae69fSSean Fertile return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; 505ab2eb2bfSHubert Tong } 506ab2eb2bfSHubert Tong 507ab2eb2bfSHubert Tong Triple::ArchType XCOFFObjectFile::getArch() const { 508837ae69fSSean Fertile return is64Bit() ? Triple::ppc64 : Triple::ppc; 509ab2eb2bfSHubert Tong } 510ab2eb2bfSHubert Tong 511ab2eb2bfSHubert Tong SubtargetFeatures XCOFFObjectFile::getFeatures() const { 512ab2eb2bfSHubert Tong return SubtargetFeatures(); 513ab2eb2bfSHubert Tong } 514ab2eb2bfSHubert Tong 515ab2eb2bfSHubert Tong bool XCOFFObjectFile::isRelocatableObject() const { 516d60d7d69Sjasonliu if (is64Bit()) 5178ec73e96SAmir Ayupov return !(fileHeader64()->Flags & NoRelMask); 518d60d7d69Sjasonliu return !(fileHeader32()->Flags & NoRelMask); 519ab2eb2bfSHubert Tong } 520ab2eb2bfSHubert Tong 521a93a33cbSSean Fertile Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { 522a93a33cbSSean Fertile // TODO FIXME Should get from auxiliary_header->o_entry when support for the 523a93a33cbSSean Fertile // auxiliary_header is added. 524a93a33cbSSean Fertile return 0; 525a93a33cbSSean Fertile } 526a93a33cbSSean Fertile 527d33b016aSChen Zheng StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const { 528d33b016aSChen Zheng return StringSwitch<StringRef>(Name) 529d33b016aSChen Zheng .Case("dwinfo", "debug_info") 530d33b016aSChen Zheng .Case("dwline", "debug_line") 531d33b016aSChen Zheng .Case("dwpbnms", "debug_pubnames") 532d33b016aSChen Zheng .Case("dwpbtyp", "debug_pubtypes") 533d33b016aSChen Zheng .Case("dwarnge", "debug_aranges") 534d33b016aSChen Zheng .Case("dwabrev", "debug_abbrev") 535d33b016aSChen Zheng .Case("dwstr", "debug_str") 536d33b016aSChen Zheng .Case("dwrnges", "debug_ranges") 537d33b016aSChen Zheng .Case("dwloc", "debug_loc") 538d33b016aSChen Zheng .Case("dwframe", "debug_frame") 539d33b016aSChen Zheng .Case("dwmac", "debug_macinfo") 540d33b016aSChen Zheng .Default(Name); 541d33b016aSChen Zheng } 542d33b016aSChen Zheng 543837ae69fSSean Fertile size_t XCOFFObjectFile::getFileHeaderSize() const { 544837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); 5459212206dSJason Liu } 5469212206dSJason Liu 547837ae69fSSean Fertile size_t XCOFFObjectFile::getSectionHeaderSize() const { 548837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFSectionHeader64) : 549837ae69fSSean Fertile sizeof(XCOFFSectionHeader32); 550837ae69fSSean Fertile } 551837ae69fSSean Fertile 552837ae69fSSean Fertile bool XCOFFObjectFile::is64Bit() const { 553837ae69fSSean Fertile return Binary::ID_XCOFF64 == getType(); 554837ae69fSSean Fertile } 555837ae69fSSean Fertile 556837ae69fSSean Fertile uint16_t XCOFFObjectFile::getMagic() const { 557837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; 558837ae69fSSean Fertile } 559837ae69fSSean Fertile 560837ae69fSSean Fertile Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { 561837ae69fSSean Fertile if (Num <= 0 || Num > getNumberOfSections()) 562837ae69fSSean Fertile return errorCodeToError(object_error::invalid_section_index); 563837ae69fSSean Fertile 564837ae69fSSean Fertile DataRefImpl DRI; 565837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(), 566837ae69fSSean Fertile getSectionHeaderSize() * (Num - 1)); 567837ae69fSSean Fertile return DRI; 5689212206dSJason Liu } 5699212206dSJason Liu 5709212206dSJason Liu Expected<StringRef> 5718e84311aSjasonliu XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { 5728e84311aSjasonliu const int16_t SectionNum = SymEntPtr.getSectionNumber(); 5739212206dSJason Liu 5749212206dSJason Liu switch (SectionNum) { 5759212206dSJason Liu case XCOFF::N_DEBUG: 5769212206dSJason Liu return "N_DEBUG"; 5779212206dSJason Liu case XCOFF::N_ABS: 5789212206dSJason Liu return "N_ABS"; 5799212206dSJason Liu case XCOFF::N_UNDEF: 5809212206dSJason Liu return "N_UNDEF"; 581837ae69fSSean Fertile default: 582837ae69fSSean Fertile Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); 583837ae69fSSean Fertile if (SecRef) 5847c72e82bSJason Liu return generateXCOFFFixedNameStringRef( 5857c72e82bSJason Liu getSectionNameInternal(SecRef.get())); 586837ae69fSSean Fertile return SecRef.takeError(); 5879212206dSJason Liu } 5889212206dSJason Liu } 5899212206dSJason Liu 5908a23f74eSEsme-Yi unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 5918a23f74eSEsme-Yi XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this); 5928a23f74eSEsme-Yi return XCOFFSymRef.getSectionNumber(); 5938a23f74eSEsme-Yi } 5948a23f74eSEsme-Yi 5959212206dSJason Liu bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 5969212206dSJason Liu return (SectionNumber <= 0 && SectionNumber >= -2); 5979212206dSJason Liu } 5989212206dSJason Liu 5999212206dSJason Liu uint16_t XCOFFObjectFile::getNumberOfSections() const { 600837ae69fSSean Fertile return is64Bit() ? fileHeader64()->NumberOfSections 601837ae69fSSean Fertile : fileHeader32()->NumberOfSections; 6029212206dSJason Liu } 6039212206dSJason Liu 604837ae69fSSean Fertile int32_t XCOFFObjectFile::getTimeStamp() const { 605837ae69fSSean Fertile return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 6069212206dSJason Liu } 6079212206dSJason Liu 6089212206dSJason Liu uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 609837ae69fSSean Fertile return is64Bit() ? fileHeader64()->AuxHeaderSize 610837ae69fSSean Fertile : fileHeader32()->AuxHeaderSize; 6119212206dSJason Liu } 6129212206dSJason Liu 613837ae69fSSean Fertile uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 614837ae69fSSean Fertile return fileHeader32()->SymbolTableOffset; 615837ae69fSSean Fertile } 616ab2eb2bfSHubert Tong 617837ae69fSSean Fertile int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 618837ae69fSSean Fertile // As far as symbol table size is concerned, if this field is negative it is 619837ae69fSSean Fertile // to be treated as a 0. However since this field is also used for printing we 620837ae69fSSean Fertile // don't want to truncate any negative values. 621837ae69fSSean Fertile return fileHeader32()->NumberOfSymTableEntries; 622837ae69fSSean Fertile } 623ab2eb2bfSHubert Tong 624837ae69fSSean Fertile uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 625837ae69fSSean Fertile return (fileHeader32()->NumberOfSymTableEntries >= 0 626837ae69fSSean Fertile ? fileHeader32()->NumberOfSymTableEntries 627837ae69fSSean Fertile : 0); 628837ae69fSSean Fertile } 629a93a33cbSSean Fertile 630837ae69fSSean Fertile uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 631837ae69fSSean Fertile return fileHeader64()->SymbolTableOffset; 632837ae69fSSean Fertile } 633837ae69fSSean Fertile 634837ae69fSSean Fertile uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 635837ae69fSSean Fertile return fileHeader64()->NumberOfSymTableEntries; 636837ae69fSSean Fertile } 637837ae69fSSean Fertile 6388e84311aSjasonliu uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { 6398e84311aSjasonliu return is64Bit() ? getNumberOfSymbolTableEntries64() 6407c72e82bSJason Liu : getLogicalNumberOfSymbolTableEntries32(); 6418e84311aSjasonliu } 6428e84311aSjasonliu 6438e84311aSjasonliu uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { 6448e84311aSjasonliu const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 6457c72e82bSJason Liu return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), 6467c72e82bSJason Liu XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); 6477c72e82bSJason Liu } 6487c72e82bSJason Liu 6497c72e82bSJason Liu void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { 6507c72e82bSJason Liu if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) 6517c72e82bSJason Liu report_fatal_error("Symbol table entry is outside of symbol table."); 6527c72e82bSJason Liu 6537c72e82bSJason Liu if (SymbolEntPtr >= getEndOfSymbolTableAddress()) 6547c72e82bSJason Liu report_fatal_error("Symbol table entry is outside of symbol table."); 6557c72e82bSJason Liu 6567c72e82bSJason Liu ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - 6577c72e82bSJason Liu reinterpret_cast<const char *>(SymbolTblPtr); 6587c72e82bSJason Liu 6597c72e82bSJason Liu if (Offset % XCOFF::SymbolTableEntrySize != 0) 6607c72e82bSJason Liu report_fatal_error( 6617c72e82bSJason Liu "Symbol table entry position is not valid inside of symbol table."); 6627c72e82bSJason Liu } 6637c72e82bSJason Liu 6647c72e82bSJason Liu uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { 6657c72e82bSJason Liu return (reinterpret_cast<const char *>(SymbolEntPtr) - 6667c72e82bSJason Liu reinterpret_cast<const char *>(SymbolTblPtr)) / 6677c72e82bSJason Liu XCOFF::SymbolTableEntrySize; 6687c72e82bSJason Liu } 6697c72e82bSJason Liu 6708e84311aSjasonliu uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { 6718e84311aSjasonliu return getAdvancedSymbolEntryAddress( 6728e84311aSjasonliu reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); 6738e84311aSjasonliu } 6748e84311aSjasonliu 67534d4bff3SDigger Lin Expected<StringRef> 67634d4bff3SDigger Lin XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { 6778e84311aSjasonliu const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 67834d4bff3SDigger Lin 6798e84311aSjasonliu if (Index >= NumberOfSymTableEntries) 68034d4bff3SDigger Lin return errorCodeToError(object_error::invalid_symbol_index); 68134d4bff3SDigger Lin 68234d4bff3SDigger Lin DataRefImpl SymDRI; 6838e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(Index); 68434d4bff3SDigger Lin return getSymbolName(SymDRI); 68534d4bff3SDigger Lin } 68634d4bff3SDigger Lin 687837ae69fSSean Fertile uint16_t XCOFFObjectFile::getFlags() const { 688837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 689837ae69fSSean Fertile } 690837ae69fSSean Fertile 691837ae69fSSean Fertile const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 692837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 693837ae69fSSean Fertile } 694837ae69fSSean Fertile 695837ae69fSSean Fertile uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 696837ae69fSSean Fertile return reinterpret_cast<uintptr_t>(SectionHeaderTable); 697837ae69fSSean Fertile } 698837ae69fSSean Fertile 699837ae69fSSean Fertile int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 700837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 701837ae69fSSean Fertile } 702837ae69fSSean Fertile 703837ae69fSSean Fertile XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 704837ae69fSSean Fertile : ObjectFile(Type, Object) { 705837ae69fSSean Fertile assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 706837ae69fSSean Fertile } 707837ae69fSSean Fertile 708837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 709837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called for non 64-bit file."); 710837ae69fSSean Fertile const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 711837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader64>(TablePtr, 712837ae69fSSean Fertile TablePtr + getNumberOfSections()); 713837ae69fSSean Fertile } 714837ae69fSSean Fertile 715837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 716837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 717837ae69fSSean Fertile const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 718837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader32>(TablePtr, 719837ae69fSSean Fertile TablePtr + getNumberOfSections()); 720837ae69fSSean Fertile } 721837ae69fSSean Fertile 72234d4bff3SDigger Lin // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO 72334d4bff3SDigger Lin // section header contains the actual count of relocation entries in the s_paddr 72434d4bff3SDigger Lin // field. STYP_OVRFLO headers contain the section index of their corresponding 72534d4bff3SDigger Lin // sections as their raw "NumberOfRelocations" field value. 726*2cdfd0b2SMaryam Benimmar template <typename T> 727*2cdfd0b2SMaryam Benimmar Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries( 728*2cdfd0b2SMaryam Benimmar const XCOFFSectionHeader<T> &Sec) const { 729*2cdfd0b2SMaryam Benimmar const T &Section = static_cast<const T &>(Sec); 730*2cdfd0b2SMaryam Benimmar if (is64Bit()) 731*2cdfd0b2SMaryam Benimmar return Section.NumberOfRelocations; 73234d4bff3SDigger Lin 733*2cdfd0b2SMaryam Benimmar uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1; 734*2cdfd0b2SMaryam Benimmar if (Section.NumberOfRelocations < XCOFF::RelocOverflow) 735*2cdfd0b2SMaryam Benimmar return Section.NumberOfRelocations; 73634d4bff3SDigger Lin for (const auto &Sec : sections32()) { 73734d4bff3SDigger Lin if (Sec.Flags == XCOFF::STYP_OVRFLO && 73834d4bff3SDigger Lin Sec.NumberOfRelocations == SectionIndex) 73934d4bff3SDigger Lin return Sec.PhysicalAddress; 74034d4bff3SDigger Lin } 74134d4bff3SDigger Lin return errorCodeToError(object_error::parse_failed); 74234d4bff3SDigger Lin } 74334d4bff3SDigger Lin 744*2cdfd0b2SMaryam Benimmar template <typename Shdr, typename Reloc> 745*2cdfd0b2SMaryam Benimmar Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const { 74634d4bff3SDigger Lin uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), 74734d4bff3SDigger Lin Sec.FileOffsetToRelocationInfo); 748*2cdfd0b2SMaryam Benimmar auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec); 74934d4bff3SDigger Lin if (Error E = NumRelocEntriesOrErr.takeError()) 750c55cf4afSBill Wendling return std::move(E); 75134d4bff3SDigger Lin 75234d4bff3SDigger Lin uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); 753*2cdfd0b2SMaryam Benimmar static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 || 754*2cdfd0b2SMaryam Benimmar sizeof(Reloc) == XCOFF::RelocationSerializationSize32), 755*2cdfd0b2SMaryam Benimmar "Relocation structure is incorrect"); 75634d4bff3SDigger Lin auto RelocationOrErr = 757*2cdfd0b2SMaryam Benimmar getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr), 758*2cdfd0b2SMaryam Benimmar NumRelocEntries * sizeof(Reloc)); 75934d4bff3SDigger Lin if (Error E = RelocationOrErr.takeError()) 760c55cf4afSBill Wendling return std::move(E); 76134d4bff3SDigger Lin 762*2cdfd0b2SMaryam Benimmar const Reloc *StartReloc = RelocationOrErr.get(); 76334d4bff3SDigger Lin 764*2cdfd0b2SMaryam Benimmar return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries); 76534d4bff3SDigger Lin } 76634d4bff3SDigger Lin 767837ae69fSSean Fertile Expected<XCOFFStringTable> 768837ae69fSSean Fertile XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 769837ae69fSSean Fertile // If there is a string table, then the buffer must contain at least 4 bytes 770837ae69fSSean Fertile // for the string table's size. Not having a string table is not an error. 771e03a135bSReid Kleckner if (Error E = Binary::checkOffset( 772e03a135bSReid Kleckner Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { 773e03a135bSReid Kleckner consumeError(std::move(E)); 774837ae69fSSean Fertile return XCOFFStringTable{0, nullptr}; 775e03a135bSReid Kleckner } 776837ae69fSSean Fertile 777837ae69fSSean Fertile // Read the size out of the buffer. 778837ae69fSSean Fertile uint32_t Size = support::endian::read32be(Obj->base() + Offset); 779837ae69fSSean Fertile 780837ae69fSSean Fertile // If the size is less then 4, then the string table is just a size and no 781837ae69fSSean Fertile // string data. 782837ae69fSSean Fertile if (Size <= 4) 783837ae69fSSean Fertile return XCOFFStringTable{4, nullptr}; 784837ae69fSSean Fertile 785837ae69fSSean Fertile auto StringTableOrErr = 786837ae69fSSean Fertile getObject<char>(Obj->Data, Obj->base() + Offset, Size); 787837ae69fSSean Fertile if (Error E = StringTableOrErr.takeError()) 788c55cf4afSBill Wendling return std::move(E); 789837ae69fSSean Fertile 790837ae69fSSean Fertile const char *StringTablePtr = StringTableOrErr.get(); 791837ae69fSSean Fertile if (StringTablePtr[Size - 1] != '\0') 792837ae69fSSean Fertile return errorCodeToError(object_error::string_table_non_null_end); 793837ae69fSSean Fertile 794837ae69fSSean Fertile return XCOFFStringTable{Size, StringTablePtr}; 795837ae69fSSean Fertile } 796837ae69fSSean Fertile 797837ae69fSSean Fertile Expected<std::unique_ptr<XCOFFObjectFile>> 798837ae69fSSean Fertile XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 7990eaee545SJonas Devlieghere // Can't use std::make_unique because of the private constructor. 800837ae69fSSean Fertile std::unique_ptr<XCOFFObjectFile> Obj; 801837ae69fSSean Fertile Obj.reset(new XCOFFObjectFile(Type, MBR)); 802837ae69fSSean Fertile 803837ae69fSSean Fertile uint64_t CurOffset = 0; 804837ae69fSSean Fertile const auto *Base = Obj->base(); 805837ae69fSSean Fertile MemoryBufferRef Data = Obj->Data; 806837ae69fSSean Fertile 807837ae69fSSean Fertile // Parse file header. 808837ae69fSSean Fertile auto FileHeaderOrErr = 809837ae69fSSean Fertile getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 810837ae69fSSean Fertile if (Error E = FileHeaderOrErr.takeError()) 811c55cf4afSBill Wendling return std::move(E); 812837ae69fSSean Fertile Obj->FileHeader = FileHeaderOrErr.get(); 813837ae69fSSean Fertile 814837ae69fSSean Fertile CurOffset += Obj->getFileHeaderSize(); 815a93a33cbSSean Fertile // TODO FIXME we don't have support for an optional header yet, so just skip 816a93a33cbSSean Fertile // past it. 817837ae69fSSean Fertile CurOffset += Obj->getOptionalHeaderSize(); 818a93a33cbSSean Fertile 819837ae69fSSean Fertile // Parse the section header table if it is present. 820837ae69fSSean Fertile if (Obj->getNumberOfSections()) { 821837ae69fSSean Fertile auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, 822837ae69fSSean Fertile Obj->getNumberOfSections() * 823837ae69fSSean Fertile Obj->getSectionHeaderSize()); 824837ae69fSSean Fertile if (Error E = SecHeadersOrErr.takeError()) 825c55cf4afSBill Wendling return std::move(E); 826837ae69fSSean Fertile Obj->SectionHeaderTable = SecHeadersOrErr.get(); 827a93a33cbSSean Fertile } 828ab2eb2bfSHubert Tong 8298e84311aSjasonliu const uint32_t NumberOfSymbolTableEntries = 8308e84311aSjasonliu Obj->getNumberOfSymbolTableEntries(); 831fd75ee91SSean Fertile 832837ae69fSSean Fertile // If there is no symbol table we are done parsing the memory buffer. 8338e84311aSjasonliu if (NumberOfSymbolTableEntries == 0) 834c55cf4afSBill Wendling return std::move(Obj); 835837ae69fSSean Fertile 836837ae69fSSean Fertile // Parse symbol table. 8378e84311aSjasonliu CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() 8388e84311aSjasonliu : Obj->getSymbolTableOffset32(); 8398e84311aSjasonliu const uint64_t SymbolTableSize = 8408e84311aSjasonliu static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * 8418e84311aSjasonliu NumberOfSymbolTableEntries; 842837ae69fSSean Fertile auto SymTableOrErr = 8438e84311aSjasonliu getObject<void *>(Data, Base + CurOffset, SymbolTableSize); 844837ae69fSSean Fertile if (Error E = SymTableOrErr.takeError()) 845c55cf4afSBill Wendling return std::move(E); 846837ae69fSSean Fertile Obj->SymbolTblPtr = SymTableOrErr.get(); 847837ae69fSSean Fertile CurOffset += SymbolTableSize; 848fd75ee91SSean Fertile 849837ae69fSSean Fertile // Parse String table. 850837ae69fSSean Fertile Expected<XCOFFStringTable> StringTableOrErr = 851837ae69fSSean Fertile parseStringTable(Obj.get(), CurOffset); 852837ae69fSSean Fertile if (Error E = StringTableOrErr.takeError()) 853c55cf4afSBill Wendling return std::move(E); 854837ae69fSSean Fertile Obj->StringTable = StringTableOrErr.get(); 855fd75ee91SSean Fertile 856c55cf4afSBill Wendling return std::move(Obj); 857fd75ee91SSean Fertile } 858fd75ee91SSean Fertile 859ab2eb2bfSHubert Tong Expected<std::unique_ptr<ObjectFile>> 860837ae69fSSean Fertile ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 861837ae69fSSean Fertile unsigned FileType) { 862837ae69fSSean Fertile return XCOFFObjectFile::create(FileType, MemBufRef); 863ab2eb2bfSHubert Tong } 864ab2eb2bfSHubert Tong 8658e84311aSjasonliu bool XCOFFSymbolRef::isFunction() const { 8668e84311aSjasonliu if (!isCsectSymbol()) 8678e84311aSjasonliu return false; 8688e84311aSjasonliu 8698e84311aSjasonliu if (getSymbolType() & FunctionSym) 8708e84311aSjasonliu return true; 8718e84311aSjasonliu 8728e84311aSjasonliu Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); 8738e84311aSjasonliu if (!ExpCsectAuxEnt) 8748e84311aSjasonliu return false; 8758e84311aSjasonliu 8768e84311aSjasonliu const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); 8778e84311aSjasonliu 8788e84311aSjasonliu // A function definition should be a label definition. 8798e84311aSjasonliu // FIXME: This is not necessarily the case when -ffunction-sections is 8808e84311aSjasonliu // enabled. 8818e84311aSjasonliu if (!CsectAuxRef.isLabel()) 8828e84311aSjasonliu return false; 8838e84311aSjasonliu 8848e84311aSjasonliu if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) 8858e84311aSjasonliu return false; 8868e84311aSjasonliu 8878e84311aSjasonliu const int16_t SectNum = getSectionNumber(); 8888e84311aSjasonliu Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); 8898e84311aSjasonliu if (!SI) { 8908e84311aSjasonliu // If we could not get the section, then this symbol should not be 8918e84311aSjasonliu // a function. So consume the error and return `false` to move on. 8928e84311aSjasonliu consumeError(SI.takeError()); 8938e84311aSjasonliu return false; 8947c72e82bSJason Liu } 8957c72e82bSJason Liu 8968e84311aSjasonliu return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); 8977c72e82bSJason Liu } 8987c72e82bSJason Liu 8998e84311aSjasonliu bool XCOFFSymbolRef::isCsectSymbol() const { 9007c72e82bSJason Liu XCOFF::StorageClass SC = getStorageClass(); 9017c72e82bSJason Liu return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || 9027c72e82bSJason Liu SC == XCOFF::C_HIDEXT); 9037c72e82bSJason Liu } 9047c72e82bSJason Liu 9058e84311aSjasonliu Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { 9068e84311aSjasonliu assert(isCsectSymbol() && 9078e84311aSjasonliu "Calling csect symbol interface with a non-csect symbol."); 9087c72e82bSJason Liu 9098e84311aSjasonliu uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); 9107c72e82bSJason Liu 9118e84311aSjasonliu Expected<StringRef> NameOrErr = getName(); 9128e84311aSjasonliu if (auto Err = NameOrErr.takeError()) 9138e84311aSjasonliu return std::move(Err); 9147c72e82bSJason Liu 9158e84311aSjasonliu if (!NumberOfAuxEntries) { 9168e84311aSjasonliu return createStringError(object_error::parse_failed, 9178e84311aSjasonliu "csect symbol \"" + *NameOrErr + 9188e84311aSjasonliu "\" contains no auxiliary entry"); 9198e84311aSjasonliu } 9207c72e82bSJason Liu 9218e84311aSjasonliu if (!OwningObjectPtr->is64Bit()) { 9228e84311aSjasonliu // In XCOFF32, the csect auxilliary entry is always the last auxiliary 9238e84311aSjasonliu // entry for the symbol. 9248e84311aSjasonliu uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 9258e84311aSjasonliu getEntryAddress(), NumberOfAuxEntries); 9268e84311aSjasonliu return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); 9278e84311aSjasonliu } 9287c72e82bSJason Liu 9298e84311aSjasonliu // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. 9308e84311aSjasonliu // We need to iterate through all the auxiliary entries to find it. 9318e84311aSjasonliu for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { 9328e84311aSjasonliu uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 9338e84311aSjasonliu getEntryAddress(), Index); 9348e84311aSjasonliu if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) == 9358e84311aSjasonliu XCOFF::SymbolAuxType::AUX_CSECT) { 9368e84311aSjasonliu #ifndef NDEBUG 9378e84311aSjasonliu OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); 9388e84311aSjasonliu #endif 9398e84311aSjasonliu return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); 9408e84311aSjasonliu } 9418e84311aSjasonliu } 9427c72e82bSJason Liu 9438e84311aSjasonliu return createStringError( 9448e84311aSjasonliu object_error::parse_failed, 9458e84311aSjasonliu "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\""); 9468e84311aSjasonliu } 9477c72e82bSJason Liu 9488e84311aSjasonliu Expected<StringRef> XCOFFSymbolRef::getName() const { 9498e84311aSjasonliu // A storage class value with the high-order bit on indicates that the name is 9508e84311aSjasonliu // a symbolic debugger stabstring. 9518e84311aSjasonliu if (getStorageClass() & 0x80) 9528e84311aSjasonliu return StringRef("Unimplemented Debug Name"); 9538e84311aSjasonliu 9548e84311aSjasonliu if (Entry32) { 9558e84311aSjasonliu if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 9568e84311aSjasonliu return generateXCOFFFixedNameStringRef(Entry32->SymbolName); 9578e84311aSjasonliu 9588e84311aSjasonliu return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); 9598e84311aSjasonliu } 9608e84311aSjasonliu 9618e84311aSjasonliu return OwningObjectPtr->getStringTableEntry(Entry64->Offset); 962ab2eb2bfSHubert Tong } 963ab2eb2bfSHubert Tong 964f8622543SFangrui Song // Explictly instantiate template classes. 965f8622543SFangrui Song template struct XCOFFSectionHeader<XCOFFSectionHeader32>; 966f8622543SFangrui Song template struct XCOFFSectionHeader<XCOFFSectionHeader64>; 967f8622543SFangrui Song 968*2cdfd0b2SMaryam Benimmar template struct XCOFFRelocation<llvm::support::ubig32_t>; 969*2cdfd0b2SMaryam Benimmar template struct XCOFFRelocation<llvm::support::ubig64_t>; 970*2cdfd0b2SMaryam Benimmar 971*2cdfd0b2SMaryam Benimmar template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>> 972*2cdfd0b2SMaryam Benimmar llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64, 973*2cdfd0b2SMaryam Benimmar llvm::object::XCOFFRelocation64>( 974*2cdfd0b2SMaryam Benimmar llvm::object::XCOFFSectionHeader64 const &) const; 975*2cdfd0b2SMaryam Benimmar template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>> 976*2cdfd0b2SMaryam Benimmar llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32, 977*2cdfd0b2SMaryam Benimmar llvm::object::XCOFFRelocation32>( 978*2cdfd0b2SMaryam Benimmar llvm::object::XCOFFSectionHeader32 const &) const; 979*2cdfd0b2SMaryam Benimmar 9802f0d755dSdiggerlin bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { 9812f0d755dSdiggerlin if (Bytes.size() < 4) 9822f0d755dSdiggerlin return false; 9832f0d755dSdiggerlin 9842f0d755dSdiggerlin return support::endian::read32be(Bytes.data()) == 0; 9852f0d755dSdiggerlin } 9862f0d755dSdiggerlin 987ab77fa51Sdiggerlin #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) 988ab77fa51Sdiggerlin #define GETVALUEWITHMASKSHIFT(X, S) \ 989ab77fa51Sdiggerlin ((Data & (TracebackTable::X)) >> (TracebackTable::S)) 9907ed515d1Szhijian 9917ed515d1Szhijian Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) { 9927ed515d1Szhijian Error Err = Error::success(); 9937ed515d1Szhijian TBVectorExt TBTVecExt(TBvectorStrRef, Err); 9947ed515d1Szhijian if (Err) 9957ed515d1Szhijian return std::move(Err); 9967ed515d1Szhijian return TBTVecExt; 9977ed515d1Szhijian } 9987ed515d1Szhijian 9997ed515d1Szhijian TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) { 10007ed515d1Szhijian const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); 10017ed515d1Szhijian Data = support::endian::read16be(Ptr); 10027ed515d1Szhijian uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2); 10037ed515d1Szhijian unsigned ParmsNum = 10047ed515d1Szhijian GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); 10057ed515d1Szhijian 10067ed515d1Szhijian ErrorAsOutParameter EAO(&Err); 10077ed515d1Szhijian Expected<SmallString<32>> VecParmsTypeOrError = 10087ed515d1Szhijian parseVectorParmsType(VecParmsTypeValue, ParmsNum); 10097ed515d1Szhijian if (!VecParmsTypeOrError) 10107ed515d1Szhijian Err = VecParmsTypeOrError.takeError(); 10117ed515d1Szhijian else 10127ed515d1Szhijian VecParmsInfo = VecParmsTypeOrError.get(); 10137ed515d1Szhijian } 10147ed515d1Szhijian 101585177965Sdiggerlin uint8_t TBVectorExt::getNumberOfVRSaved() const { 1016ab77fa51Sdiggerlin return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); 1017ab77fa51Sdiggerlin } 1018ab77fa51Sdiggerlin 1019ab77fa51Sdiggerlin bool TBVectorExt::isVRSavedOnStack() const { 1020ab77fa51Sdiggerlin return GETVALUEWITHMASK(IsVRSavedOnStackMask); 1021ab77fa51Sdiggerlin } 1022ab77fa51Sdiggerlin 1023ab77fa51Sdiggerlin bool TBVectorExt::hasVarArgs() const { 1024ab77fa51Sdiggerlin return GETVALUEWITHMASK(HasVarArgsMask); 1025ab77fa51Sdiggerlin } 10267ed515d1Szhijian 1027ab77fa51Sdiggerlin uint8_t TBVectorExt::getNumberOfVectorParms() const { 1028ab77fa51Sdiggerlin return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, 1029ab77fa51Sdiggerlin NumberOfVectorParmsShift); 1030ab77fa51Sdiggerlin } 1031ab77fa51Sdiggerlin 1032ab77fa51Sdiggerlin bool TBVectorExt::hasVMXInstruction() const { 1033ab77fa51Sdiggerlin return GETVALUEWITHMASK(HasVMXInstructionMask); 1034ab77fa51Sdiggerlin } 1035ab77fa51Sdiggerlin #undef GETVALUEWITHMASK 1036ab77fa51Sdiggerlin #undef GETVALUEWITHMASKSHIFT 1037ab77fa51Sdiggerlin 10382f0d755dSdiggerlin Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr, 10392f0d755dSdiggerlin uint64_t &Size) { 10402f0d755dSdiggerlin Error Err = Error::success(); 10412f0d755dSdiggerlin XCOFFTracebackTable TBT(Ptr, Size, Err); 10422f0d755dSdiggerlin if (Err) 10432f0d755dSdiggerlin return std::move(Err); 10442f0d755dSdiggerlin return TBT; 10452f0d755dSdiggerlin } 10462f0d755dSdiggerlin 10472f0d755dSdiggerlin XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, 10482f0d755dSdiggerlin Error &Err) 10492f0d755dSdiggerlin : TBPtr(Ptr) { 10502f0d755dSdiggerlin ErrorAsOutParameter EAO(&Err); 10512f0d755dSdiggerlin DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false, 10522f0d755dSdiggerlin /*AddressSize=*/0); 10532f0d755dSdiggerlin DataExtractor::Cursor Cur(/*Offset=*/0); 10542f0d755dSdiggerlin 10552f0d755dSdiggerlin // Skip 8 bytes of mandatory fields. 10562f0d755dSdiggerlin DE.getU64(Cur); 10572f0d755dSdiggerlin 10587ed515d1Szhijian unsigned FixedParmsNum = getNumberOfFixedParms(); 10597ed515d1Szhijian unsigned FloatingParmsNum = getNumberOfFPParms(); 10607ed515d1Szhijian uint32_t ParamsTypeValue = 0; 10612f0d755dSdiggerlin 10627ed515d1Szhijian // Begin to parse optional fields. 10637ed515d1Szhijian if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) 10647ed515d1Szhijian ParamsTypeValue = DE.getU32(Cur); 10652f0d755dSdiggerlin 10662f0d755dSdiggerlin if (Cur && hasTraceBackTableOffset()) 10672f0d755dSdiggerlin TraceBackTableOffset = DE.getU32(Cur); 10682f0d755dSdiggerlin 10692f0d755dSdiggerlin if (Cur && isInterruptHandler()) 10702f0d755dSdiggerlin HandlerMask = DE.getU32(Cur); 10712f0d755dSdiggerlin 10722f0d755dSdiggerlin if (Cur && hasControlledStorage()) { 10732f0d755dSdiggerlin NumOfCtlAnchors = DE.getU32(Cur); 10742f0d755dSdiggerlin if (Cur && NumOfCtlAnchors) { 10752f0d755dSdiggerlin SmallVector<uint32_t, 8> Disp; 10762f0d755dSdiggerlin Disp.reserve(NumOfCtlAnchors.getValue()); 10772f0d755dSdiggerlin for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I) 10782f0d755dSdiggerlin Disp.push_back(DE.getU32(Cur)); 10792f0d755dSdiggerlin if (Cur) 10802f0d755dSdiggerlin ControlledStorageInfoDisp = std::move(Disp); 10812f0d755dSdiggerlin } 10822f0d755dSdiggerlin } 10832f0d755dSdiggerlin 10842f0d755dSdiggerlin if (Cur && isFuncNamePresent()) { 10852f0d755dSdiggerlin uint16_t FunctionNameLen = DE.getU16(Cur); 10862f0d755dSdiggerlin if (Cur) 10872f0d755dSdiggerlin FunctionName = DE.getBytes(Cur, FunctionNameLen); 10882f0d755dSdiggerlin } 10892f0d755dSdiggerlin 10902f0d755dSdiggerlin if (Cur && isAllocaUsed()) 10912f0d755dSdiggerlin AllocaRegister = DE.getU8(Cur); 10922f0d755dSdiggerlin 10937ed515d1Szhijian unsigned VectorParmsNum = 0; 1094ab77fa51Sdiggerlin if (Cur && hasVectorInfo()) { 1095ab77fa51Sdiggerlin StringRef VectorExtRef = DE.getBytes(Cur, 6); 10967ed515d1Szhijian if (Cur) { 10977ed515d1Szhijian Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef); 10987ed515d1Szhijian if (!TBVecExtOrErr) { 10997ed515d1Szhijian Err = TBVecExtOrErr.takeError(); 11007ed515d1Szhijian return; 11017ed515d1Szhijian } 11027ed515d1Szhijian VecExt = TBVecExtOrErr.get(); 11037ed515d1Szhijian VectorParmsNum = VecExt.getValue().getNumberOfVectorParms(); 11047ed515d1Szhijian } 11057ed515d1Szhijian } 11067ed515d1Szhijian 11077ed515d1Szhijian // As long as there is no fixed-point or floating-point parameter, this 11087ed515d1Szhijian // field remains not present even when hasVectorInfo gives true and 11097ed515d1Szhijian // indicates the presence of vector parameters. 11107ed515d1Szhijian if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) { 11117ed515d1Szhijian Expected<SmallString<32>> ParmsTypeOrError = 11127ed515d1Szhijian hasVectorInfo() 11137ed515d1Szhijian ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum, 11147ed515d1Szhijian FloatingParmsNum, VectorParmsNum) 11157ed515d1Szhijian : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum); 11167ed515d1Szhijian 11177ed515d1Szhijian if (!ParmsTypeOrError) { 11187ed515d1Szhijian Err = ParmsTypeOrError.takeError(); 11197ed515d1Szhijian return; 11207ed515d1Szhijian } 11217ed515d1Szhijian ParmsType = ParmsTypeOrError.get(); 1122ab77fa51Sdiggerlin } 1123ab77fa51Sdiggerlin 1124ab77fa51Sdiggerlin if (Cur && hasExtensionTable()) 1125ab77fa51Sdiggerlin ExtensionTable = DE.getU8(Cur); 11262f0d755dSdiggerlin 11272f0d755dSdiggerlin if (!Cur) 11282f0d755dSdiggerlin Err = Cur.takeError(); 11297ed515d1Szhijian 11302f0d755dSdiggerlin Size = Cur.tell(); 11312f0d755dSdiggerlin } 11322f0d755dSdiggerlin 11332f0d755dSdiggerlin #define GETBITWITHMASK(P, X) \ 11342f0d755dSdiggerlin (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) 11352f0d755dSdiggerlin #define GETBITWITHMASKSHIFT(P, X, S) \ 11362f0d755dSdiggerlin ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \ 11372f0d755dSdiggerlin (TracebackTable::S)) 11382f0d755dSdiggerlin 11392f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getVersion() const { 11402f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift); 11412f0d755dSdiggerlin } 11422f0d755dSdiggerlin 11432f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getLanguageID() const { 11442f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift); 11452f0d755dSdiggerlin } 11462f0d755dSdiggerlin 11472f0d755dSdiggerlin bool XCOFFTracebackTable::isGlobalLinkage() const { 11482f0d755dSdiggerlin return GETBITWITHMASK(0, IsGlobaLinkageMask); 11492f0d755dSdiggerlin } 11502f0d755dSdiggerlin 11512f0d755dSdiggerlin bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const { 11522f0d755dSdiggerlin return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask); 11532f0d755dSdiggerlin } 11542f0d755dSdiggerlin 11552f0d755dSdiggerlin bool XCOFFTracebackTable::hasTraceBackTableOffset() const { 11562f0d755dSdiggerlin return GETBITWITHMASK(0, HasTraceBackTableOffsetMask); 11572f0d755dSdiggerlin } 11582f0d755dSdiggerlin 11592f0d755dSdiggerlin bool XCOFFTracebackTable::isInternalProcedure() const { 11602f0d755dSdiggerlin return GETBITWITHMASK(0, IsInternalProcedureMask); 11612f0d755dSdiggerlin } 11622f0d755dSdiggerlin 11632f0d755dSdiggerlin bool XCOFFTracebackTable::hasControlledStorage() const { 11642f0d755dSdiggerlin return GETBITWITHMASK(0, HasControlledStorageMask); 11652f0d755dSdiggerlin } 11662f0d755dSdiggerlin 11672f0d755dSdiggerlin bool XCOFFTracebackTable::isTOCless() const { 11682f0d755dSdiggerlin return GETBITWITHMASK(0, IsTOClessMask); 11692f0d755dSdiggerlin } 11702f0d755dSdiggerlin 11712f0d755dSdiggerlin bool XCOFFTracebackTable::isFloatingPointPresent() const { 11722f0d755dSdiggerlin return GETBITWITHMASK(0, IsFloatingPointPresentMask); 11732f0d755dSdiggerlin } 11742f0d755dSdiggerlin 11752f0d755dSdiggerlin bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const { 11762f0d755dSdiggerlin return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask); 11772f0d755dSdiggerlin } 11782f0d755dSdiggerlin 11792f0d755dSdiggerlin bool XCOFFTracebackTable::isInterruptHandler() const { 11802f0d755dSdiggerlin return GETBITWITHMASK(0, IsInterruptHandlerMask); 11812f0d755dSdiggerlin } 11822f0d755dSdiggerlin 11832f0d755dSdiggerlin bool XCOFFTracebackTable::isFuncNamePresent() const { 11842f0d755dSdiggerlin return GETBITWITHMASK(0, IsFunctionNamePresentMask); 11852f0d755dSdiggerlin } 11862f0d755dSdiggerlin 11872f0d755dSdiggerlin bool XCOFFTracebackTable::isAllocaUsed() const { 11882f0d755dSdiggerlin return GETBITWITHMASK(0, IsAllocaUsedMask); 11892f0d755dSdiggerlin } 11902f0d755dSdiggerlin 11912f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getOnConditionDirective() const { 11922f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask, 11932f0d755dSdiggerlin OnConditionDirectiveShift); 11942f0d755dSdiggerlin } 11952f0d755dSdiggerlin 11962f0d755dSdiggerlin bool XCOFFTracebackTable::isCRSaved() const { 11972f0d755dSdiggerlin return GETBITWITHMASK(0, IsCRSavedMask); 11982f0d755dSdiggerlin } 11992f0d755dSdiggerlin 12002f0d755dSdiggerlin bool XCOFFTracebackTable::isLRSaved() const { 12012f0d755dSdiggerlin return GETBITWITHMASK(0, IsLRSavedMask); 12022f0d755dSdiggerlin } 12032f0d755dSdiggerlin 12042f0d755dSdiggerlin bool XCOFFTracebackTable::isBackChainStored() const { 12052f0d755dSdiggerlin return GETBITWITHMASK(4, IsBackChainStoredMask); 12062f0d755dSdiggerlin } 12072f0d755dSdiggerlin 12082f0d755dSdiggerlin bool XCOFFTracebackTable::isFixup() const { 12092f0d755dSdiggerlin return GETBITWITHMASK(4, IsFixupMask); 12102f0d755dSdiggerlin } 12112f0d755dSdiggerlin 12122f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const { 12132f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift); 12142f0d755dSdiggerlin } 12152f0d755dSdiggerlin 12162f0d755dSdiggerlin bool XCOFFTracebackTable::hasExtensionTable() const { 12172f0d755dSdiggerlin return GETBITWITHMASK(4, HasExtensionTableMask); 12182f0d755dSdiggerlin } 12192f0d755dSdiggerlin 12202f0d755dSdiggerlin bool XCOFFTracebackTable::hasVectorInfo() const { 12212f0d755dSdiggerlin return GETBITWITHMASK(4, HasVectorInfoMask); 12222f0d755dSdiggerlin } 12232f0d755dSdiggerlin 1224c80fbdf2Sdiggerlin uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const { 12252f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift); 12262f0d755dSdiggerlin } 12272f0d755dSdiggerlin 12282f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const { 12292f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask, 12302f0d755dSdiggerlin NumberOfFixedParmsShift); 12312f0d755dSdiggerlin } 12322f0d755dSdiggerlin 12332f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumberOfFPParms() const { 12342f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask, 12352f0d755dSdiggerlin NumberOfFloatingPointParmsShift); 12362f0d755dSdiggerlin } 12372f0d755dSdiggerlin 12382f0d755dSdiggerlin bool XCOFFTracebackTable::hasParmsOnStack() const { 12392f0d755dSdiggerlin return GETBITWITHMASK(4, HasParmsOnStackMask); 12402f0d755dSdiggerlin } 12412f0d755dSdiggerlin 12422f0d755dSdiggerlin #undef GETBITWITHMASK 12432f0d755dSdiggerlin #undef GETBITWITHMASKSHIFT 1244ab2eb2bfSHubert Tong } // namespace object 1245ab2eb2bfSHubert Tong } // namespace llvm 1246