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 722cdfd0b2SMaryam Benimmar template <typename AddressType> 732cdfd0b2SMaryam Benimmar bool XCOFFRelocation<AddressType>::isRelocationSigned() const { 7434d4bff3SDigger Lin return Info & XR_SIGN_INDICATOR_MASK; 7534d4bff3SDigger Lin } 7634d4bff3SDigger Lin 772cdfd0b2SMaryam Benimmar template <typename AddressType> 782cdfd0b2SMaryam Benimmar bool XCOFFRelocation<AddressType>::isFixupIndicated() const { 7934d4bff3SDigger Lin return Info & XR_FIXUP_INDICATOR_MASK; 8034d4bff3SDigger Lin } 8134d4bff3SDigger Lin 822cdfd0b2SMaryam Benimmar template <typename AddressType> 832cdfd0b2SMaryam 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 1522cdfd0b2SMaryam Benimmar template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const { 1532cdfd0b2SMaryam Benimmar return static_cast<const T *>(SectionHeaderTable); 1542cdfd0b2SMaryam Benimmar } 1552cdfd0b2SMaryam 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); 298*ea81898dSEsme-Yi if (Error E = Binary::checkOffset( 299*ea81898dSEsme-Yi Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize)) 300*ea81898dSEsme-Yi return std::move(E); 301b91f798fSdiggerlin 302b91f798fSdiggerlin return makeArrayRef(ContentStart,SectionSize); 303ab2eb2bfSHubert Tong } 304ab2eb2bfSHubert Tong 305ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 306ab2eb2bfSHubert Tong uint64_t Result = 0; 307ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 308ab2eb2bfSHubert Tong return Result; 309ab2eb2bfSHubert Tong } 310ab2eb2bfSHubert Tong 311b21ed75eSEsme-Yi Expected<uintptr_t> XCOFFObjectFile::getLoaderSectionAddress() const { 312b21ed75eSEsme-Yi uint64_t OffsetToLoaderSection = 0; 313b21ed75eSEsme-Yi uint64_t SizeOfLoaderSection = 0; 314b21ed75eSEsme-Yi 315b21ed75eSEsme-Yi if (is64Bit()) { 316b21ed75eSEsme-Yi for (const auto &Sec64 : sections64()) 317b21ed75eSEsme-Yi if (Sec64.getSectionType() == XCOFF::STYP_LOADER) { 318b21ed75eSEsme-Yi OffsetToLoaderSection = Sec64.FileOffsetToRawData; 319b21ed75eSEsme-Yi SizeOfLoaderSection = Sec64.SectionSize; 320b21ed75eSEsme-Yi break; 321b21ed75eSEsme-Yi } 322b21ed75eSEsme-Yi } else { 323b21ed75eSEsme-Yi for (const auto &Sec32 : sections32()) 324b21ed75eSEsme-Yi if (Sec32.getSectionType() == XCOFF::STYP_LOADER) { 325b21ed75eSEsme-Yi OffsetToLoaderSection = Sec32.FileOffsetToRawData; 326b21ed75eSEsme-Yi SizeOfLoaderSection = Sec32.SectionSize; 327b21ed75eSEsme-Yi break; 328b21ed75eSEsme-Yi } 329b21ed75eSEsme-Yi } 330b21ed75eSEsme-Yi 331b21ed75eSEsme-Yi // No loader section is not an error. 332b21ed75eSEsme-Yi if (!SizeOfLoaderSection) 333b21ed75eSEsme-Yi return 0; 334b21ed75eSEsme-Yi 335b21ed75eSEsme-Yi uintptr_t LoderSectionStart = 336b21ed75eSEsme-Yi reinterpret_cast<uintptr_t>(base() + OffsetToLoaderSection); 337b21ed75eSEsme-Yi if (Error E = 338b21ed75eSEsme-Yi Binary::checkOffset(Data, LoderSectionStart, SizeOfLoaderSection)) 339b21ed75eSEsme-Yi return std::move(E); 340b21ed75eSEsme-Yi return LoderSectionStart; 341b21ed75eSEsme-Yi } 342b21ed75eSEsme-Yi 343ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 344d33b016aSChen Zheng return false; 345ab2eb2bfSHubert Tong } 346ab2eb2bfSHubert Tong 347ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { 348837ae69fSSean Fertile return getSectionFlags(Sec) & XCOFF::STYP_TEXT; 349ab2eb2bfSHubert Tong } 350ab2eb2bfSHubert Tong 351ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { 352837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec); 353a93a33cbSSean Fertile return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); 354ab2eb2bfSHubert Tong } 355ab2eb2bfSHubert Tong 356ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { 357837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec); 358a93a33cbSSean Fertile return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); 359ab2eb2bfSHubert Tong } 360ab2eb2bfSHubert Tong 361c8e980abSEsme-Yi bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const { 362c8e980abSEsme-Yi uint32_t Flags = getSectionFlags(Sec); 363c8e980abSEsme-Yi return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF); 364c8e980abSEsme-Yi } 365c8e980abSEsme-Yi 366ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { 367b91f798fSdiggerlin return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0 368b91f798fSdiggerlin : toSection32(Sec)->FileOffsetToRawData == 0; 369ab2eb2bfSHubert Tong } 370ab2eb2bfSHubert Tong 371ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 372d60d7d69Sjasonliu DataRefImpl Ret; 3732cdfd0b2SMaryam Benimmar if (is64Bit()) { 3742cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); 3752cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 3762cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); 3772cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 3782cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 3792cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 3802cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 3812cdfd0b2SMaryam Benimmar } 382d60d7d69Sjasonliu Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); 3832cdfd0b2SMaryam Benimmar } else { 3842cdfd0b2SMaryam Benimmar const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 3852cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 3862cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); 3872cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 3882cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 3892cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 3902cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 3912cdfd0b2SMaryam Benimmar } 3922cdfd0b2SMaryam Benimmar Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); 3932cdfd0b2SMaryam Benimmar } 394d60d7d69Sjasonliu return relocation_iterator(RelocationRef(Ret, this)); 395ab2eb2bfSHubert Tong } 396ab2eb2bfSHubert Tong 397ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { 398d60d7d69Sjasonliu DataRefImpl Ret; 3992cdfd0b2SMaryam Benimmar if (is64Bit()) { 4002cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); 4012cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 4022cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); 4032cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 4042cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 4052cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 4062cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 4072cdfd0b2SMaryam Benimmar } 408d60d7d69Sjasonliu Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); 4092cdfd0b2SMaryam Benimmar } else { 4102cdfd0b2SMaryam Benimmar const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 4112cdfd0b2SMaryam Benimmar auto RelocationsOrErr = 4122cdfd0b2SMaryam Benimmar relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); 4132cdfd0b2SMaryam Benimmar if (Error E = RelocationsOrErr.takeError()) { 4142cdfd0b2SMaryam Benimmar // TODO: report the error up the stack. 4152cdfd0b2SMaryam Benimmar consumeError(std::move(E)); 4162cdfd0b2SMaryam Benimmar return relocation_iterator(RelocationRef()); 4172cdfd0b2SMaryam Benimmar } 4182cdfd0b2SMaryam Benimmar Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); 4192cdfd0b2SMaryam Benimmar } 420d60d7d69Sjasonliu return relocation_iterator(RelocationRef(Ret, this)); 421ab2eb2bfSHubert Tong } 422ab2eb2bfSHubert Tong 423ab2eb2bfSHubert Tong void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 4242cdfd0b2SMaryam Benimmar if (is64Bit()) 4252cdfd0b2SMaryam Benimmar Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1); 4262cdfd0b2SMaryam Benimmar else 427d60d7d69Sjasonliu Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); 428ab2eb2bfSHubert Tong } 429ab2eb2bfSHubert Tong 430ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 4312cdfd0b2SMaryam Benimmar if (is64Bit()) { 4322cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 4332cdfd0b2SMaryam Benimmar const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64(); 4342cdfd0b2SMaryam Benimmar const uint64_t RelocAddress = Reloc->VirtualAddress; 4352cdfd0b2SMaryam Benimmar const uint16_t NumberOfSections = getNumberOfSections(); 4362cdfd0b2SMaryam Benimmar for (uint16_t I = 0; I < NumberOfSections; ++I) { 4372cdfd0b2SMaryam Benimmar // Find which section this relocation belongs to, and get the 4382cdfd0b2SMaryam Benimmar // relocation offset relative to the start of the section. 4392cdfd0b2SMaryam Benimmar if (Sec64->VirtualAddress <= RelocAddress && 4402cdfd0b2SMaryam Benimmar RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) { 4412cdfd0b2SMaryam Benimmar return RelocAddress - Sec64->VirtualAddress; 4422cdfd0b2SMaryam Benimmar } 4432cdfd0b2SMaryam Benimmar ++Sec64; 4442cdfd0b2SMaryam Benimmar } 4452cdfd0b2SMaryam Benimmar } else { 446d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 447d60d7d69Sjasonliu const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); 448d60d7d69Sjasonliu const uint32_t RelocAddress = Reloc->VirtualAddress; 449d60d7d69Sjasonliu const uint16_t NumberOfSections = getNumberOfSections(); 4502cdfd0b2SMaryam Benimmar for (uint16_t I = 0; I < NumberOfSections; ++I) { 4512cdfd0b2SMaryam Benimmar // Find which section this relocation belongs to, and get the 452d60d7d69Sjasonliu // relocation offset relative to the start of the section. 453d60d7d69Sjasonliu if (Sec32->VirtualAddress <= RelocAddress && 454d60d7d69Sjasonliu RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { 455d60d7d69Sjasonliu return RelocAddress - Sec32->VirtualAddress; 456d60d7d69Sjasonliu } 457d60d7d69Sjasonliu ++Sec32; 458d60d7d69Sjasonliu } 4592cdfd0b2SMaryam Benimmar } 460d60d7d69Sjasonliu return InvalidRelocOffset; 461ab2eb2bfSHubert Tong } 462ab2eb2bfSHubert Tong 463ab2eb2bfSHubert Tong symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 4642cdfd0b2SMaryam Benimmar uint32_t Index; 4652cdfd0b2SMaryam Benimmar if (is64Bit()) { 4662cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 4672cdfd0b2SMaryam Benimmar Index = Reloc->SymbolIndex; 4682cdfd0b2SMaryam Benimmar 4692cdfd0b2SMaryam Benimmar if (Index >= getNumberOfSymbolTableEntries64()) 4702cdfd0b2SMaryam Benimmar return symbol_end(); 4712cdfd0b2SMaryam Benimmar } else { 472d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 4732cdfd0b2SMaryam Benimmar Index = Reloc->SymbolIndex; 474d60d7d69Sjasonliu 475d60d7d69Sjasonliu if (Index >= getLogicalNumberOfSymbolTableEntries32()) 476d60d7d69Sjasonliu return symbol_end(); 4772cdfd0b2SMaryam Benimmar } 478d60d7d69Sjasonliu DataRefImpl SymDRI; 4798e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(Index); 480d60d7d69Sjasonliu return symbol_iterator(SymbolRef(SymDRI, this)); 481ab2eb2bfSHubert Tong } 482ab2eb2bfSHubert Tong 483ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { 484d60d7d69Sjasonliu if (is64Bit()) 4852cdfd0b2SMaryam Benimmar return viewAs<XCOFFRelocation64>(Rel.p)->Type; 486d60d7d69Sjasonliu return viewAs<XCOFFRelocation32>(Rel.p)->Type; 487ab2eb2bfSHubert Tong } 488ab2eb2bfSHubert Tong 489ab2eb2bfSHubert Tong void XCOFFObjectFile::getRelocationTypeName( 490ab2eb2bfSHubert Tong DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 4912cdfd0b2SMaryam Benimmar StringRef Res; 4922cdfd0b2SMaryam Benimmar if (is64Bit()) { 4932cdfd0b2SMaryam Benimmar const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 4942cdfd0b2SMaryam Benimmar Res = XCOFF::getRelocationTypeString(Reloc->Type); 4952cdfd0b2SMaryam Benimmar } else { 496d60d7d69Sjasonliu const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 4972cdfd0b2SMaryam Benimmar Res = XCOFF::getRelocationTypeString(Reloc->Type); 4982cdfd0b2SMaryam Benimmar } 499d60d7d69Sjasonliu Result.append(Res.begin(), Res.end()); 500ab2eb2bfSHubert Tong } 501ab2eb2bfSHubert Tong 502ac00376aSvgxbj Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 503ab2eb2bfSHubert Tong uint32_t Result = 0; 5048a23f74eSEsme-Yi // TODO: Return correct symbol flags. 505ab2eb2bfSHubert Tong return Result; 506ab2eb2bfSHubert Tong } 507ab2eb2bfSHubert Tong 508ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { 5099212206dSJason Liu DataRefImpl SymDRI; 5109212206dSJason Liu SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); 5119212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this)); 512ab2eb2bfSHubert Tong } 513ab2eb2bfSHubert Tong 514ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_end() const { 5159212206dSJason Liu DataRefImpl SymDRI; 5168e84311aSjasonliu const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries(); 5178e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries); 5189212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this)); 519ab2eb2bfSHubert Tong } 520ab2eb2bfSHubert Tong 521ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_begin() const { 522a93a33cbSSean Fertile DataRefImpl DRI; 523837ae69fSSean Fertile DRI.p = getSectionHeaderTableAddress(); 524a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this)); 525ab2eb2bfSHubert Tong } 526ab2eb2bfSHubert Tong 527ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_end() const { 528a93a33cbSSean Fertile DataRefImpl DRI; 529837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(), 530837ae69fSSean Fertile getNumberOfSections() * getSectionHeaderSize()); 531a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this)); 532ab2eb2bfSHubert Tong } 533ab2eb2bfSHubert Tong 534837ae69fSSean Fertile uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } 535ab2eb2bfSHubert Tong 536ab2eb2bfSHubert Tong StringRef XCOFFObjectFile::getFileFormatName() const { 537837ae69fSSean Fertile return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; 538ab2eb2bfSHubert Tong } 539ab2eb2bfSHubert Tong 540ab2eb2bfSHubert Tong Triple::ArchType XCOFFObjectFile::getArch() const { 541837ae69fSSean Fertile return is64Bit() ? Triple::ppc64 : Triple::ppc; 542ab2eb2bfSHubert Tong } 543ab2eb2bfSHubert Tong 544ab2eb2bfSHubert Tong SubtargetFeatures XCOFFObjectFile::getFeatures() const { 545ab2eb2bfSHubert Tong return SubtargetFeatures(); 546ab2eb2bfSHubert Tong } 547ab2eb2bfSHubert Tong 548ab2eb2bfSHubert Tong bool XCOFFObjectFile::isRelocatableObject() const { 549d60d7d69Sjasonliu if (is64Bit()) 5508ec73e96SAmir Ayupov return !(fileHeader64()->Flags & NoRelMask); 551d60d7d69Sjasonliu return !(fileHeader32()->Flags & NoRelMask); 552ab2eb2bfSHubert Tong } 553ab2eb2bfSHubert Tong 554a93a33cbSSean Fertile Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { 555a93a33cbSSean Fertile // TODO FIXME Should get from auxiliary_header->o_entry when support for the 556a93a33cbSSean Fertile // auxiliary_header is added. 557a93a33cbSSean Fertile return 0; 558a93a33cbSSean Fertile } 559a93a33cbSSean Fertile 560d33b016aSChen Zheng StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const { 561d33b016aSChen Zheng return StringSwitch<StringRef>(Name) 562d33b016aSChen Zheng .Case("dwinfo", "debug_info") 563d33b016aSChen Zheng .Case("dwline", "debug_line") 564d33b016aSChen Zheng .Case("dwpbnms", "debug_pubnames") 565d33b016aSChen Zheng .Case("dwpbtyp", "debug_pubtypes") 566d33b016aSChen Zheng .Case("dwarnge", "debug_aranges") 567d33b016aSChen Zheng .Case("dwabrev", "debug_abbrev") 568d33b016aSChen Zheng .Case("dwstr", "debug_str") 569d33b016aSChen Zheng .Case("dwrnges", "debug_ranges") 570d33b016aSChen Zheng .Case("dwloc", "debug_loc") 571d33b016aSChen Zheng .Case("dwframe", "debug_frame") 572d33b016aSChen Zheng .Case("dwmac", "debug_macinfo") 573d33b016aSChen Zheng .Default(Name); 574d33b016aSChen Zheng } 575d33b016aSChen Zheng 576837ae69fSSean Fertile size_t XCOFFObjectFile::getFileHeaderSize() const { 577837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); 5789212206dSJason Liu } 5799212206dSJason Liu 580837ae69fSSean Fertile size_t XCOFFObjectFile::getSectionHeaderSize() const { 581837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFSectionHeader64) : 582837ae69fSSean Fertile sizeof(XCOFFSectionHeader32); 583837ae69fSSean Fertile } 584837ae69fSSean Fertile 585837ae69fSSean Fertile bool XCOFFObjectFile::is64Bit() const { 586837ae69fSSean Fertile return Binary::ID_XCOFF64 == getType(); 587837ae69fSSean Fertile } 588837ae69fSSean Fertile 589837ae69fSSean Fertile uint16_t XCOFFObjectFile::getMagic() const { 590837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; 591837ae69fSSean Fertile } 592837ae69fSSean Fertile 593837ae69fSSean Fertile Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { 594837ae69fSSean Fertile if (Num <= 0 || Num > getNumberOfSections()) 595837ae69fSSean Fertile return errorCodeToError(object_error::invalid_section_index); 596837ae69fSSean Fertile 597837ae69fSSean Fertile DataRefImpl DRI; 598837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(), 599837ae69fSSean Fertile getSectionHeaderSize() * (Num - 1)); 600837ae69fSSean Fertile return DRI; 6019212206dSJason Liu } 6029212206dSJason Liu 6039212206dSJason Liu Expected<StringRef> 6048e84311aSjasonliu XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { 6058e84311aSjasonliu const int16_t SectionNum = SymEntPtr.getSectionNumber(); 6069212206dSJason Liu 6079212206dSJason Liu switch (SectionNum) { 6089212206dSJason Liu case XCOFF::N_DEBUG: 6099212206dSJason Liu return "N_DEBUG"; 6109212206dSJason Liu case XCOFF::N_ABS: 6119212206dSJason Liu return "N_ABS"; 6129212206dSJason Liu case XCOFF::N_UNDEF: 6139212206dSJason Liu return "N_UNDEF"; 614837ae69fSSean Fertile default: 615837ae69fSSean Fertile Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); 616837ae69fSSean Fertile if (SecRef) 6177c72e82bSJason Liu return generateXCOFFFixedNameStringRef( 6187c72e82bSJason Liu getSectionNameInternal(SecRef.get())); 619837ae69fSSean Fertile return SecRef.takeError(); 6209212206dSJason Liu } 6219212206dSJason Liu } 6229212206dSJason Liu 6238a23f74eSEsme-Yi unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 6248a23f74eSEsme-Yi XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this); 6258a23f74eSEsme-Yi return XCOFFSymRef.getSectionNumber(); 6268a23f74eSEsme-Yi } 6278a23f74eSEsme-Yi 6289212206dSJason Liu bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 6299212206dSJason Liu return (SectionNumber <= 0 && SectionNumber >= -2); 6309212206dSJason Liu } 6319212206dSJason Liu 6329212206dSJason Liu uint16_t XCOFFObjectFile::getNumberOfSections() const { 633837ae69fSSean Fertile return is64Bit() ? fileHeader64()->NumberOfSections 634837ae69fSSean Fertile : fileHeader32()->NumberOfSections; 6359212206dSJason Liu } 6369212206dSJason Liu 637837ae69fSSean Fertile int32_t XCOFFObjectFile::getTimeStamp() const { 638837ae69fSSean Fertile return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 6399212206dSJason Liu } 6409212206dSJason Liu 6419212206dSJason Liu uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 642837ae69fSSean Fertile return is64Bit() ? fileHeader64()->AuxHeaderSize 643837ae69fSSean Fertile : fileHeader32()->AuxHeaderSize; 6449212206dSJason Liu } 6459212206dSJason Liu 646837ae69fSSean Fertile uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 647837ae69fSSean Fertile return fileHeader32()->SymbolTableOffset; 648837ae69fSSean Fertile } 649ab2eb2bfSHubert Tong 650837ae69fSSean Fertile int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 651837ae69fSSean Fertile // As far as symbol table size is concerned, if this field is negative it is 652837ae69fSSean Fertile // to be treated as a 0. However since this field is also used for printing we 653837ae69fSSean Fertile // don't want to truncate any negative values. 654837ae69fSSean Fertile return fileHeader32()->NumberOfSymTableEntries; 655837ae69fSSean Fertile } 656ab2eb2bfSHubert Tong 657837ae69fSSean Fertile uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 658837ae69fSSean Fertile return (fileHeader32()->NumberOfSymTableEntries >= 0 659837ae69fSSean Fertile ? fileHeader32()->NumberOfSymTableEntries 660837ae69fSSean Fertile : 0); 661837ae69fSSean Fertile } 662a93a33cbSSean Fertile 663837ae69fSSean Fertile uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 664837ae69fSSean Fertile return fileHeader64()->SymbolTableOffset; 665837ae69fSSean Fertile } 666837ae69fSSean Fertile 667837ae69fSSean Fertile uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 668837ae69fSSean Fertile return fileHeader64()->NumberOfSymTableEntries; 669837ae69fSSean Fertile } 670837ae69fSSean Fertile 6718e84311aSjasonliu uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { 6728e84311aSjasonliu return is64Bit() ? getNumberOfSymbolTableEntries64() 6737c72e82bSJason Liu : getLogicalNumberOfSymbolTableEntries32(); 6748e84311aSjasonliu } 6758e84311aSjasonliu 6768e84311aSjasonliu uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { 6778e84311aSjasonliu const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 6787c72e82bSJason Liu return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), 6797c72e82bSJason Liu XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); 6807c72e82bSJason Liu } 6817c72e82bSJason Liu 6827c72e82bSJason Liu void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { 6837c72e82bSJason Liu if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) 6847c72e82bSJason Liu report_fatal_error("Symbol table entry is outside of symbol table."); 6857c72e82bSJason Liu 6867c72e82bSJason Liu if (SymbolEntPtr >= getEndOfSymbolTableAddress()) 6877c72e82bSJason Liu report_fatal_error("Symbol table entry is outside of symbol table."); 6887c72e82bSJason Liu 6897c72e82bSJason Liu ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - 6907c72e82bSJason Liu reinterpret_cast<const char *>(SymbolTblPtr); 6917c72e82bSJason Liu 6927c72e82bSJason Liu if (Offset % XCOFF::SymbolTableEntrySize != 0) 6937c72e82bSJason Liu report_fatal_error( 6947c72e82bSJason Liu "Symbol table entry position is not valid inside of symbol table."); 6957c72e82bSJason Liu } 6967c72e82bSJason Liu 6977c72e82bSJason Liu uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { 6987c72e82bSJason Liu return (reinterpret_cast<const char *>(SymbolEntPtr) - 6997c72e82bSJason Liu reinterpret_cast<const char *>(SymbolTblPtr)) / 7007c72e82bSJason Liu XCOFF::SymbolTableEntrySize; 7017c72e82bSJason Liu } 7027c72e82bSJason Liu 7038e84311aSjasonliu uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { 7048e84311aSjasonliu return getAdvancedSymbolEntryAddress( 7058e84311aSjasonliu reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); 7068e84311aSjasonliu } 7078e84311aSjasonliu 70834d4bff3SDigger Lin Expected<StringRef> 70934d4bff3SDigger Lin XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { 7108e84311aSjasonliu const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 71134d4bff3SDigger Lin 7128e84311aSjasonliu if (Index >= NumberOfSymTableEntries) 71334d4bff3SDigger Lin return errorCodeToError(object_error::invalid_symbol_index); 71434d4bff3SDigger Lin 71534d4bff3SDigger Lin DataRefImpl SymDRI; 7168e84311aSjasonliu SymDRI.p = getSymbolEntryAddressByIndex(Index); 71734d4bff3SDigger Lin return getSymbolName(SymDRI); 71834d4bff3SDigger Lin } 71934d4bff3SDigger Lin 720837ae69fSSean Fertile uint16_t XCOFFObjectFile::getFlags() const { 721837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 722837ae69fSSean Fertile } 723837ae69fSSean Fertile 724837ae69fSSean Fertile const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 725837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 726837ae69fSSean Fertile } 727837ae69fSSean Fertile 728837ae69fSSean Fertile uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 729837ae69fSSean Fertile return reinterpret_cast<uintptr_t>(SectionHeaderTable); 730837ae69fSSean Fertile } 731837ae69fSSean Fertile 732837ae69fSSean Fertile int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 733837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 734837ae69fSSean Fertile } 735837ae69fSSean Fertile 736837ae69fSSean Fertile XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 737837ae69fSSean Fertile : ObjectFile(Type, Object) { 738837ae69fSSean Fertile assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 739837ae69fSSean Fertile } 740837ae69fSSean Fertile 741837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 742837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called for non 64-bit file."); 743837ae69fSSean Fertile const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 744837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader64>(TablePtr, 745837ae69fSSean Fertile TablePtr + getNumberOfSections()); 746837ae69fSSean Fertile } 747837ae69fSSean Fertile 748837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 749837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 750837ae69fSSean Fertile const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 751837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader32>(TablePtr, 752837ae69fSSean Fertile TablePtr + getNumberOfSections()); 753837ae69fSSean Fertile } 754837ae69fSSean Fertile 75534d4bff3SDigger Lin // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO 75634d4bff3SDigger Lin // section header contains the actual count of relocation entries in the s_paddr 75734d4bff3SDigger Lin // field. STYP_OVRFLO headers contain the section index of their corresponding 75834d4bff3SDigger Lin // sections as their raw "NumberOfRelocations" field value. 7592cdfd0b2SMaryam Benimmar template <typename T> 7602cdfd0b2SMaryam Benimmar Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries( 7612cdfd0b2SMaryam Benimmar const XCOFFSectionHeader<T> &Sec) const { 7622cdfd0b2SMaryam Benimmar const T &Section = static_cast<const T &>(Sec); 7632cdfd0b2SMaryam Benimmar if (is64Bit()) 7642cdfd0b2SMaryam Benimmar return Section.NumberOfRelocations; 76534d4bff3SDigger Lin 7662cdfd0b2SMaryam Benimmar uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1; 7672cdfd0b2SMaryam Benimmar if (Section.NumberOfRelocations < XCOFF::RelocOverflow) 7682cdfd0b2SMaryam Benimmar return Section.NumberOfRelocations; 76934d4bff3SDigger Lin for (const auto &Sec : sections32()) { 77034d4bff3SDigger Lin if (Sec.Flags == XCOFF::STYP_OVRFLO && 77134d4bff3SDigger Lin Sec.NumberOfRelocations == SectionIndex) 77234d4bff3SDigger Lin return Sec.PhysicalAddress; 77334d4bff3SDigger Lin } 77434d4bff3SDigger Lin return errorCodeToError(object_error::parse_failed); 77534d4bff3SDigger Lin } 77634d4bff3SDigger Lin 7772cdfd0b2SMaryam Benimmar template <typename Shdr, typename Reloc> 7782cdfd0b2SMaryam Benimmar Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const { 77934d4bff3SDigger Lin uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), 78034d4bff3SDigger Lin Sec.FileOffsetToRelocationInfo); 7812cdfd0b2SMaryam Benimmar auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec); 78234d4bff3SDigger Lin if (Error E = NumRelocEntriesOrErr.takeError()) 783c55cf4afSBill Wendling return std::move(E); 78434d4bff3SDigger Lin 78534d4bff3SDigger Lin uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); 7862cdfd0b2SMaryam Benimmar static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 || 7872cdfd0b2SMaryam Benimmar sizeof(Reloc) == XCOFF::RelocationSerializationSize32), 7882cdfd0b2SMaryam Benimmar "Relocation structure is incorrect"); 78934d4bff3SDigger Lin auto RelocationOrErr = 7902cdfd0b2SMaryam Benimmar getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr), 7912cdfd0b2SMaryam Benimmar NumRelocEntries * sizeof(Reloc)); 79234d4bff3SDigger Lin if (Error E = RelocationOrErr.takeError()) 793c55cf4afSBill Wendling return std::move(E); 79434d4bff3SDigger Lin 7952cdfd0b2SMaryam Benimmar const Reloc *StartReloc = RelocationOrErr.get(); 79634d4bff3SDigger Lin 7972cdfd0b2SMaryam Benimmar return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries); 79834d4bff3SDigger Lin } 79934d4bff3SDigger Lin 800837ae69fSSean Fertile Expected<XCOFFStringTable> 801837ae69fSSean Fertile XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 802837ae69fSSean Fertile // If there is a string table, then the buffer must contain at least 4 bytes 803837ae69fSSean Fertile // for the string table's size. Not having a string table is not an error. 804e03a135bSReid Kleckner if (Error E = Binary::checkOffset( 805e03a135bSReid Kleckner Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { 806e03a135bSReid Kleckner consumeError(std::move(E)); 807837ae69fSSean Fertile return XCOFFStringTable{0, nullptr}; 808e03a135bSReid Kleckner } 809837ae69fSSean Fertile 810837ae69fSSean Fertile // Read the size out of the buffer. 811837ae69fSSean Fertile uint32_t Size = support::endian::read32be(Obj->base() + Offset); 812837ae69fSSean Fertile 813837ae69fSSean Fertile // If the size is less then 4, then the string table is just a size and no 814837ae69fSSean Fertile // string data. 815837ae69fSSean Fertile if (Size <= 4) 816837ae69fSSean Fertile return XCOFFStringTable{4, nullptr}; 817837ae69fSSean Fertile 818837ae69fSSean Fertile auto StringTableOrErr = 819837ae69fSSean Fertile getObject<char>(Obj->Data, Obj->base() + Offset, Size); 820837ae69fSSean Fertile if (Error E = StringTableOrErr.takeError()) 821c55cf4afSBill Wendling return std::move(E); 822837ae69fSSean Fertile 823837ae69fSSean Fertile const char *StringTablePtr = StringTableOrErr.get(); 824837ae69fSSean Fertile if (StringTablePtr[Size - 1] != '\0') 825837ae69fSSean Fertile return errorCodeToError(object_error::string_table_non_null_end); 826837ae69fSSean Fertile 827837ae69fSSean Fertile return XCOFFStringTable{Size, StringTablePtr}; 828837ae69fSSean Fertile } 829837ae69fSSean Fertile 830b21ed75eSEsme-Yi // This function returns the import file table. Each entry in the import file 831b21ed75eSEsme-Yi // table consists of: "path_name\0base_name\0archive_member_name\0". 832b21ed75eSEsme-Yi Expected<StringRef> XCOFFObjectFile::getImportFileTable() const { 833b21ed75eSEsme-Yi Expected<uintptr_t> LoaderSectionAddrOrError = getLoaderSectionAddress(); 834b21ed75eSEsme-Yi if (!LoaderSectionAddrOrError) 835b21ed75eSEsme-Yi return LoaderSectionAddrOrError.takeError(); 836b21ed75eSEsme-Yi 837b21ed75eSEsme-Yi uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); 838b21ed75eSEsme-Yi if (!LoaderSectionAddr) 839b21ed75eSEsme-Yi return StringRef(); 840b21ed75eSEsme-Yi 841b21ed75eSEsme-Yi uint64_t OffsetToImportFileTable = 0; 842b21ed75eSEsme-Yi uint64_t LengthOfImportFileTable = 0; 843b21ed75eSEsme-Yi if (is64Bit()) { 844b21ed75eSEsme-Yi const LoaderSectionHeader64 *LoaderSec64 = 845b21ed75eSEsme-Yi viewAs<LoaderSectionHeader64>(LoaderSectionAddr); 846b21ed75eSEsme-Yi OffsetToImportFileTable = LoaderSec64->OffsetToImpid; 847b21ed75eSEsme-Yi LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl; 848b21ed75eSEsme-Yi } else { 849b21ed75eSEsme-Yi const LoaderSectionHeader32 *LoaderSec32 = 850b21ed75eSEsme-Yi viewAs<LoaderSectionHeader32>(LoaderSectionAddr); 851b21ed75eSEsme-Yi OffsetToImportFileTable = LoaderSec32->OffsetToImpid; 852b21ed75eSEsme-Yi LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl; 853b21ed75eSEsme-Yi } 854b21ed75eSEsme-Yi 855b21ed75eSEsme-Yi auto ImportTableOrErr = getObject<char>( 856b21ed75eSEsme-Yi Data, 857b21ed75eSEsme-Yi reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable), 858b21ed75eSEsme-Yi LengthOfImportFileTable); 859b21ed75eSEsme-Yi if (Error E = ImportTableOrErr.takeError()) 860b21ed75eSEsme-Yi return std::move(E); 861b21ed75eSEsme-Yi 862b21ed75eSEsme-Yi const char *ImportTablePtr = ImportTableOrErr.get(); 863b21ed75eSEsme-Yi if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0') 864b21ed75eSEsme-Yi return createStringError( 865b21ed75eSEsme-Yi object_error::parse_failed, 866b21ed75eSEsme-Yi "the import file table must end with a null terminator"); 867b21ed75eSEsme-Yi 868b21ed75eSEsme-Yi return StringRef(ImportTablePtr, LengthOfImportFileTable); 869b21ed75eSEsme-Yi } 870b21ed75eSEsme-Yi 871837ae69fSSean Fertile Expected<std::unique_ptr<XCOFFObjectFile>> 872837ae69fSSean Fertile XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 8730eaee545SJonas Devlieghere // Can't use std::make_unique because of the private constructor. 874837ae69fSSean Fertile std::unique_ptr<XCOFFObjectFile> Obj; 875837ae69fSSean Fertile Obj.reset(new XCOFFObjectFile(Type, MBR)); 876837ae69fSSean Fertile 877837ae69fSSean Fertile uint64_t CurOffset = 0; 878837ae69fSSean Fertile const auto *Base = Obj->base(); 879837ae69fSSean Fertile MemoryBufferRef Data = Obj->Data; 880837ae69fSSean Fertile 881837ae69fSSean Fertile // Parse file header. 882837ae69fSSean Fertile auto FileHeaderOrErr = 883837ae69fSSean Fertile getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 884837ae69fSSean Fertile if (Error E = FileHeaderOrErr.takeError()) 885c55cf4afSBill Wendling return std::move(E); 886837ae69fSSean Fertile Obj->FileHeader = FileHeaderOrErr.get(); 887837ae69fSSean Fertile 888837ae69fSSean Fertile CurOffset += Obj->getFileHeaderSize(); 889a93a33cbSSean Fertile // TODO FIXME we don't have support for an optional header yet, so just skip 890a93a33cbSSean Fertile // past it. 891837ae69fSSean Fertile CurOffset += Obj->getOptionalHeaderSize(); 892a93a33cbSSean Fertile 893837ae69fSSean Fertile // Parse the section header table if it is present. 894837ae69fSSean Fertile if (Obj->getNumberOfSections()) { 895837ae69fSSean Fertile auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, 896837ae69fSSean Fertile Obj->getNumberOfSections() * 897837ae69fSSean Fertile Obj->getSectionHeaderSize()); 898837ae69fSSean Fertile if (Error E = SecHeadersOrErr.takeError()) 899c55cf4afSBill Wendling return std::move(E); 900837ae69fSSean Fertile Obj->SectionHeaderTable = SecHeadersOrErr.get(); 901a93a33cbSSean Fertile } 902ab2eb2bfSHubert Tong 9038e84311aSjasonliu const uint32_t NumberOfSymbolTableEntries = 9048e84311aSjasonliu Obj->getNumberOfSymbolTableEntries(); 905fd75ee91SSean Fertile 906837ae69fSSean Fertile // If there is no symbol table we are done parsing the memory buffer. 9078e84311aSjasonliu if (NumberOfSymbolTableEntries == 0) 908c55cf4afSBill Wendling return std::move(Obj); 909837ae69fSSean Fertile 910837ae69fSSean Fertile // Parse symbol table. 9118e84311aSjasonliu CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() 9128e84311aSjasonliu : Obj->getSymbolTableOffset32(); 9138e84311aSjasonliu const uint64_t SymbolTableSize = 9148e84311aSjasonliu static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * 9158e84311aSjasonliu NumberOfSymbolTableEntries; 916837ae69fSSean Fertile auto SymTableOrErr = 9178e84311aSjasonliu getObject<void *>(Data, Base + CurOffset, SymbolTableSize); 918837ae69fSSean Fertile if (Error E = SymTableOrErr.takeError()) 919c55cf4afSBill Wendling return std::move(E); 920837ae69fSSean Fertile Obj->SymbolTblPtr = SymTableOrErr.get(); 921837ae69fSSean Fertile CurOffset += SymbolTableSize; 922fd75ee91SSean Fertile 923837ae69fSSean Fertile // Parse String table. 924837ae69fSSean Fertile Expected<XCOFFStringTable> StringTableOrErr = 925837ae69fSSean Fertile parseStringTable(Obj.get(), CurOffset); 926837ae69fSSean Fertile if (Error E = StringTableOrErr.takeError()) 927c55cf4afSBill Wendling return std::move(E); 928837ae69fSSean Fertile Obj->StringTable = StringTableOrErr.get(); 929fd75ee91SSean Fertile 930c55cf4afSBill Wendling return std::move(Obj); 931fd75ee91SSean Fertile } 932fd75ee91SSean Fertile 933ab2eb2bfSHubert Tong Expected<std::unique_ptr<ObjectFile>> 934837ae69fSSean Fertile ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 935837ae69fSSean Fertile unsigned FileType) { 936837ae69fSSean Fertile return XCOFFObjectFile::create(FileType, MemBufRef); 937ab2eb2bfSHubert Tong } 938ab2eb2bfSHubert Tong 9398e84311aSjasonliu bool XCOFFSymbolRef::isFunction() const { 9408e84311aSjasonliu if (!isCsectSymbol()) 9418e84311aSjasonliu return false; 9428e84311aSjasonliu 9438e84311aSjasonliu if (getSymbolType() & FunctionSym) 9448e84311aSjasonliu return true; 9458e84311aSjasonliu 9468e84311aSjasonliu Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); 9478e84311aSjasonliu if (!ExpCsectAuxEnt) 9488e84311aSjasonliu return false; 9498e84311aSjasonliu 9508e84311aSjasonliu const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); 9518e84311aSjasonliu 9528e84311aSjasonliu // A function definition should be a label definition. 9538e84311aSjasonliu // FIXME: This is not necessarily the case when -ffunction-sections is 9548e84311aSjasonliu // enabled. 9558e84311aSjasonliu if (!CsectAuxRef.isLabel()) 9568e84311aSjasonliu return false; 9578e84311aSjasonliu 9588e84311aSjasonliu if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) 9598e84311aSjasonliu return false; 9608e84311aSjasonliu 9618e84311aSjasonliu const int16_t SectNum = getSectionNumber(); 9628e84311aSjasonliu Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); 9638e84311aSjasonliu if (!SI) { 9648e84311aSjasonliu // If we could not get the section, then this symbol should not be 9658e84311aSjasonliu // a function. So consume the error and return `false` to move on. 9668e84311aSjasonliu consumeError(SI.takeError()); 9678e84311aSjasonliu return false; 9687c72e82bSJason Liu } 9697c72e82bSJason Liu 9708e84311aSjasonliu return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); 9717c72e82bSJason Liu } 9727c72e82bSJason Liu 9738e84311aSjasonliu bool XCOFFSymbolRef::isCsectSymbol() const { 9747c72e82bSJason Liu XCOFF::StorageClass SC = getStorageClass(); 9757c72e82bSJason Liu return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || 9767c72e82bSJason Liu SC == XCOFF::C_HIDEXT); 9777c72e82bSJason Liu } 9787c72e82bSJason Liu 9798e84311aSjasonliu Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { 9808e84311aSjasonliu assert(isCsectSymbol() && 9818e84311aSjasonliu "Calling csect symbol interface with a non-csect symbol."); 9827c72e82bSJason Liu 9838e84311aSjasonliu uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); 9847c72e82bSJason Liu 9858e84311aSjasonliu Expected<StringRef> NameOrErr = getName(); 9868e84311aSjasonliu if (auto Err = NameOrErr.takeError()) 9878e84311aSjasonliu return std::move(Err); 9887c72e82bSJason Liu 9898e84311aSjasonliu if (!NumberOfAuxEntries) { 9908e84311aSjasonliu return createStringError(object_error::parse_failed, 9918e84311aSjasonliu "csect symbol \"" + *NameOrErr + 9928e84311aSjasonliu "\" contains no auxiliary entry"); 9938e84311aSjasonliu } 9947c72e82bSJason Liu 9958e84311aSjasonliu if (!OwningObjectPtr->is64Bit()) { 9968e84311aSjasonliu // In XCOFF32, the csect auxilliary entry is always the last auxiliary 9978e84311aSjasonliu // entry for the symbol. 9988e84311aSjasonliu uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 9998e84311aSjasonliu getEntryAddress(), NumberOfAuxEntries); 10008e84311aSjasonliu return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); 10018e84311aSjasonliu } 10027c72e82bSJason Liu 10038e84311aSjasonliu // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. 10048e84311aSjasonliu // We need to iterate through all the auxiliary entries to find it. 10058e84311aSjasonliu for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { 10068e84311aSjasonliu uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 10078e84311aSjasonliu getEntryAddress(), Index); 10088e84311aSjasonliu if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) == 10098e84311aSjasonliu XCOFF::SymbolAuxType::AUX_CSECT) { 10108e84311aSjasonliu #ifndef NDEBUG 10118e84311aSjasonliu OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); 10128e84311aSjasonliu #endif 10138e84311aSjasonliu return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); 10148e84311aSjasonliu } 10158e84311aSjasonliu } 10167c72e82bSJason Liu 10178e84311aSjasonliu return createStringError( 10188e84311aSjasonliu object_error::parse_failed, 10198e84311aSjasonliu "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\""); 10208e84311aSjasonliu } 10217c72e82bSJason Liu 10228e84311aSjasonliu Expected<StringRef> XCOFFSymbolRef::getName() const { 10238e84311aSjasonliu // A storage class value with the high-order bit on indicates that the name is 10248e84311aSjasonliu // a symbolic debugger stabstring. 10258e84311aSjasonliu if (getStorageClass() & 0x80) 10268e84311aSjasonliu return StringRef("Unimplemented Debug Name"); 10278e84311aSjasonliu 10288e84311aSjasonliu if (Entry32) { 10298e84311aSjasonliu if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 10308e84311aSjasonliu return generateXCOFFFixedNameStringRef(Entry32->SymbolName); 10318e84311aSjasonliu 10328e84311aSjasonliu return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); 10338e84311aSjasonliu } 10348e84311aSjasonliu 10358e84311aSjasonliu return OwningObjectPtr->getStringTableEntry(Entry64->Offset); 1036ab2eb2bfSHubert Tong } 1037ab2eb2bfSHubert Tong 1038f8622543SFangrui Song // Explictly instantiate template classes. 1039f8622543SFangrui Song template struct XCOFFSectionHeader<XCOFFSectionHeader32>; 1040f8622543SFangrui Song template struct XCOFFSectionHeader<XCOFFSectionHeader64>; 1041f8622543SFangrui Song 10422cdfd0b2SMaryam Benimmar template struct XCOFFRelocation<llvm::support::ubig32_t>; 10432cdfd0b2SMaryam Benimmar template struct XCOFFRelocation<llvm::support::ubig64_t>; 10442cdfd0b2SMaryam Benimmar 10452cdfd0b2SMaryam Benimmar template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>> 10462cdfd0b2SMaryam Benimmar llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64, 10472cdfd0b2SMaryam Benimmar llvm::object::XCOFFRelocation64>( 10482cdfd0b2SMaryam Benimmar llvm::object::XCOFFSectionHeader64 const &) const; 10492cdfd0b2SMaryam Benimmar template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>> 10502cdfd0b2SMaryam Benimmar llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32, 10512cdfd0b2SMaryam Benimmar llvm::object::XCOFFRelocation32>( 10522cdfd0b2SMaryam Benimmar llvm::object::XCOFFSectionHeader32 const &) const; 10532cdfd0b2SMaryam Benimmar 10542f0d755dSdiggerlin bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { 10552f0d755dSdiggerlin if (Bytes.size() < 4) 10562f0d755dSdiggerlin return false; 10572f0d755dSdiggerlin 10582f0d755dSdiggerlin return support::endian::read32be(Bytes.data()) == 0; 10592f0d755dSdiggerlin } 10602f0d755dSdiggerlin 1061ab77fa51Sdiggerlin #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) 1062ab77fa51Sdiggerlin #define GETVALUEWITHMASKSHIFT(X, S) \ 1063ab77fa51Sdiggerlin ((Data & (TracebackTable::X)) >> (TracebackTable::S)) 10647ed515d1Szhijian 10657ed515d1Szhijian Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) { 10667ed515d1Szhijian Error Err = Error::success(); 10677ed515d1Szhijian TBVectorExt TBTVecExt(TBvectorStrRef, Err); 10687ed515d1Szhijian if (Err) 10697ed515d1Szhijian return std::move(Err); 10707ed515d1Szhijian return TBTVecExt; 10717ed515d1Szhijian } 10727ed515d1Szhijian 10737ed515d1Szhijian TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) { 10747ed515d1Szhijian const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); 10757ed515d1Szhijian Data = support::endian::read16be(Ptr); 10767ed515d1Szhijian uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2); 10777ed515d1Szhijian unsigned ParmsNum = 10787ed515d1Szhijian GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); 10797ed515d1Szhijian 10807ed515d1Szhijian ErrorAsOutParameter EAO(&Err); 10817ed515d1Szhijian Expected<SmallString<32>> VecParmsTypeOrError = 10827ed515d1Szhijian parseVectorParmsType(VecParmsTypeValue, ParmsNum); 10837ed515d1Szhijian if (!VecParmsTypeOrError) 10847ed515d1Szhijian Err = VecParmsTypeOrError.takeError(); 10857ed515d1Szhijian else 10867ed515d1Szhijian VecParmsInfo = VecParmsTypeOrError.get(); 10877ed515d1Szhijian } 10887ed515d1Szhijian 108985177965Sdiggerlin uint8_t TBVectorExt::getNumberOfVRSaved() const { 1090ab77fa51Sdiggerlin return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); 1091ab77fa51Sdiggerlin } 1092ab77fa51Sdiggerlin 1093ab77fa51Sdiggerlin bool TBVectorExt::isVRSavedOnStack() const { 1094ab77fa51Sdiggerlin return GETVALUEWITHMASK(IsVRSavedOnStackMask); 1095ab77fa51Sdiggerlin } 1096ab77fa51Sdiggerlin 1097ab77fa51Sdiggerlin bool TBVectorExt::hasVarArgs() const { 1098ab77fa51Sdiggerlin return GETVALUEWITHMASK(HasVarArgsMask); 1099ab77fa51Sdiggerlin } 11007ed515d1Szhijian 1101ab77fa51Sdiggerlin uint8_t TBVectorExt::getNumberOfVectorParms() const { 1102ab77fa51Sdiggerlin return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, 1103ab77fa51Sdiggerlin NumberOfVectorParmsShift); 1104ab77fa51Sdiggerlin } 1105ab77fa51Sdiggerlin 1106ab77fa51Sdiggerlin bool TBVectorExt::hasVMXInstruction() const { 1107ab77fa51Sdiggerlin return GETVALUEWITHMASK(HasVMXInstructionMask); 1108ab77fa51Sdiggerlin } 1109ab77fa51Sdiggerlin #undef GETVALUEWITHMASK 1110ab77fa51Sdiggerlin #undef GETVALUEWITHMASKSHIFT 1111ab77fa51Sdiggerlin 11122f0d755dSdiggerlin Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr, 11132f0d755dSdiggerlin uint64_t &Size) { 11142f0d755dSdiggerlin Error Err = Error::success(); 11152f0d755dSdiggerlin XCOFFTracebackTable TBT(Ptr, Size, Err); 11162f0d755dSdiggerlin if (Err) 11172f0d755dSdiggerlin return std::move(Err); 11182f0d755dSdiggerlin return TBT; 11192f0d755dSdiggerlin } 11202f0d755dSdiggerlin 11212f0d755dSdiggerlin XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, 11222f0d755dSdiggerlin Error &Err) 11232f0d755dSdiggerlin : TBPtr(Ptr) { 11242f0d755dSdiggerlin ErrorAsOutParameter EAO(&Err); 11252f0d755dSdiggerlin DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false, 11262f0d755dSdiggerlin /*AddressSize=*/0); 11272f0d755dSdiggerlin DataExtractor::Cursor Cur(/*Offset=*/0); 11282f0d755dSdiggerlin 11292f0d755dSdiggerlin // Skip 8 bytes of mandatory fields. 11302f0d755dSdiggerlin DE.getU64(Cur); 11312f0d755dSdiggerlin 11327ed515d1Szhijian unsigned FixedParmsNum = getNumberOfFixedParms(); 11337ed515d1Szhijian unsigned FloatingParmsNum = getNumberOfFPParms(); 11347ed515d1Szhijian uint32_t ParamsTypeValue = 0; 11352f0d755dSdiggerlin 11367ed515d1Szhijian // Begin to parse optional fields. 11377ed515d1Szhijian if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) 11387ed515d1Szhijian ParamsTypeValue = DE.getU32(Cur); 11392f0d755dSdiggerlin 11402f0d755dSdiggerlin if (Cur && hasTraceBackTableOffset()) 11412f0d755dSdiggerlin TraceBackTableOffset = DE.getU32(Cur); 11422f0d755dSdiggerlin 11432f0d755dSdiggerlin if (Cur && isInterruptHandler()) 11442f0d755dSdiggerlin HandlerMask = DE.getU32(Cur); 11452f0d755dSdiggerlin 11462f0d755dSdiggerlin if (Cur && hasControlledStorage()) { 11472f0d755dSdiggerlin NumOfCtlAnchors = DE.getU32(Cur); 11482f0d755dSdiggerlin if (Cur && NumOfCtlAnchors) { 11492f0d755dSdiggerlin SmallVector<uint32_t, 8> Disp; 11502f0d755dSdiggerlin Disp.reserve(NumOfCtlAnchors.getValue()); 11512f0d755dSdiggerlin for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I) 11522f0d755dSdiggerlin Disp.push_back(DE.getU32(Cur)); 11532f0d755dSdiggerlin if (Cur) 11542f0d755dSdiggerlin ControlledStorageInfoDisp = std::move(Disp); 11552f0d755dSdiggerlin } 11562f0d755dSdiggerlin } 11572f0d755dSdiggerlin 11582f0d755dSdiggerlin if (Cur && isFuncNamePresent()) { 11592f0d755dSdiggerlin uint16_t FunctionNameLen = DE.getU16(Cur); 11602f0d755dSdiggerlin if (Cur) 11612f0d755dSdiggerlin FunctionName = DE.getBytes(Cur, FunctionNameLen); 11622f0d755dSdiggerlin } 11632f0d755dSdiggerlin 11642f0d755dSdiggerlin if (Cur && isAllocaUsed()) 11652f0d755dSdiggerlin AllocaRegister = DE.getU8(Cur); 11662f0d755dSdiggerlin 11677ed515d1Szhijian unsigned VectorParmsNum = 0; 1168ab77fa51Sdiggerlin if (Cur && hasVectorInfo()) { 1169ab77fa51Sdiggerlin StringRef VectorExtRef = DE.getBytes(Cur, 6); 11707ed515d1Szhijian if (Cur) { 11717ed515d1Szhijian Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef); 11727ed515d1Szhijian if (!TBVecExtOrErr) { 11737ed515d1Szhijian Err = TBVecExtOrErr.takeError(); 11747ed515d1Szhijian return; 11757ed515d1Szhijian } 11767ed515d1Szhijian VecExt = TBVecExtOrErr.get(); 11777ed515d1Szhijian VectorParmsNum = VecExt.getValue().getNumberOfVectorParms(); 11787ed515d1Szhijian } 11797ed515d1Szhijian } 11807ed515d1Szhijian 11817ed515d1Szhijian // As long as there is no fixed-point or floating-point parameter, this 11827ed515d1Szhijian // field remains not present even when hasVectorInfo gives true and 11837ed515d1Szhijian // indicates the presence of vector parameters. 11847ed515d1Szhijian if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) { 11857ed515d1Szhijian Expected<SmallString<32>> ParmsTypeOrError = 11867ed515d1Szhijian hasVectorInfo() 11877ed515d1Szhijian ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum, 11887ed515d1Szhijian FloatingParmsNum, VectorParmsNum) 11897ed515d1Szhijian : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum); 11907ed515d1Szhijian 11917ed515d1Szhijian if (!ParmsTypeOrError) { 11927ed515d1Szhijian Err = ParmsTypeOrError.takeError(); 11937ed515d1Szhijian return; 11947ed515d1Szhijian } 11957ed515d1Szhijian ParmsType = ParmsTypeOrError.get(); 1196ab77fa51Sdiggerlin } 1197ab77fa51Sdiggerlin 1198ab77fa51Sdiggerlin if (Cur && hasExtensionTable()) 1199ab77fa51Sdiggerlin ExtensionTable = DE.getU8(Cur); 12002f0d755dSdiggerlin 12012f0d755dSdiggerlin if (!Cur) 12022f0d755dSdiggerlin Err = Cur.takeError(); 12037ed515d1Szhijian 12042f0d755dSdiggerlin Size = Cur.tell(); 12052f0d755dSdiggerlin } 12062f0d755dSdiggerlin 12072f0d755dSdiggerlin #define GETBITWITHMASK(P, X) \ 12082f0d755dSdiggerlin (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) 12092f0d755dSdiggerlin #define GETBITWITHMASKSHIFT(P, X, S) \ 12102f0d755dSdiggerlin ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \ 12112f0d755dSdiggerlin (TracebackTable::S)) 12122f0d755dSdiggerlin 12132f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getVersion() const { 12142f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift); 12152f0d755dSdiggerlin } 12162f0d755dSdiggerlin 12172f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getLanguageID() const { 12182f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift); 12192f0d755dSdiggerlin } 12202f0d755dSdiggerlin 12212f0d755dSdiggerlin bool XCOFFTracebackTable::isGlobalLinkage() const { 12222f0d755dSdiggerlin return GETBITWITHMASK(0, IsGlobaLinkageMask); 12232f0d755dSdiggerlin } 12242f0d755dSdiggerlin 12252f0d755dSdiggerlin bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const { 12262f0d755dSdiggerlin return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask); 12272f0d755dSdiggerlin } 12282f0d755dSdiggerlin 12292f0d755dSdiggerlin bool XCOFFTracebackTable::hasTraceBackTableOffset() const { 12302f0d755dSdiggerlin return GETBITWITHMASK(0, HasTraceBackTableOffsetMask); 12312f0d755dSdiggerlin } 12322f0d755dSdiggerlin 12332f0d755dSdiggerlin bool XCOFFTracebackTable::isInternalProcedure() const { 12342f0d755dSdiggerlin return GETBITWITHMASK(0, IsInternalProcedureMask); 12352f0d755dSdiggerlin } 12362f0d755dSdiggerlin 12372f0d755dSdiggerlin bool XCOFFTracebackTable::hasControlledStorage() const { 12382f0d755dSdiggerlin return GETBITWITHMASK(0, HasControlledStorageMask); 12392f0d755dSdiggerlin } 12402f0d755dSdiggerlin 12412f0d755dSdiggerlin bool XCOFFTracebackTable::isTOCless() const { 12422f0d755dSdiggerlin return GETBITWITHMASK(0, IsTOClessMask); 12432f0d755dSdiggerlin } 12442f0d755dSdiggerlin 12452f0d755dSdiggerlin bool XCOFFTracebackTable::isFloatingPointPresent() const { 12462f0d755dSdiggerlin return GETBITWITHMASK(0, IsFloatingPointPresentMask); 12472f0d755dSdiggerlin } 12482f0d755dSdiggerlin 12492f0d755dSdiggerlin bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const { 12502f0d755dSdiggerlin return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask); 12512f0d755dSdiggerlin } 12522f0d755dSdiggerlin 12532f0d755dSdiggerlin bool XCOFFTracebackTable::isInterruptHandler() const { 12542f0d755dSdiggerlin return GETBITWITHMASK(0, IsInterruptHandlerMask); 12552f0d755dSdiggerlin } 12562f0d755dSdiggerlin 12572f0d755dSdiggerlin bool XCOFFTracebackTable::isFuncNamePresent() const { 12582f0d755dSdiggerlin return GETBITWITHMASK(0, IsFunctionNamePresentMask); 12592f0d755dSdiggerlin } 12602f0d755dSdiggerlin 12612f0d755dSdiggerlin bool XCOFFTracebackTable::isAllocaUsed() const { 12622f0d755dSdiggerlin return GETBITWITHMASK(0, IsAllocaUsedMask); 12632f0d755dSdiggerlin } 12642f0d755dSdiggerlin 12652f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getOnConditionDirective() const { 12662f0d755dSdiggerlin return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask, 12672f0d755dSdiggerlin OnConditionDirectiveShift); 12682f0d755dSdiggerlin } 12692f0d755dSdiggerlin 12702f0d755dSdiggerlin bool XCOFFTracebackTable::isCRSaved() const { 12712f0d755dSdiggerlin return GETBITWITHMASK(0, IsCRSavedMask); 12722f0d755dSdiggerlin } 12732f0d755dSdiggerlin 12742f0d755dSdiggerlin bool XCOFFTracebackTable::isLRSaved() const { 12752f0d755dSdiggerlin return GETBITWITHMASK(0, IsLRSavedMask); 12762f0d755dSdiggerlin } 12772f0d755dSdiggerlin 12782f0d755dSdiggerlin bool XCOFFTracebackTable::isBackChainStored() const { 12792f0d755dSdiggerlin return GETBITWITHMASK(4, IsBackChainStoredMask); 12802f0d755dSdiggerlin } 12812f0d755dSdiggerlin 12822f0d755dSdiggerlin bool XCOFFTracebackTable::isFixup() const { 12832f0d755dSdiggerlin return GETBITWITHMASK(4, IsFixupMask); 12842f0d755dSdiggerlin } 12852f0d755dSdiggerlin 12862f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const { 12872f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift); 12882f0d755dSdiggerlin } 12892f0d755dSdiggerlin 12902f0d755dSdiggerlin bool XCOFFTracebackTable::hasExtensionTable() const { 12912f0d755dSdiggerlin return GETBITWITHMASK(4, HasExtensionTableMask); 12922f0d755dSdiggerlin } 12932f0d755dSdiggerlin 12942f0d755dSdiggerlin bool XCOFFTracebackTable::hasVectorInfo() const { 12952f0d755dSdiggerlin return GETBITWITHMASK(4, HasVectorInfoMask); 12962f0d755dSdiggerlin } 12972f0d755dSdiggerlin 1298c80fbdf2Sdiggerlin uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const { 12992f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift); 13002f0d755dSdiggerlin } 13012f0d755dSdiggerlin 13022f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const { 13032f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask, 13042f0d755dSdiggerlin NumberOfFixedParmsShift); 13052f0d755dSdiggerlin } 13062f0d755dSdiggerlin 13072f0d755dSdiggerlin uint8_t XCOFFTracebackTable::getNumberOfFPParms() const { 13082f0d755dSdiggerlin return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask, 13092f0d755dSdiggerlin NumberOfFloatingPointParmsShift); 13102f0d755dSdiggerlin } 13112f0d755dSdiggerlin 13122f0d755dSdiggerlin bool XCOFFTracebackTable::hasParmsOnStack() const { 13132f0d755dSdiggerlin return GETBITWITHMASK(4, HasParmsOnStackMask); 13142f0d755dSdiggerlin } 13152f0d755dSdiggerlin 13162f0d755dSdiggerlin #undef GETBITWITHMASK 13172f0d755dSdiggerlin #undef GETBITWITHMASKSHIFT 1318ab2eb2bfSHubert Tong } // namespace object 1319ab2eb2bfSHubert Tong } // namespace llvm 1320