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" 14ab2eb2bfSHubert Tong #include <cstddef> 15ab2eb2bfSHubert Tong #include <cstring> 16ab2eb2bfSHubert Tong 17ab2eb2bfSHubert Tong namespace llvm { 18ab2eb2bfSHubert Tong namespace object { 19ab2eb2bfSHubert Tong 20837ae69fSSean Fertile // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer 21837ae69fSSean Fertile // 'M'. Returns a pointer to the underlying object on success. 22ab2eb2bfSHubert Tong template <typename T> 23837ae69fSSean Fertile static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, 24ab2eb2bfSHubert Tong const uint64_t Size = sizeof(T)) { 25ab2eb2bfSHubert Tong uintptr_t Addr = uintptr_t(Ptr); 26ab2eb2bfSHubert Tong if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) 27837ae69fSSean Fertile return errorCodeToError(EC); 28837ae69fSSean Fertile return reinterpret_cast<const T *>(Addr); 29837ae69fSSean Fertile } 30837ae69fSSean Fertile 31837ae69fSSean Fertile static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) { 32837ae69fSSean Fertile return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) + 33837ae69fSSean Fertile Offset); 34ab2eb2bfSHubert Tong } 35ab2eb2bfSHubert Tong 36a93a33cbSSean Fertile template <typename T> static const T *viewAs(uintptr_t in) { 37a93a33cbSSean Fertile return reinterpret_cast<const T *>(in); 38a93a33cbSSean Fertile } 39a93a33cbSSean Fertile 4029141da7SSean Fertile static StringRef generateStringRef(const char *Name) { 4129141da7SSean Fertile auto NulCharPtr = 4229141da7SSean Fertile static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize)); 439212206dSJason Liu return NulCharPtr ? StringRef(Name, NulCharPtr - Name) 4429141da7SSean Fertile : StringRef(Name, XCOFF::NameSize); 459212206dSJason Liu } 469212206dSJason Liu 47837ae69fSSean Fertile void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, 48837ae69fSSean Fertile uintptr_t TableAddress) const { 49837ae69fSSean Fertile if (Addr < TableAddress) 50a93a33cbSSean Fertile report_fatal_error("Section header outside of section header table."); 51a93a33cbSSean Fertile 52837ae69fSSean Fertile uintptr_t Offset = Addr - TableAddress; 53837ae69fSSean Fertile if (Offset >= getSectionHeaderSize() * getNumberOfSections()) 54837ae69fSSean Fertile report_fatal_error("Section header outside of section header table."); 55837ae69fSSean Fertile 56a93a33cbSSean Fertile if (Offset % getSectionHeaderSize() != 0) 57a93a33cbSSean Fertile report_fatal_error( 58a93a33cbSSean Fertile "Section header pointer does not point to a valid section header."); 59837ae69fSSean Fertile } 60837ae69fSSean Fertile 61837ae69fSSean Fertile const XCOFFSectionHeader32 * 62837ae69fSSean Fertile XCOFFObjectFile::toSection32(DataRefImpl Ref) const { 63837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 64837ae69fSSean Fertile #ifndef NDEBUG 65837ae69fSSean Fertile checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 66a93a33cbSSean Fertile #endif 67837ae69fSSean Fertile return viewAs<XCOFFSectionHeader32>(Ref.p); 68837ae69fSSean Fertile } 69837ae69fSSean Fertile 70837ae69fSSean Fertile const XCOFFSectionHeader64 * 71837ae69fSSean Fertile XCOFFObjectFile::toSection64(DataRefImpl Ref) const { 72837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 73837ae69fSSean Fertile #ifndef NDEBUG 74837ae69fSSean Fertile checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 75837ae69fSSean Fertile #endif 76837ae69fSSean Fertile return viewAs<XCOFFSectionHeader64>(Ref.p); 77a93a33cbSSean Fertile } 78a93a33cbSSean Fertile 799212206dSJason Liu const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const { 80837ae69fSSean Fertile assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); 819212206dSJason Liu assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); 829212206dSJason Liu auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p); 839212206dSJason Liu return SymEntPtr; 849212206dSJason Liu } 859212206dSJason Liu 86837ae69fSSean Fertile const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { 87837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 88837ae69fSSean Fertile return static_cast<const XCOFFFileHeader32 *>(FileHeader); 89a93a33cbSSean Fertile } 90a93a33cbSSean Fertile 91837ae69fSSean Fertile const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { 92837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 93837ae69fSSean Fertile return static_cast<const XCOFFFileHeader64 *>(FileHeader); 94a93a33cbSSean Fertile } 95a93a33cbSSean Fertile 96837ae69fSSean Fertile const XCOFFSectionHeader32 * 97837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable32() const { 98837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 99837ae69fSSean Fertile return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable); 100837ae69fSSean Fertile } 101837ae69fSSean Fertile 102837ae69fSSean Fertile const XCOFFSectionHeader64 * 103837ae69fSSean Fertile XCOFFObjectFile::sectionHeaderTable64() const { 104837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 105837ae69fSSean Fertile return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable); 106837ae69fSSean Fertile } 1079212206dSJason Liu 108ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1099212206dSJason Liu const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); 1109212206dSJason Liu SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1; 1119212206dSJason Liu Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr); 112ab2eb2bfSHubert Tong } 113ab2eb2bfSHubert Tong 114ab2eb2bfSHubert Tong Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 1159212206dSJason Liu const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); 1169212206dSJason Liu 1179212206dSJason Liu if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) 11829141da7SSean Fertile return generateStringRef(SymEntPtr->SymbolName); 1199212206dSJason Liu 1209212206dSJason Liu // A storage class value with the high-order bit on indicates that the name is 1219212206dSJason Liu // a symbolic debugger stabstring. 1229212206dSJason Liu if (SymEntPtr->StorageClass & 0x80) 1239212206dSJason Liu return StringRef("Unimplemented Debug Name"); 1249212206dSJason Liu 1259212206dSJason Liu uint32_t Offset = SymEntPtr->NameInStrTbl.Offset; 1269212206dSJason Liu // The byte offset is relative to the start of the string table 1279212206dSJason Liu // or .debug section. A byte offset value of 0 is a null or zero-length symbol 1289212206dSJason Liu // name. A byte offset in the range 1 to 3 (inclusive) points into the length 1299212206dSJason Liu // field; as a soft-error recovery mechanism, we treat such cases as having an 1309212206dSJason Liu // offset of 0. 1319212206dSJason Liu if (Offset < 4) 1329212206dSJason Liu return StringRef(nullptr, 0); 1339212206dSJason Liu 1349212206dSJason Liu if (StringTable.Data != nullptr && StringTable.Size > Offset) 1359212206dSJason Liu return (StringTable.Data + Offset); 1369212206dSJason Liu 1379212206dSJason Liu return make_error<GenericBinaryError>("Symbol Name parse failed", 1389212206dSJason Liu object_error::parse_failed); 139ab2eb2bfSHubert Tong } 140ab2eb2bfSHubert Tong 141ab2eb2bfSHubert Tong Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 142ab2eb2bfSHubert Tong uint64_t Result = 0; 143ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 144ab2eb2bfSHubert Tong return Result; 145ab2eb2bfSHubert Tong } 146ab2eb2bfSHubert Tong 147ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 1489212206dSJason Liu return toSymbolEntry(Symb)->Value; 149ab2eb2bfSHubert Tong } 150ab2eb2bfSHubert Tong 151ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 152ab2eb2bfSHubert Tong uint64_t Result = 0; 153ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 154ab2eb2bfSHubert Tong return Result; 155ab2eb2bfSHubert Tong } 156ab2eb2bfSHubert Tong 157ab2eb2bfSHubert Tong Expected<SymbolRef::Type> 158ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 159ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 160ab2eb2bfSHubert Tong return SymbolRef::ST_Other; 161ab2eb2bfSHubert Tong } 162ab2eb2bfSHubert Tong 163ab2eb2bfSHubert Tong Expected<section_iterator> 164ab2eb2bfSHubert Tong XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 1659212206dSJason Liu const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); 1669212206dSJason Liu int16_t SectNum = SymEntPtr->SectionNumber; 1679212206dSJason Liu 1689212206dSJason Liu if (isReservedSectionNumber(SectNum)) 1699212206dSJason Liu return section_end(); 1709212206dSJason Liu 171837ae69fSSean Fertile Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum); 172837ae69fSSean Fertile if (!ExpSec) 173837ae69fSSean Fertile return ExpSec.takeError(); 1749212206dSJason Liu 175837ae69fSSean Fertile return section_iterator(SectionRef(ExpSec.get(), this)); 176ab2eb2bfSHubert Tong } 177ab2eb2bfSHubert Tong 178ab2eb2bfSHubert Tong void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 179a93a33cbSSean Fertile const char *Ptr = reinterpret_cast<const char *>(Sec.p); 180a93a33cbSSean Fertile Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); 181ab2eb2bfSHubert Tong } 182ab2eb2bfSHubert Tong 1838be28cdcSFangrui Song Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { 18429141da7SSean Fertile return generateStringRef(getSectionNameInternal(Sec)); 185ab2eb2bfSHubert Tong } 186ab2eb2bfSHubert Tong 187ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 188210314aeSSean Fertile // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 189210314aeSSean Fertile // with MSVC. 190210314aeSSean Fertile if (is64Bit()) 191210314aeSSean Fertile return toSection64(Sec)->VirtualAddress; 192210314aeSSean Fertile 193210314aeSSean Fertile return toSection32(Sec)->VirtualAddress; 194ab2eb2bfSHubert Tong } 195ab2eb2bfSHubert Tong 196ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 197a93a33cbSSean Fertile // Section numbers in XCOFF are numbered beginning at 1. A section number of 198a93a33cbSSean Fertile // zero is used to indicate that a symbol is being imported or is undefined. 199837ae69fSSean Fertile if (is64Bit()) 200837ae69fSSean Fertile return toSection64(Sec) - sectionHeaderTable64() + 1; 201837ae69fSSean Fertile else 202837ae69fSSean Fertile return toSection32(Sec) - sectionHeaderTable32() + 1; 203ab2eb2bfSHubert Tong } 204ab2eb2bfSHubert Tong 205ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 206210314aeSSean Fertile // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 207210314aeSSean Fertile // with MSVC. 208210314aeSSean Fertile if (is64Bit()) 209210314aeSSean Fertile return toSection64(Sec)->SectionSize; 210210314aeSSean Fertile 211210314aeSSean Fertile return toSection32(Sec)->SectionSize; 212ab2eb2bfSHubert Tong } 213ab2eb2bfSHubert Tong 214e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>> 215e1cb2c0fSFangrui Song XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { 216ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 217ab2eb2bfSHubert Tong } 218ab2eb2bfSHubert Tong 219ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 220ab2eb2bfSHubert Tong uint64_t Result = 0; 221ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 222ab2eb2bfSHubert Tong return Result; 223ab2eb2bfSHubert Tong } 224ab2eb2bfSHubert Tong 225ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 226ab2eb2bfSHubert Tong bool Result = false; 227ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 228ab2eb2bfSHubert Tong return Result; 229ab2eb2bfSHubert Tong } 230ab2eb2bfSHubert Tong 231ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { 232837ae69fSSean Fertile return getSectionFlags(Sec) & XCOFF::STYP_TEXT; 233ab2eb2bfSHubert Tong } 234ab2eb2bfSHubert Tong 235ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { 236837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec); 237a93a33cbSSean Fertile return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); 238ab2eb2bfSHubert Tong } 239ab2eb2bfSHubert Tong 240ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { 241837ae69fSSean Fertile uint32_t Flags = getSectionFlags(Sec); 242a93a33cbSSean Fertile return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); 243ab2eb2bfSHubert Tong } 244ab2eb2bfSHubert Tong 245ab2eb2bfSHubert Tong bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { 246ab2eb2bfSHubert Tong bool Result = false; 247ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 248ab2eb2bfSHubert Tong return Result; 249ab2eb2bfSHubert Tong } 250ab2eb2bfSHubert Tong 251ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 252ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 253ab2eb2bfSHubert Tong return relocation_iterator(RelocationRef()); 254ab2eb2bfSHubert Tong } 255ab2eb2bfSHubert Tong 256ab2eb2bfSHubert Tong relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { 257ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 258ab2eb2bfSHubert Tong return relocation_iterator(RelocationRef()); 259ab2eb2bfSHubert Tong } 260ab2eb2bfSHubert Tong 261ab2eb2bfSHubert Tong void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 262ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 263ab2eb2bfSHubert Tong return; 264ab2eb2bfSHubert Tong } 265ab2eb2bfSHubert Tong 266ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 267ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 268ab2eb2bfSHubert Tong uint64_t Result = 0; 269ab2eb2bfSHubert Tong return Result; 270ab2eb2bfSHubert Tong } 271ab2eb2bfSHubert Tong 272ab2eb2bfSHubert Tong symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 273ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 274ab2eb2bfSHubert Tong return symbol_iterator(SymbolRef()); 275ab2eb2bfSHubert Tong } 276ab2eb2bfSHubert Tong 277ab2eb2bfSHubert Tong uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { 278ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 279ab2eb2bfSHubert Tong uint64_t Result = 0; 280ab2eb2bfSHubert Tong return Result; 281ab2eb2bfSHubert Tong } 282ab2eb2bfSHubert Tong 283ab2eb2bfSHubert Tong void XCOFFObjectFile::getRelocationTypeName( 284ab2eb2bfSHubert Tong DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 285ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 286ab2eb2bfSHubert Tong return; 287ab2eb2bfSHubert Tong } 288ab2eb2bfSHubert Tong 289ab2eb2bfSHubert Tong uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 290ab2eb2bfSHubert Tong uint32_t Result = 0; 291ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 292ab2eb2bfSHubert Tong return Result; 293ab2eb2bfSHubert Tong } 294ab2eb2bfSHubert Tong 295ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { 296837ae69fSSean Fertile assert(!is64Bit() && "64-bit support not implemented yet."); 2979212206dSJason Liu DataRefImpl SymDRI; 2989212206dSJason Liu SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); 2999212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this)); 300ab2eb2bfSHubert Tong } 301ab2eb2bfSHubert Tong 302ab2eb2bfSHubert Tong basic_symbol_iterator XCOFFObjectFile::symbol_end() const { 303837ae69fSSean Fertile assert(!is64Bit() && "64-bit support not implemented yet."); 3049212206dSJason Liu DataRefImpl SymDRI; 3059212206dSJason Liu SymDRI.p = reinterpret_cast<uintptr_t>( 306837ae69fSSean Fertile SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32()); 3079212206dSJason Liu return basic_symbol_iterator(SymbolRef(SymDRI, this)); 308ab2eb2bfSHubert Tong } 309ab2eb2bfSHubert Tong 310ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_begin() const { 311a93a33cbSSean Fertile DataRefImpl DRI; 312837ae69fSSean Fertile DRI.p = getSectionHeaderTableAddress(); 313a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this)); 314ab2eb2bfSHubert Tong } 315ab2eb2bfSHubert Tong 316ab2eb2bfSHubert Tong section_iterator XCOFFObjectFile::section_end() const { 317a93a33cbSSean Fertile DataRefImpl DRI; 318837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(), 319837ae69fSSean Fertile getNumberOfSections() * getSectionHeaderSize()); 320a93a33cbSSean Fertile return section_iterator(SectionRef(DRI, this)); 321ab2eb2bfSHubert Tong } 322ab2eb2bfSHubert Tong 323837ae69fSSean Fertile uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } 324ab2eb2bfSHubert Tong 325ab2eb2bfSHubert Tong StringRef XCOFFObjectFile::getFileFormatName() const { 326837ae69fSSean Fertile return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; 327ab2eb2bfSHubert Tong } 328ab2eb2bfSHubert Tong 329ab2eb2bfSHubert Tong Triple::ArchType XCOFFObjectFile::getArch() const { 330837ae69fSSean Fertile return is64Bit() ? Triple::ppc64 : Triple::ppc; 331ab2eb2bfSHubert Tong } 332ab2eb2bfSHubert Tong 333ab2eb2bfSHubert Tong SubtargetFeatures XCOFFObjectFile::getFeatures() const { 334ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 335ab2eb2bfSHubert Tong return SubtargetFeatures(); 336ab2eb2bfSHubert Tong } 337ab2eb2bfSHubert Tong 338ab2eb2bfSHubert Tong bool XCOFFObjectFile::isRelocatableObject() const { 339ab2eb2bfSHubert Tong bool Result = false; 340ab2eb2bfSHubert Tong llvm_unreachable("Not yet implemented!"); 341ab2eb2bfSHubert Tong return Result; 342ab2eb2bfSHubert Tong } 343ab2eb2bfSHubert Tong 344a93a33cbSSean Fertile Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { 345a93a33cbSSean Fertile // TODO FIXME Should get from auxiliary_header->o_entry when support for the 346a93a33cbSSean Fertile // auxiliary_header is added. 347a93a33cbSSean Fertile return 0; 348a93a33cbSSean Fertile } 349a93a33cbSSean Fertile 350837ae69fSSean Fertile size_t XCOFFObjectFile::getFileHeaderSize() const { 351837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); 3529212206dSJason Liu } 3539212206dSJason Liu 354837ae69fSSean Fertile size_t XCOFFObjectFile::getSectionHeaderSize() const { 355837ae69fSSean Fertile return is64Bit() ? sizeof(XCOFFSectionHeader64) : 356837ae69fSSean Fertile sizeof(XCOFFSectionHeader32); 357837ae69fSSean Fertile } 358837ae69fSSean Fertile 359837ae69fSSean Fertile bool XCOFFObjectFile::is64Bit() const { 360837ae69fSSean Fertile return Binary::ID_XCOFF64 == getType(); 361837ae69fSSean Fertile } 362837ae69fSSean Fertile 363837ae69fSSean Fertile uint16_t XCOFFObjectFile::getMagic() const { 364837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; 365837ae69fSSean Fertile } 366837ae69fSSean Fertile 367837ae69fSSean Fertile Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { 368837ae69fSSean Fertile if (Num <= 0 || Num > getNumberOfSections()) 369837ae69fSSean Fertile return errorCodeToError(object_error::invalid_section_index); 370837ae69fSSean Fertile 371837ae69fSSean Fertile DataRefImpl DRI; 372837ae69fSSean Fertile DRI.p = getWithOffset(getSectionHeaderTableAddress(), 373837ae69fSSean Fertile getSectionHeaderSize() * (Num - 1)); 374837ae69fSSean Fertile return DRI; 3759212206dSJason Liu } 3769212206dSJason Liu 3779212206dSJason Liu Expected<StringRef> 3789212206dSJason Liu XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const { 379837ae69fSSean Fertile assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); 3809212206dSJason Liu int16_t SectionNum = SymEntPtr->SectionNumber; 3819212206dSJason Liu 3829212206dSJason Liu switch (SectionNum) { 3839212206dSJason Liu case XCOFF::N_DEBUG: 3849212206dSJason Liu return "N_DEBUG"; 3859212206dSJason Liu case XCOFF::N_ABS: 3869212206dSJason Liu return "N_ABS"; 3879212206dSJason Liu case XCOFF::N_UNDEF: 3889212206dSJason Liu return "N_UNDEF"; 389837ae69fSSean Fertile default: 390837ae69fSSean Fertile Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); 391837ae69fSSean Fertile if (SecRef) 39229141da7SSean Fertile return generateStringRef(getSectionNameInternal(SecRef.get())); 393837ae69fSSean Fertile return SecRef.takeError(); 3949212206dSJason Liu } 3959212206dSJason Liu } 3969212206dSJason Liu 3979212206dSJason Liu bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 3989212206dSJason Liu return (SectionNumber <= 0 && SectionNumber >= -2); 3999212206dSJason Liu } 4009212206dSJason Liu 4019212206dSJason Liu uint16_t XCOFFObjectFile::getNumberOfSections() const { 402837ae69fSSean Fertile return is64Bit() ? fileHeader64()->NumberOfSections 403837ae69fSSean Fertile : fileHeader32()->NumberOfSections; 4049212206dSJason Liu } 4059212206dSJason Liu 406837ae69fSSean Fertile int32_t XCOFFObjectFile::getTimeStamp() const { 407837ae69fSSean Fertile return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 4089212206dSJason Liu } 4099212206dSJason Liu 4109212206dSJason Liu uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 411837ae69fSSean Fertile return is64Bit() ? fileHeader64()->AuxHeaderSize 412837ae69fSSean Fertile : fileHeader32()->AuxHeaderSize; 4139212206dSJason Liu } 4149212206dSJason Liu 415837ae69fSSean Fertile uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 416837ae69fSSean Fertile return fileHeader32()->SymbolTableOffset; 417837ae69fSSean Fertile } 418ab2eb2bfSHubert Tong 419837ae69fSSean Fertile int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 420837ae69fSSean Fertile // As far as symbol table size is concerned, if this field is negative it is 421837ae69fSSean Fertile // to be treated as a 0. However since this field is also used for printing we 422837ae69fSSean Fertile // don't want to truncate any negative values. 423837ae69fSSean Fertile return fileHeader32()->NumberOfSymTableEntries; 424837ae69fSSean Fertile } 425ab2eb2bfSHubert Tong 426837ae69fSSean Fertile uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 427837ae69fSSean Fertile return (fileHeader32()->NumberOfSymTableEntries >= 0 428837ae69fSSean Fertile ? fileHeader32()->NumberOfSymTableEntries 429837ae69fSSean Fertile : 0); 430837ae69fSSean Fertile } 431a93a33cbSSean Fertile 432837ae69fSSean Fertile uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 433837ae69fSSean Fertile return fileHeader64()->SymbolTableOffset; 434837ae69fSSean Fertile } 435837ae69fSSean Fertile 436837ae69fSSean Fertile uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 437837ae69fSSean Fertile return fileHeader64()->NumberOfSymTableEntries; 438837ae69fSSean Fertile } 439837ae69fSSean Fertile 440837ae69fSSean Fertile uint16_t XCOFFObjectFile::getFlags() const { 441837ae69fSSean Fertile return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 442837ae69fSSean Fertile } 443837ae69fSSean Fertile 444837ae69fSSean Fertile const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 445837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 446837ae69fSSean Fertile } 447837ae69fSSean Fertile 448837ae69fSSean Fertile uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 449837ae69fSSean Fertile return reinterpret_cast<uintptr_t>(SectionHeaderTable); 450837ae69fSSean Fertile } 451837ae69fSSean Fertile 452837ae69fSSean Fertile int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 453837ae69fSSean Fertile return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 454837ae69fSSean Fertile } 455837ae69fSSean Fertile 456837ae69fSSean Fertile XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 457837ae69fSSean Fertile : ObjectFile(Type, Object) { 458837ae69fSSean Fertile assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 459837ae69fSSean Fertile } 460837ae69fSSean Fertile 461837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 462837ae69fSSean Fertile assert(is64Bit() && "64-bit interface called for non 64-bit file."); 463837ae69fSSean Fertile const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 464837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader64>(TablePtr, 465837ae69fSSean Fertile TablePtr + getNumberOfSections()); 466837ae69fSSean Fertile } 467837ae69fSSean Fertile 468837ae69fSSean Fertile ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 469837ae69fSSean Fertile assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 470837ae69fSSean Fertile const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 471837ae69fSSean Fertile return ArrayRef<XCOFFSectionHeader32>(TablePtr, 472837ae69fSSean Fertile TablePtr + getNumberOfSections()); 473837ae69fSSean Fertile } 474837ae69fSSean Fertile 475837ae69fSSean Fertile Expected<XCOFFStringTable> 476837ae69fSSean Fertile XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 477837ae69fSSean Fertile // If there is a string table, then the buffer must contain at least 4 bytes 478837ae69fSSean Fertile // for the string table's size. Not having a string table is not an error. 479837ae69fSSean Fertile if (auto EC = Binary::checkOffset( 480837ae69fSSean Fertile Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) 481837ae69fSSean Fertile return XCOFFStringTable{0, nullptr}; 482837ae69fSSean Fertile 483837ae69fSSean Fertile // Read the size out of the buffer. 484837ae69fSSean Fertile uint32_t Size = support::endian::read32be(Obj->base() + Offset); 485837ae69fSSean Fertile 486837ae69fSSean Fertile // If the size is less then 4, then the string table is just a size and no 487837ae69fSSean Fertile // string data. 488837ae69fSSean Fertile if (Size <= 4) 489837ae69fSSean Fertile return XCOFFStringTable{4, nullptr}; 490837ae69fSSean Fertile 491837ae69fSSean Fertile auto StringTableOrErr = 492837ae69fSSean Fertile getObject<char>(Obj->Data, Obj->base() + Offset, Size); 493837ae69fSSean Fertile if (Error E = StringTableOrErr.takeError()) 494837ae69fSSean Fertile return std::move(E); 495837ae69fSSean Fertile 496837ae69fSSean Fertile const char *StringTablePtr = StringTableOrErr.get(); 497837ae69fSSean Fertile if (StringTablePtr[Size - 1] != '\0') 498837ae69fSSean Fertile return errorCodeToError(object_error::string_table_non_null_end); 499837ae69fSSean Fertile 500837ae69fSSean Fertile return XCOFFStringTable{Size, StringTablePtr}; 501837ae69fSSean Fertile } 502837ae69fSSean Fertile 503837ae69fSSean Fertile Expected<std::unique_ptr<XCOFFObjectFile>> 504837ae69fSSean Fertile XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 505*0eaee545SJonas Devlieghere // Can't use std::make_unique because of the private constructor. 506837ae69fSSean Fertile std::unique_ptr<XCOFFObjectFile> Obj; 507837ae69fSSean Fertile Obj.reset(new XCOFFObjectFile(Type, MBR)); 508837ae69fSSean Fertile 509837ae69fSSean Fertile uint64_t CurOffset = 0; 510837ae69fSSean Fertile const auto *Base = Obj->base(); 511837ae69fSSean Fertile MemoryBufferRef Data = Obj->Data; 512837ae69fSSean Fertile 513837ae69fSSean Fertile // Parse file header. 514837ae69fSSean Fertile auto FileHeaderOrErr = 515837ae69fSSean Fertile getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 516837ae69fSSean Fertile if (Error E = FileHeaderOrErr.takeError()) 517837ae69fSSean Fertile return std::move(E); 518837ae69fSSean Fertile Obj->FileHeader = FileHeaderOrErr.get(); 519837ae69fSSean Fertile 520837ae69fSSean Fertile CurOffset += Obj->getFileHeaderSize(); 521a93a33cbSSean Fertile // TODO FIXME we don't have support for an optional header yet, so just skip 522a93a33cbSSean Fertile // past it. 523837ae69fSSean Fertile CurOffset += Obj->getOptionalHeaderSize(); 524a93a33cbSSean Fertile 525837ae69fSSean Fertile // Parse the section header table if it is present. 526837ae69fSSean Fertile if (Obj->getNumberOfSections()) { 527837ae69fSSean Fertile auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, 528837ae69fSSean Fertile Obj->getNumberOfSections() * 529837ae69fSSean Fertile Obj->getSectionHeaderSize()); 530837ae69fSSean Fertile if (Error E = SecHeadersOrErr.takeError()) 531837ae69fSSean Fertile return std::move(E); 532837ae69fSSean Fertile Obj->SectionHeaderTable = SecHeadersOrErr.get(); 533a93a33cbSSean Fertile } 534ab2eb2bfSHubert Tong 535837ae69fSSean Fertile // 64-bit object supports only file header and section headers for now. 536837ae69fSSean Fertile if (Obj->is64Bit()) 537837ae69fSSean Fertile return std::move(Obj); 538fd75ee91SSean Fertile 539837ae69fSSean Fertile // If there is no symbol table we are done parsing the memory buffer. 540837ae69fSSean Fertile if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0) 541837ae69fSSean Fertile return std::move(Obj); 542837ae69fSSean Fertile 543837ae69fSSean Fertile // Parse symbol table. 544837ae69fSSean Fertile CurOffset = Obj->fileHeader32()->SymbolTableOffset; 5459212206dSJason Liu uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) * 546837ae69fSSean Fertile Obj->getLogicalNumberOfSymbolTableEntries32(); 547837ae69fSSean Fertile auto SymTableOrErr = 548837ae69fSSean Fertile getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize); 549837ae69fSSean Fertile if (Error E = SymTableOrErr.takeError()) 550837ae69fSSean Fertile return std::move(E); 551837ae69fSSean Fertile Obj->SymbolTblPtr = SymTableOrErr.get(); 552837ae69fSSean Fertile CurOffset += SymbolTableSize; 553fd75ee91SSean Fertile 554837ae69fSSean Fertile // Parse String table. 555837ae69fSSean Fertile Expected<XCOFFStringTable> StringTableOrErr = 556837ae69fSSean Fertile parseStringTable(Obj.get(), CurOffset); 557837ae69fSSean Fertile if (Error E = StringTableOrErr.takeError()) 558837ae69fSSean Fertile return std::move(E); 559837ae69fSSean Fertile Obj->StringTable = StringTableOrErr.get(); 560fd75ee91SSean Fertile 561837ae69fSSean Fertile return std::move(Obj); 562fd75ee91SSean Fertile } 563fd75ee91SSean Fertile 564ab2eb2bfSHubert Tong Expected<std::unique_ptr<ObjectFile>> 565837ae69fSSean Fertile ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 566837ae69fSSean Fertile unsigned FileType) { 567837ae69fSSean Fertile return XCOFFObjectFile::create(FileType, MemBufRef); 568ab2eb2bfSHubert Tong } 569ab2eb2bfSHubert Tong 570837ae69fSSean Fertile StringRef XCOFFSectionHeader32::getName() const { 57129141da7SSean Fertile return generateStringRef(Name); 572837ae69fSSean Fertile } 573837ae69fSSean Fertile 574837ae69fSSean Fertile StringRef XCOFFSectionHeader64::getName() const { 57529141da7SSean Fertile return generateStringRef(Name); 576ab2eb2bfSHubert Tong } 577ab2eb2bfSHubert Tong 578ab2eb2bfSHubert Tong } // namespace object 579ab2eb2bfSHubert Tong } // namespace llvm 580