Index: llvm/include/llvm/BinaryFormat/XCOFF.h =================================================================== --- llvm/include/llvm/BinaryFormat/XCOFF.h +++ llvm/include/llvm/BinaryFormat/XCOFF.h @@ -292,6 +292,15 @@ TCPU_970 = 19 ///< PPC970 - PowerPC 64-bit architecture. }; +enum SymbolAuxType : uint8_t { + AUX_EXCEPT = 255, ///< Identifies an exception auxiliary entry. + AUX_FCN = 254, ///< Identifies a function auxiliary entry. + AUX_SYM = 253, ///< Identifies a symbol auxiliary entry. + AUX_FILE = 252, ///< Identifies a file auxiliary entry. + AUX_CSECT = 251, ///< Identifies a csect auxiliary entry. + AUX_SECT = 250 ///< Identifies a SECT auxiliary entry. +}; // 64-bit XCOFF file only. + StringRef getMappingClassString(XCOFF::StorageMappingClass SMC); StringRef getRelocationTypeString(XCOFF::RelocationType Type); Index: llvm/include/llvm/Object/XCOFFObjectFile.h =================================================================== --- llvm/include/llvm/Object/XCOFFObjectFile.h +++ llvm/include/llvm/Object/XCOFFObjectFile.h @@ -97,68 +97,120 @@ char Padding[4]; }; -struct XCOFFSymbolEntry { - enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; - typedef struct { - support::big32_t Magic; // Zero indicates name in string table. - support::ubig32_t Offset; - } NameInStrTblType; - - typedef struct { - uint8_t LanguageId; - uint8_t CpuTypeId; - } CFileLanguageIdAndTypeIdType; - - union { - char SymbolName[XCOFF::NameSize]; - NameInStrTblType NameInStrTbl; - }; - - support::ubig32_t Value; // Symbol value; storage class-dependent. - support::big16_t SectionNumber; - - union { - support::ubig16_t SymbolType; - CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; - }; - - XCOFF::StorageClass StorageClass; - uint8_t NumberOfAuxEntries; -}; - struct XCOFFStringTable { uint32_t Size; const char *Data; }; struct XCOFFCsectAuxEnt32 { - static constexpr uint8_t SymbolTypeMask = 0x07; - static constexpr uint8_t SymbolAlignmentMask = 0xF8; - static constexpr size_t SymbolAlignmentBitOffset = 3; - - support::ubig32_t - SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect - // length. - // If the symbol type is XTY_LD, the symbol table - // index of the containing csect. - // If the symbol type is XTY_ER, 0. + support::ubig32_t SectionOrLength; support::ubig32_t ParameterHashIndex; support::ubig16_t TypeChkSectNum; uint8_t SymbolAlignmentAndType; XCOFF::StorageMappingClass StorageMappingClass; support::ubig32_t StabInfoIndex; support::ubig16_t StabSectNum; +}; + +struct XCOFFCsectAuxEnt64 { + support::ubig32_t SectionOrLengthLowByte; + support::ubig32_t ParameterHashIndex; + support::ubig16_t TypeChkSectNum; + uint8_t SymbolAlignmentAndType; + XCOFF::StorageMappingClass StorageMappingClass; + support::ubig32_t SectionOrLengthHighByte; + uint8_t Pad; + XCOFF::SymbolAuxType AuxType; +}; + +class XCOFFCsectAuxRef { +public: + static constexpr uint8_t SymbolTypeMask = 0x07; + static constexpr uint8_t SymbolAlignmentMask = 0xF8; + static constexpr size_t SymbolAlignmentBitOffset = 3; + + XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {} + XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {} + + // For getSectionOrLength(), + // If the symbol type is XTY_SD or XTY_CM, the csect length. + // If the symbol type is XTY_LD, the symbol table + // index of the containing csect. + // If the symbol type is XTY_ER, 0. + uint64_t getSectionOrLength() const { + return Entry32 ? getSectionOrLength32() : getSectionOrLength64(); + } + + uint32_t getSectionOrLength32() const { + assert(Entry32 && "32-bit interface called on 64-bit object file."); + return Entry32->SectionOrLength; + } + + uint64_t getSectionOrLength64() const { + assert(Entry64 && "64-bit interface called on 32-bit object file."); + return (static_cast(Entry64->SectionOrLengthHighByte) << 32) | + Entry64->SectionOrLengthLowByte; + } + + uint32_t getParameterHashIndex() const { + if (Entry32) + return Entry32->ParameterHashIndex; + return Entry64->ParameterHashIndex; + } + + uint16_t getTypeChkSectNum() const { + if (Entry32) + return Entry32->TypeChkSectNum; + return Entry64->TypeChkSectNum; + } + + XCOFF::StorageMappingClass getStorageMappingClass() const { + if (Entry32) + return Entry32->StorageMappingClass; + return Entry64->StorageMappingClass; + } + + uintptr_t getAddress() const { + if (Entry32) + return reinterpret_cast(Entry32); + return reinterpret_cast(Entry64); + } uint16_t getAlignmentLog2() const { - return (SymbolAlignmentAndType & SymbolAlignmentMask) >> + return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >> SymbolAlignmentBitOffset; } uint8_t getSymbolType() const { - return SymbolAlignmentAndType & SymbolTypeMask; + return getSymbolAlignmentAndType() & SymbolTypeMask; } bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; } + + uint32_t getStabInfoIndex32() const { + assert(Entry32 && "32-bit interface called on 64-bit object file."); + return Entry32->StabInfoIndex; + } + + uint16_t getStabSectNum32() const { + assert(Entry32 && "32-bit interface called on 64-bit object file."); + return Entry32->StabSectNum; + } + + XCOFF::SymbolAuxType getAuxType64() const { + assert(Entry64 && "64-bit interface called on 32-bit object file."); + return Entry64->AuxType; + } + +private: + uint8_t getSymbolAlignmentAndType() const { + if (Entry32) + return Entry32->SymbolAlignmentAndType; + return Entry64->SymbolAlignmentAndType; + } + + const XCOFFCsectAuxEnt32 *Entry32 = nullptr; + const XCOFFCsectAuxEnt64 *Entry64 = nullptr; }; struct XCOFFFileAuxEnt { @@ -173,7 +225,7 @@ }; XCOFF::CFileStringType Type; uint8_t ReservedZeros[2]; - uint8_t AuxType; // 64-bit XCOFF file only. + XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only. }; struct XCOFFSectAuxEntForStat { @@ -181,7 +233,7 @@ support::ubig16_t NumberOfRelocEnt; support::ubig16_t NumberOfLineNum; uint8_t Pad[10]; -}; +}; // 32-bit XCOFF file only. struct XCOFFRelocation32 { // Masks for packing/unpacking the r_rsize field of relocations. @@ -215,12 +267,14 @@ uint8_t getRelocatedLength() const; }; +class XCOFFSymbolRef; + class XCOFFObjectFile : public ObjectFile { private: const void *FileHeader = nullptr; const void *SectionHeaderTable = nullptr; - const XCOFFSymbolEntry *SymbolTblPtr = nullptr; + const void *SymbolTblPtr = nullptr; XCOFFStringTable StringTable = {0, nullptr}; const XCOFFFileHeader32 *fileHeader32() const; @@ -242,9 +296,6 @@ // null-terminated. const char *getSectionNameInternal(DataRefImpl Sec) const; - // This function returns string table entry. - Expected getStringTableEntry(uint32_t Offset) const; - static bool isReservedSectionNumber(int16_t SectionNumber); // Constructor and "create" factory function. The constructor is only a thin @@ -322,15 +373,11 @@ // Below here is the non-inherited interface. bool is64Bit() const; - const XCOFFSymbolEntry *getPointerToSymbolTable() const { - assert(!is64Bit() && "Symbol table handling not supported yet."); - return SymbolTblPtr; - } + const void *getPointerToSymbolTable() const { return SymbolTblPtr; } - Expected - getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const; + Expected getSymbolSectionName(XCOFFSymbolRef Ref) const; - const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const; + XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const; // File header related interfaces. uint16_t getMagic() const; @@ -351,6 +398,7 @@ uint32_t getNumberOfSymbolTableEntries64() const; uint32_t getSymbolIndex(uintptr_t SymEntPtr) const; + uintptr_t getSymbolAddressByIndex(uint32_t SymbolTableIndex) const; Expected getSymbolNameByIndex(uint32_t SymbolTableIndex) const; Expected getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const; @@ -372,27 +420,135 @@ Expected> relocations(const XCOFFSectionHeader32 &) const; + // This function returns string table entry. + Expected getStringTableEntry(uint32_t Offset) const; + + static uintptr_t getAdvancedSymbolAddress(uintptr_t CurrentAddress, + uint32_t Distance) { + return reinterpret_cast( + reinterpret_cast(CurrentAddress) + + Distance * XCOFF::SymbolTableEntrySize); + } static bool classof(const Binary *B) { return B->isXCOFF(); } }; // XCOFFObjectFile -class XCOFFSymbolRef { - const DataRefImpl SymEntDataRef; - const XCOFFObjectFile *const OwningObjectPtr; +typedef struct { + uint8_t LanguageId; + uint8_t CpuTypeId; +} CFileLanguageIdAndTypeIdType; + +struct XCOFFSymbolEntry32 { + typedef struct { + support::big32_t Magic; // Zero indicates name in string table. + support::ubig32_t Offset; + } NameInStrTblType; + + union { + char SymbolName[XCOFF::NameSize]; + NameInStrTblType NameInStrTbl; + }; + + support::ubig32_t Value; // Symbol value; storage class-dependent. + support::big16_t SectionNumber; + + union { + support::ubig16_t SymbolType; + CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; + }; + + XCOFF::StorageClass StorageClass; + uint8_t NumberOfAuxEntries; +}; +struct XCOFFSymbolEntry64 { + support::ubig64_t Value; // Symbol value; storage class-dependent. + support::ubig32_t Offset; + support::big16_t SectionNumber; + + union { + support::ubig16_t SymbolType; + CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; + }; + + XCOFF::StorageClass StorageClass; + uint8_t NumberOfAuxEntries; +}; + +class XCOFFSymbolRef { public: + enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; + XCOFFSymbolRef(DataRefImpl SymEntDataRef, const XCOFFObjectFile *OwningObjectPtr) - : SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){}; + : OwningObjectPtr(OwningObjectPtr) { + assert(SymEntDataRef.p != 0 && "Symbol table pointer can not be nullptr!"); + if (OwningObjectPtr->is64Bit()) + Entry64 = reinterpret_cast(SymEntDataRef.p); + else + Entry32 = reinterpret_cast(SymEntDataRef.p); + } + + uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); } - XCOFF::StorageClass getStorageClass() const; - uint8_t getNumberOfAuxEntries() const; - const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const; - uint16_t getType() const; - int16_t getSectionNumber() const; + uint32_t getValue32() const { return Entry32->Value; } + uint64_t getValue64() const { return Entry64->Value; } - bool hasCsectAuxEnt() const; + int16_t getSectionNumber() const { + if (Entry32) + return Entry32->SectionNumber; + return Entry64->SectionNumber; + } + + uint16_t getSymbolType() const { + if (Entry32) + return Entry32->SymbolType; + return Entry64->SymbolType; + } + + uint8_t getLanguageIdForCFile() const { + assert(getStorageClass() == XCOFF::C_FILE && + "This interface is for C_FILE only."); + if (Entry32) + return Entry32->CFileLanguageIdAndTypeId.LanguageId; + return Entry64->CFileLanguageIdAndTypeId.LanguageId; + } + + uint8_t getCPUTypeIddForCFile() const { + assert(getStorageClass() == XCOFF::C_FILE && + "This interface is for C_FILE only."); + if (Entry32) + return Entry32->CFileLanguageIdAndTypeId.CpuTypeId; + return Entry64->CFileLanguageIdAndTypeId.CpuTypeId; + } + + XCOFF::StorageClass getStorageClass() const { + if (Entry32) + return Entry32->StorageClass; + return Entry64->StorageClass; + } + + uint8_t getNumberOfAuxEntries() const { + if (Entry32) + return Entry32->NumberOfAuxEntries; + return Entry64->NumberOfAuxEntries; + } + + uintptr_t getAddress() const { + if (Entry32) + return reinterpret_cast(Entry32); + return reinterpret_cast(Entry64); + } + + Expected getName() const; bool isFunction() const; + bool isCsectSymbol() const; + Expected getXCOFFCsectAuxRef() const; + +private: + const XCOFFObjectFile *OwningObjectPtr; + const XCOFFSymbolEntry32 *Entry32 = nullptr; + const XCOFFSymbolEntry64 *Entry64 = nullptr; }; /// This class provides methods to extract traceback table data from a buffer. Index: llvm/lib/Object/XCOFFObjectFile.cpp =================================================================== --- llvm/lib/Object/XCOFFObjectFile.cpp +++ llvm/lib/Object/XCOFFObjectFile.cpp @@ -25,6 +25,7 @@ static const uint8_t FunctionSym = 0x20; static const uint8_t SymTypeMask = 0x07; static const uint16_t NoRelMask = 0x0001; +static const size_t SymbolAuxTypeOffset = 17; // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer // 'M'. Returns a pointer to the underlying object on success. @@ -114,14 +115,12 @@ return viewAs(Ref.p); } -const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); +XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const { assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); #ifndef NDEBUG checkSymbolEntryPointer(Ref.p); #endif - auto SymEntPtr = viewAs(Ref.p); - return SymEntPtr; + return XCOFFSymbolRef(Ref, this); } const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { @@ -147,15 +146,15 @@ } void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { - const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); - SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1; + uintptr_t NextSymbolAddr = getAdvancedSymbolAddress( + Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1); #ifndef NDEBUG // This function is used by basic_symbol_iterator, which allows to // point to the end-of-symbol-table address. - if (reinterpret_cast(SymEntPtr) != getEndOfSymbolTableAddress()) - checkSymbolEntryPointer(reinterpret_cast(SymEntPtr)); + if (NextSymbolAddr != getEndOfSymbolTableAddress()) + checkSymbolEntryPointer(NextSymbolAddr); #endif - Symb.p = reinterpret_cast(SymEntPtr); + Symb.p = NextSymbolAddr; } Expected @@ -177,34 +176,21 @@ Expected XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { - if (CFileEntPtr->NameInStrTbl.Magic != - XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) + if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) return generateXCOFFFixedNameStringRef(CFileEntPtr->Name); return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset); } Expected XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { - const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); - - // A storage class value with the high-order bit on indicates that the name is - // a symbolic debugger stabstring. - if (SymEntPtr->StorageClass & 0x80) - return StringRef("Unimplemented Debug Name"); - - if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) - return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName); - - return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset); + return toSymbolRef(Symb).getName(); } Expected XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); - return toSymbolEntry(Symb)->Value; + return toSymbolRef(Symb).getValue(); } uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); - return toSymbolEntry(Symb)->Value; + return toSymbolRef(Symb).getValue(); } uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { @@ -221,8 +207,7 @@ Expected XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { - const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); - int16_t SectNum = SymEntPtr->SectionNumber; + int16_t SectNum = toSymbolRef(Symb).getSectionNumber(); if (isReservedSectionNumber(SectNum)) return section_end(); @@ -377,7 +362,7 @@ return symbol_end(); DataRefImpl SymDRI; - SymDRI.p = reinterpret_cast(getPointerToSymbolTable() + Index); + SymDRI.p = getSymbolAddressByIndex(Index); return symbol_iterator(SymbolRef(SymDRI, this)); } @@ -403,19 +388,17 @@ } basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); DataRefImpl SymDRI; SymDRI.p = reinterpret_cast(SymbolTblPtr); return basic_symbol_iterator(SymbolRef(SymDRI, this)); } basic_symbol_iterator XCOFFObjectFile::symbol_end() const { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); DataRefImpl SymDRI; - SymDRI.p = reinterpret_cast( - SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32()); + const uint32_t NumberOfSymbolTableEntries = + is64Bit() ? getNumberOfSymbolTableEntries64() + : getLogicalNumberOfSymbolTableEntries32(); + SymDRI.p = getSymbolAddressByIndex(NumberOfSymbolTableEntries); return basic_symbol_iterator(SymbolRef(SymDRI, this)); } @@ -486,9 +469,8 @@ } Expected -XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const { - assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); - int16_t SectionNum = SymEntPtr->SectionNumber; +XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { + int16_t SectionNum = SymEntPtr.getSectionNumber(); switch (SectionNum) { case XCOFF::N_DEBUG: @@ -578,16 +560,22 @@ XCOFF::SymbolTableEntrySize; } +uintptr_t XCOFFObjectFile::getSymbolAddressByIndex(uint32_t Index) const { + return getAdvancedSymbolAddress( + reinterpret_cast(getPointerToSymbolTable()), Index); +} + Expected XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { - if (is64Bit()) - report_fatal_error("64-bit symbol table support not implemented yet."); + const uint32_t NumberOfSymTableEntries = + is64Bit() ? getNumberOfSymbolTableEntries64() + : getLogicalNumberOfSymbolTableEntries32(); - if (Index >= getLogicalNumberOfSymbolTableEntries32()) + if (Index >= NumberOfSymTableEntries) return errorCodeToError(object_error::invalid_symbol_index); DataRefImpl SymDRI; - SymDRI.p = reinterpret_cast(getPointerToSymbolTable() + Index); + SymDRI.p = getSymbolAddressByIndex(Index); return getSymbolName(SymDRI); } @@ -729,20 +717,21 @@ Obj->SectionHeaderTable = SecHeadersOrErr.get(); } - // 64-bit object supports only file header and section headers for now. - if (Obj->is64Bit()) - return std::move(Obj); - + const uint32_t NumberOfSymbolTableEntries = + Obj->is64Bit() ? Obj->getNumberOfSymbolTableEntries64() + : Obj->getLogicalNumberOfSymbolTableEntries32(); // If there is no symbol table we are done parsing the memory buffer. - if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0) + if (NumberOfSymbolTableEntries == 0) return std::move(Obj); // Parse symbol table. - CurOffset = Obj->fileHeader32()->SymbolTableOffset; - uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) * - Obj->getLogicalNumberOfSymbolTableEntries32(); + CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() + : Obj->getSymbolTableOffset32(); + uint64_t SymbolTableSize = + static_cast(XCOFF::SymbolTableEntrySize) * + NumberOfSymbolTableEntries; auto SymTableOrErr = - getObject(Data, Base + CurOffset, SymbolTableSize); + getObject(Data, Base + CurOffset, SymbolTableSize); if (Error E = SymTableOrErr.takeError()) return std::move(E); Obj->SymbolTblPtr = SymTableOrErr.get(); @@ -764,74 +753,92 @@ return XCOFFObjectFile::create(FileType, MemBufRef); } -XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass; -} +bool XCOFFSymbolRef::isFunction() const { + if (!isCsectSymbol()) + return false; -uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries; -} + if (getSymbolType() & FunctionSym) + return true; -// TODO: The function needs to return an error if there is no csect auxiliary -// entry. -const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const { - assert(!OwningObjectPtr->is64Bit() && - "32-bit interface called on 64-bit object file."); - assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found."); + Expected ExpCsectAuxEnt = getXCOFFCsectAuxRef(); + if (!ExpCsectAuxEnt) + return false; - // In XCOFF32, the csect auxilliary entry is always the last auxiliary - // entry for the symbol. - uintptr_t AuxAddr = getWithOffset( - SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries()); + const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); -#ifndef NDEBUG - OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); -#endif + // A function definition should be a label definition. + if (CsectAuxRef.isLabel()) + return false; - return reinterpret_cast(AuxAddr); -} + if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) + return false; -uint16_t XCOFFSymbolRef::getType() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType; -} + int16_t SectNum = getSectionNumber(); + Expected SI = OwningObjectPtr->getSectionByNum(SectNum); + if (!SI) { + consumeError(std::move(SI.takeError())); + return false; + } -int16_t XCOFFSymbolRef::getSectionNumber() const { - return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber; + return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); } -// TODO: The function name needs to be changed to express the purpose of the -// function. -bool XCOFFSymbolRef::hasCsectAuxEnt() const { +bool XCOFFSymbolRef::isCsectSymbol() const { XCOFF::StorageClass SC = getStorageClass(); return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || SC == XCOFF::C_HIDEXT); } -bool XCOFFSymbolRef::isFunction() const { - if (OwningObjectPtr->is64Bit()) - report_fatal_error("64-bit support is unimplemented yet."); +Expected XCOFFSymbolRef::getXCOFFCsectAuxRef() const { + if (!isCsectSymbol()) + return createStringError( + object_error::parse_failed, + "this symbol entry type could not have a csect auxiliary entry"); - if (getType() & FunctionSym) - return true; + if (!OwningObjectPtr->is64Bit()) { + // In XCOFF32, the csect auxilliary entry is always the last auxiliary + // entry for the symbol. + uintptr_t AuxAddr = getWithOffset( + getAddress(), XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries()); + return XCOFFCsectAuxRef(viewAs(AuxAddr)); + } - if (!hasCsectAuxEnt()) - return false; + auto getSymbolAuxType = [this](uintptr_t AuxAddr) { + return viewAs( + getWithOffset(AuxAddr, SymbolAuxTypeOffset)); + }; + + // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. + // We need to iterate through all the auxiliary entries to find it. + for (uint8_t Index = getNumberOfAuxEntries(); Index > 0; --Index) { + uintptr_t AuxAddr = + getWithOffset(getAddress(), XCOFF::SymbolTableEntrySize * Index); + if (*getSymbolAuxType(AuxAddr) == XCOFF::SymbolAuxType::AUX_CSECT) { +#ifndef NDEBUG + OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); +#endif + return XCOFFCsectAuxRef(viewAs(AuxAddr)); + } + } - const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32(); + return createStringError(object_error::parse_failed, + "a csect auxiliary entry is not found"); +} - // A function definition should be a label definition. - if ((CsectAuxEnt->SymbolAlignmentAndType & SymTypeMask) != XCOFF::XTY_LD) - return false; +Expected XCOFFSymbolRef::getName() const { + // A storage class value with the high-order bit on indicates that the name is + // a symbolic debugger stabstring. + if (getStorageClass() & 0x80) + return StringRef("Unimplemented Debug Name"); - if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR) - return false; + if (Entry32) { + if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) + return generateXCOFFFixedNameStringRef(Entry32->SymbolName); - int16_t SectNum = getSectionNumber(); - Expected SI = OwningObjectPtr->getSectionByNum(SectNum); - if (!SI) - return false; + return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); + } - return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); + return OwningObjectPtr->getStringTableEntry(Entry64->Offset); } // Explictly instantiate template classes. Index: llvm/test/tools/llvm-objdump/XCOFF/disassemble-symbol-description64.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objdump/XCOFF/disassemble-symbol-description64.test @@ -0,0 +1,96 @@ +# REQUIRES: powerpc-registered-target + +# RUN: llvm-objdump -D %p/Inputs/xcoff-section-headers64.o | \ +# RUN: FileCheck --check-prefixes=COMMON,PLAIN %s + +# RUN: llvm-objdump -D --symbol-description %p/Inputs/xcoff-section-headers64.o | \ +# RUN: FileCheck --check-prefixes=COMMON,DESC %s + +# RUN: not --crash llvm-objdump -D -r --symbol-description %p/Inputs/xcoff-section-headers64.o 2>&1 | \ +# RUN: FileCheck --check-prefix=ERROR %s +# ERROR: 64-bit support not implemented yet + +## xcoff-section-headers64.o Compiled with IBM XL C/C++ for AIX, V16.1.0 +## compiler command: xlc -q64 -qtls -o xcoff-section-headers64.o -c test.c + +## test.c: +## int a; +## int b = 12345; +## __thread int c; +## __thread double d = 3.14159; +## +## int func(void) { +## return a; +## } + +COMMON: Inputs/xcoff-section-headers64.o: file format aix5coff64-rs6000 +COMMON: Disassembly of section .text: +COMMON-EMPTY: +PLAIN: 0000000000000000 <.func>: +DESC: 0000000000000000 (idx: 6) .func: +COMMON-NEXT: 0: e8 62 00 08 ld 3, 8(2) +COMMON-NEXT: 4: e8 63 00 02 lwa 3, 0(3) +COMMON-NEXT: 8: 4e 80 00 20 blr +COMMON-NEXT: c: 00 00 00 00 +COMMON-NEXT: 10: 00 00 20 40 +COMMON-NEXT: 14: 00 00 00 01 +COMMON-NEXT: 18: 00 00 00 0c +COMMON-NEXT: 1c: 00 04 66 75 +COMMON-NEXT: 20: 6e 63 00 00 xoris 3, 19, 0 +COMMON-NEXT: ... +COMMON-EMPTY: +COMMON-NEXT: Disassembly of section .data: +COMMON-EMPTY: +PLAIN: 0000000000000080 : +DESC: 0000000000000080 (idx: 12) func[TC]: +COMMON-NEXT: 80: 00 00 00 00 +COMMON-NEXT: 84: 00 00 00 a8 +COMMON-EMPTY: +PLAIN: 0000000000000088 : +DESC: 0000000000000088 (idx: 16) a[TC]: +COMMON-NEXT: 88: 00 00 00 00 +COMMON-NEXT: 8c: 00 00 00 c8 +COMMON-EMPTY: +PLAIN: 0000000000000090 : +DESC: 0000000000000090 (idx: 20) b[TC]: +COMMON-NEXT: 90: 00 00 00 00 +COMMON-NEXT: 94: 00 00 00 c0 +COMMON-EMPTY: +PLAIN: 0000000000000098 : +DESC: 0000000000000098 (idx: 24) c[TC]: +COMMON-NEXT: 98: 00 00 00 00 +COMMON-NEXT: 9c: 00 00 00 08 +COMMON-EMPTY: +PLAIN: 00000000000000a0 : +DESC: 00000000000000a0 (idx: 28) d[TC]: +COMMON-NEXT: ... +COMMON-EMPTY: +PLAIN: 00000000000000a8 : +DESC: 00000000000000a8 (idx: 10) func[DS]: +COMMON-NEXT: ... +COMMON-NEXT: b4: 00 00 00 80 +COMMON-NEXT: ... +COMMON-EMPTY: +PLAIN: 00000000000000c0 : +DESC: 00000000000000c0 (idx: 18) b[RW]: +COMMON-NEXT: c0: 00 00 30 39 +COMMON-NEXT: c4: 00 00 00 00 +COMMON-EMPTY: +COMMON-NEXT: Disassembly of section .bss: +COMMON-EMPTY: +PLAIN: 00000000000000c8 : +DESC: 00000000000000c8 (idx: 14) a[RW]: +COMMON-NEXT: ... +COMMON-EMPTY: +COMMON-NEXT: Disassembly of section .tdata: +COMMON-EMPTY: +PLAIN: 0000000000000000 : +DESC: 0000000000000000 (idx: 26) d[TL]: +COMMON-NEXT: 0: 40 09 21 f9 bdnzfl 9, 0x21f8 +COMMON-NEXT: 4: f0 1b 86 6e +COMMON-EMPTY: +COMMON-NEXT: Disassembly of section .tbss: +COMMON-EMPTY: +PLAIN: 0000000000000008 : +DESC: 0000000000000008 (idx: 22) c[UL]: +COMMON-NEXT: ... Index: llvm/test/tools/llvm-readobj/XCOFF/symbols64.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-readobj/XCOFF/symbols64.test @@ -0,0 +1,387 @@ +## This file tests the ability of llvm-readobj to display the symbol table for a +## 64-bit XCOFF object file. +## The object file used is generated by the following source file +## and command on AIX: +## +## > cat test8.c +## +## extern int i; +## extern int TestforXcoff; +## extern int fun(int i); +## static int static_i; +## char* p="abcd"; +## int fun1(int j) { +## static_i++; +## j++; +## j=j+*p; +## return j; +## } +## +## int main() { +## i++; +## fun(i); +## return fun1(i); +## } +## +## > xlc -q64 -c test8.c -o symbol64.o + +# RUN: llvm-readobj --symbols %p/Inputs/symbol64.o | \ +# RUN: FileCheck --check-prefix=SYMBOL64 %s + +# SYMBOL64: File: {{.*}}symbol64.o +# SYMBOL64-NEXT: Format: aix5coff64-rs6000 +# SYMBOL64-NEXT: Arch: powerpc64 +# SYMBOL64-NEXT: AddressSize: 64bit +# SYMBOL64-NEXT: Symbols [ +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 0 +# SYMBOL64-NEXT: Name: .file +# SYMBOL64-NEXT: Value (SymbolTableIndex): 0x0 +# SYMBOL64-NEXT: Section: N_DEBUG +# SYMBOL64-NEXT: Source Language ID: TB_C (0x0) +# SYMBOL64-NEXT: CPU Version ID: TCPU_PPC64 (0x2) +# SYMBOL64-NEXT: StorageClass: C_FILE (0x67) +# SYMBOL64-NEXT: NumberOfAuxEntries: 3 +# SYMBOL64-NEXT: File Auxiliary Entry { +# SYMBOL64-NEXT: Index: 1 +# SYMBOL64-NEXT: Name: test64.c +# SYMBOL64-NEXT: Type: XFT_FN (0x0) +# SYMBOL64-NEXT: Auxiliary Type: AUX_FILE (0xFC) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: File Auxiliary Entry { +# SYMBOL64-NEXT: Index: 2 +# SYMBOL64-NEXT: Name: Mon Aug 10 16:07:48 2020 +# SYMBOL64-NEXT: Type: XFT_CT (0x1) +# SYMBOL64-NEXT: Auxiliary Type: AUX_FILE (0xFC) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: File Auxiliary Entry { +# SYMBOL64-NEXT: Index: 3 +# SYMBOL64-NEXT: Name: IBM XL C for AIX, Version 16.1.0.6 +# SYMBOL64-NEXT: Type: XFT_CV (0x2) +# SYMBOL64-NEXT: Auxiliary Type: AUX_FILE (0xFC) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 4 +# SYMBOL64-NEXT: Name: +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: .text +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 5 +# SYMBOL64-NEXT: SectionLen: 256 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 7 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 6 +# SYMBOL64-NEXT: Name: .fun1 +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: .text +# SYMBOL64-NEXT: Type: 0x20 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 7 +# SYMBOL64-NEXT: ContainingCsectSymbolIndex: 4 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 0 +# SYMBOL64-NEXT: SymbolType: XTY_LD (0x2) +# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 8 +# SYMBOL64-NEXT: Name: .main +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x80 +# SYMBOL64-NEXT: Section: .text +# SYMBOL64-NEXT: Type: 0x20 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 9 +# SYMBOL64-NEXT: ContainingCsectSymbolIndex: 4 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 0 +# SYMBOL64-NEXT: SymbolType: XTY_LD (0x2) +# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 10 +# SYMBOL64-NEXT: Name: TOC +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x100 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 11 +# SYMBOL64-NEXT: SectionLen: 0 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 2 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_TC0 (0xF) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 12 +# SYMBOL64-NEXT: Name: +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x128 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 13 +# SYMBOL64-NEXT: SectionLen: 8 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 14 +# SYMBOL64-NEXT: Name: +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x168 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 15 +# SYMBOL64-NEXT: SectionLen: 5 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_RO (0x1) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 16 +# SYMBOL64-NEXT: Name: _$STATIC_BSS +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x170 +# SYMBOL64-NEXT: Section: .bss +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 17 +# SYMBOL64-NEXT: SectionLen: 4 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 2 +# SYMBOL64-NEXT: SymbolType: XTY_CM (0x3) +# SYMBOL64-NEXT: StorageMappingClass: XMC_RW (0x5) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 18 +# SYMBOL64-NEXT: Name: _$STATIC_BSS +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x108 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 19 +# SYMBOL64-NEXT: SectionLen: 8 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 20 +# SYMBOL64-NEXT: Name: fun1 +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x130 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 21 +# SYMBOL64-NEXT: SectionLen: 24 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_DS (0xA) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 22 +# SYMBOL64-NEXT: Name: fun1 +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x100 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 23 +# SYMBOL64-NEXT: SectionLen: 8 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 24 +# SYMBOL64-NEXT: Name: p +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x160 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 25 +# SYMBOL64-NEXT: SectionLen: 8 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_RW (0x5) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 26 +# SYMBOL64-NEXT: Name: p +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x110 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 27 +# SYMBOL64-NEXT: SectionLen: 8 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 28 +# SYMBOL64-NEXT: Name: main +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x148 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 29 +# SYMBOL64-NEXT: SectionLen: 24 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_DS (0xA) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 30 +# SYMBOL64-NEXT: Name: main +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x118 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 31 +# SYMBOL64-NEXT: SectionLen: 8 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 32 +# SYMBOL64-NEXT: Name: i +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: N_UNDEF +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 33 +# SYMBOL64-NEXT: SectionLen: 0 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 0 +# SYMBOL64-NEXT: SymbolType: XTY_ER (0x0) +# SYMBOL64-NEXT: StorageMappingClass: XMC_UA (0x4) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 34 +# SYMBOL64-NEXT: Name: i +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x120 +# SYMBOL64-NEXT: Section: .data +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 35 +# SYMBOL64-NEXT: SectionLen: 8 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 3 +# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 36 +# SYMBOL64-NEXT: Name: .fun +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: N_UNDEF +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 37 +# SYMBOL64-NEXT: SectionLen: 0 +# SYMBOL64-NEXT: ParameterHashIndex: 0x0 +# SYMBOL64-NEXT: TypeChkSectNum: 0x0 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 0 +# SYMBOL64-NEXT: SymbolType: XTY_ER (0x0) +# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0) +# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: ] Index: llvm/tools/llvm-objdump/XCOFFDump.cpp =================================================================== --- llvm/tools/llvm-objdump/XCOFFDump.cpp +++ llvm/tools/llvm-objdump/XCOFFDump.cpp @@ -46,22 +46,30 @@ Optional objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile *Obj, const SymbolRef &Sym) { - XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj); + const XCOFFSymbolRef SymRef = Obj->toSymbolRef(Sym.getRawDataRefImpl()); - if (SymRef.hasCsectAuxEnt()) - return SymRef.getXCOFFCsectAuxEnt32()->StorageMappingClass; + if (!SymRef.isCsectSymbol()) + return None; - return None; + auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef(); + if (!CsectAuxEntOrErr) + return None; + + return CsectAuxEntOrErr.get().getStorageMappingClass(); } bool objdump::isLabel(const XCOFFObjectFile *Obj, const SymbolRef &Sym) { - XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj); + const XCOFFSymbolRef SymRef = Obj->toSymbolRef(Sym.getRawDataRefImpl()); + + if (!SymRef.isCsectSymbol()) + return false; - if (SymRef.hasCsectAuxEnt()) - return SymRef.getXCOFFCsectAuxEnt32()->isLabel(); + auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef(); + if (!CsectAuxEntOrErr) + return false; - return false; + return CsectAuxEntOrErr.get().isLabel(); } std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo, Index: llvm/tools/llvm-readobj/XCOFFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -40,7 +40,7 @@ template void printGenericSectionHeader(T &Sec) const; template void printOverflowSectionHeader(T &Sec) const; void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr); - void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr); + void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef); void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr); void printSymbol(const SymbolRef &); void printRelocations(ArrayRef Sections); @@ -164,10 +164,15 @@ #undef ECase }; +static const EnumEntry SymAuxType[] = { +#define ECase(X) \ + { #X, XCOFF::X } + ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE), + ECase(AUX_CSECT), ECase(AUX_SECT) +#undef ECase +}; + void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) { - if (Obj.is64Bit()) - report_fatal_error( - "Printing for File Auxiliary Entry in 64-bit is unimplemented."); StringRef FileName = unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr)); DictScope SymDs(W, "File Auxiliary Entry"); @@ -176,6 +181,12 @@ W.printString("Name", FileName); W.printEnum("Type", static_cast(AuxEntPtr->Type), makeArrayRef(FileStringType)); + if (Obj.is64Bit()) { + if (AuxEntPtr->AuxType != XCOFF::AUX_FILE) + W.startLine() << "!Mismatched auxiliary type: "; + W.printEnum("Auxiliary Type", static_cast(AuxEntPtr->AuxType), + makeArrayRef(SymAuxType)); + } } static const EnumEntry CsectStorageMappingClass[] = @@ -199,27 +210,32 @@ #undef ECase }; -void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) { - assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file."); - +void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) { DictScope SymDs(W, "CSECT Auxiliary Entry"); - W.printNumber("Index", - Obj.getSymbolIndex(reinterpret_cast(AuxEntPtr))); - if (AuxEntPtr->isLabel()) - W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength); - else - W.printNumber("SectionLen", AuxEntPtr->SectionOrLength); - W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex); - W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum); + W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getAddress())); + W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex" + : "SectionLen", + AuxEntRef.getSectionOrLength()); + W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex()); + W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum()); // Print out symbol alignment and type. - W.printNumber("SymbolAlignmentLog2", AuxEntPtr->getAlignmentLog2()); - W.printEnum("SymbolType", AuxEntPtr->getSymbolType(), + W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2()); + W.printEnum("SymbolType", AuxEntRef.getSymbolType(), makeArrayRef(CsectSymbolTypeClass)); W.printEnum("StorageMappingClass", - static_cast(AuxEntPtr->StorageMappingClass), + static_cast(AuxEntRef.getStorageMappingClass()), makeArrayRef(CsectStorageMappingClass)); - W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex); - W.printHex("StabSectNum", AuxEntPtr->StabSectNum); + + if (Obj.is64Bit()) { + const XCOFF::SymbolAuxType AuxType = AuxEntRef.getAuxType64(); + if (AuxType != XCOFF::AUX_CSECT) + W.startLine() << "!Mismatched auxiliary type: "; + W.printEnum("Auxiliary Type", static_cast(AuxType), + makeArrayRef(SymAuxType)); + } else { + W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32()); + W.printHex("StabSectNum", AuxEntRef.getStabSectNum32()); + } } void XCOFFDumper::printSectAuxEntForStat( @@ -301,53 +317,49 @@ }; void XCOFFDumper::printSymbol(const SymbolRef &S) { - if (Obj.is64Bit()) - report_fatal_error("64-bit support is unimplemented."); - DataRefImpl SymbolDRI = S.getRawDataRefImpl(); - const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI); + XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI); - XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj); - uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries(); + uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries(); DictScope SymDs(W, "Symbol"); StringRef SymbolName = - unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI)); + unwrapOrError(Obj.getFileName(), SymbolEntRef.getName()); - W.printNumber("Index", - Obj.getSymbolIndex(reinterpret_cast(SymbolEntPtr))); + W.printNumber("Index", Obj.getSymbolIndex(SymbolEntRef.getAddress())); W.printString("Name", SymbolName); - W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass), - SymbolEntPtr->Value); + W.printHex(GetSymbolValueName(SymbolEntRef.getStorageClass()), + SymbolEntRef.getValue()); StringRef SectionName = - unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr)); + unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef)); W.printString("Section", SectionName); - if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) { - W.printEnum("Source Language ID", - SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId, + if (SymbolEntRef.getStorageClass() == XCOFF::C_FILE) { + W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(), makeArrayRef(CFileLangIdClass)); - W.printEnum("CPU Version ID", - SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId, + W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(), makeArrayRef(CFileCpuIdClass)); } else - W.printHex("Type", SymbolEntPtr->SymbolType); + W.printHex("Type", SymbolEntRef.getSymbolType()); - W.printEnum("StorageClass", static_cast(SymbolEntPtr->StorageClass), + W.printEnum("StorageClass", + static_cast(SymbolEntRef.getStorageClass()), makeArrayRef(SymStorageClass)); - W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries); + W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries); if (NumberOfAuxEntries == 0) return; - switch (XCOFFSymRef.getStorageClass()) { + switch (SymbolEntRef.getStorageClass()) { case XCOFF::C_FILE: // If the symbol is C_FILE and has auxiliary entries... for (int i = 1; i <= NumberOfAuxEntries; i++) { const XCOFFFileAuxEnt *FileAuxEntPtr = - reinterpret_cast(SymbolEntPtr + i); + reinterpret_cast( + XCOFFObjectFile::getAdvancedSymbolAddress( + SymbolEntRef.getAddress(), i)); #ifndef NDEBUG Obj.checkSymbolEntryPointer(reinterpret_cast(FileAuxEntPtr)); #endif @@ -356,11 +368,11 @@ break; case XCOFF::C_EXT: case XCOFF::C_WEAKEXT: - case XCOFF::C_HIDEXT: + case XCOFF::C_HIDEXT: { // If the symbol is for a function, and it has more than 1 auxiliary entry, // then one of them must be function auxiliary entry which we do not // support yet. - if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2) + if (SymbolEntRef.isFunction() && NumberOfAuxEntries >= 2) report_fatal_error("Function auxiliary entry printing is unimplemented."); // If there is more than 1 auxiliary entry, instead of printing out @@ -369,21 +381,33 @@ for (int i = 1; i < NumberOfAuxEntries; i++) { W.startLine() << "!Unexpected raw auxiliary entry data:\n"; W.startLine() << format_bytes( - ArrayRef(reinterpret_cast(SymbolEntPtr + i), + ArrayRef(reinterpret_cast( + XCOFFObjectFile::getAdvancedSymbolAddress( + SymbolEntRef.getAddress(), i)), XCOFF::SymbolTableEntrySize)); } - // The symbol's last auxiliary entry is a CSECT Auxiliary Entry. - printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32()); + auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef(); + if (!ErrOrCsectAuxRef) { + handleAllErrors(std::move(ErrOrCsectAuxRef.takeError()), + [this](const StringError &SE) { + W.startLine() << SE.getMessage() << "\n"; + }); + break; + } + + printCsectAuxEnt(ErrOrCsectAuxRef.get()); break; + } case XCOFF::C_STAT: if (NumberOfAuxEntries > 1) report_fatal_error( "C_STAT symbol should not have more than 1 auxiliary entry."); const XCOFFSectAuxEntForStat *StatAuxEntPtr; - StatAuxEntPtr = - reinterpret_cast(SymbolEntPtr + 1); + StatAuxEntPtr = reinterpret_cast( + XCOFFObjectFile::getAdvancedSymbolAddress(SymbolEntRef.getAddress(), + 1)); #ifndef NDEBUG Obj.checkSymbolEntryPointer(reinterpret_cast(StatAuxEntPtr)); #endif @@ -399,7 +423,9 @@ for (int i = 1; i <= NumberOfAuxEntries; i++) { W.startLine() << "!Unexpected raw auxiliary entry data:\n"; W.startLine() << format_bytes( - ArrayRef(reinterpret_cast(SymbolEntPtr + i), + ArrayRef(reinterpret_cast( + XCOFFObjectFile::getAdvancedSymbolAddress( + SymbolEntRef.getAddress(), i)), XCOFF::SymbolTableEntrySize)); } break; Index: llvm/tools/obj2yaml/xcoff2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/xcoff2yaml.cpp +++ llvm/tools/obj2yaml/xcoff2yaml.cpp @@ -55,7 +55,7 @@ for (const SymbolRef &S : Obj.symbols()) { DataRefImpl SymbolDRI = S.getRawDataRefImpl(); - const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI); + const XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI); XCOFFYAML::Symbol Sym; Expected SymNameRefOrErr = Obj.getSymbolName(SymbolDRI); @@ -64,18 +64,18 @@ } Sym.SymbolName = SymNameRefOrErr.get(); - Sym.Value = SymbolEntPtr->Value; + Sym.Value = SymbolEntRef.getValue(); Expected SectionNameRefOrErr = - Obj.getSymbolSectionName(SymbolEntPtr); + Obj.getSymbolSectionName(SymbolEntRef); if (!SectionNameRefOrErr) return errorToErrorCode(SectionNameRefOrErr.takeError()); Sym.SectionName = SectionNameRefOrErr.get(); - Sym.Type = SymbolEntPtr->SymbolType; - Sym.StorageClass = SymbolEntPtr->StorageClass; - Sym.NumberOfAuxEntries = SymbolEntPtr->NumberOfAuxEntries; + Sym.Type = SymbolEntRef.getSymbolType(); + Sym.StorageClass = SymbolEntRef.getStorageClass(); + Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries(); Symbols.push_back(Sym); } Index: llvm/unittests/Object/XCOFFObjectFileTest.cpp =================================================================== --- llvm/unittests/Object/XCOFFObjectFileTest.cpp +++ llvm/unittests/Object/XCOFFObjectFileTest.cpp @@ -281,3 +281,115 @@ "unexpected end of data at offset 0x25 while reading [0x25, 0x26)")); EXPECT_EQ(Size, 37u); } + +TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef32) { + const uint8_t XCOFF32Binary[] = { + // File header. + 0x01, 0xdf, 0x00, 0x01, 0x5f, 0x58, 0xf8, 0x95, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + + // Section header for empty .data section. + 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, + + // Start of symbol table. + // C_File symbol. + 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xfe, 0x00, 0x03, 0x67, 0x01, + // File Auxiliary Entry. + 0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // Csect symbol. + 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x6b, 0x01, + // Csect auxiliary entry. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + ArrayRef XCOFF32Ref(XCOFF32Binary, sizeof(XCOFF32Binary)); + Expected> XCOFFObjOrErr = + object::ObjectFile::createObjectFile( + MemoryBufferRef(toStringRef(XCOFF32Ref), "dummyXCOFF"), + file_magic::xcoff_object_32); + ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded()); + + const XCOFFObjectFile &File = *cast((*XCOFFObjOrErr).get()); + DataRefImpl Ref; + Ref.p = reinterpret_cast(File.getPointerToSymbolTable()); + XCOFFSymbolRef SymRef = File.toSymbolRef(Ref); + Expected ExpectErr = SymRef.getXCOFFCsectAuxRef(); + EXPECT_THAT_ERROR( + ExpectErr.takeError(), + FailedWithMessage( + "this symbol entry type could not have a csect auxiliary entry")); + + File.moveSymbolNext(Ref); + SymRef = File.toSymbolRef(Ref); + Expected CsectRefOrErr = SymRef.getXCOFFCsectAuxRef(); + ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded()); +} + +TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef64) { + uint8_t XCOFF64Binary[] = { + // File header. + 0x01, 0xf7, 0x00, 0x01, 0x5f, 0x59, 0x25, 0xeb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + + // Section header for empty .data section. + 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + + // Start of symbol table. + // C_File symbol. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0xff, 0xfe, 0x00, 0x02, 0x67, 0x01, + // File Auxiliary Entry. + 0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + + // Csect symbol. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x01, 0x00, 0x00, 0x6b, 0x01, + // Csect auxiliary entry. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, + + // String table. + 0x00, 0x00, 0x00, 0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x2e, 0x64, + 0x61, 0x74, 0x61, 0x00}; + + ArrayRef XCOFF64Ref(XCOFF64Binary, sizeof(XCOFF64Binary)); + Expected> XCOFFObjOrErr = + object::ObjectFile::createObjectFile( + MemoryBufferRef(toStringRef(XCOFF64Ref), "dummyXCOFF"), + file_magic::xcoff_object_64); + ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded()); + + const XCOFFObjectFile &File = *cast((*XCOFFObjOrErr).get()); + DataRefImpl Ref; + Ref.p = reinterpret_cast(File.getPointerToSymbolTable()); + XCOFFSymbolRef SymRef = File.toSymbolRef(Ref); + Expected ExpectErr = SymRef.getXCOFFCsectAuxRef(); + EXPECT_THAT_ERROR( + ExpectErr.takeError(), + FailedWithMessage( + "this symbol entry type could not have a csect auxiliary entry")); + + File.moveSymbolNext(Ref); + SymRef = File.toSymbolRef(Ref); + Expected CsectRefOrErr = SymRef.getXCOFFCsectAuxRef(); + ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded()); + + // Inject incorrect value. + XCOFF64Binary[167] = static_cast(XCOFF::AUX_SYM); + Expected NotFoundErr = SymRef.getXCOFFCsectAuxRef(); + EXPECT_THAT_ERROR(NotFoundErr.takeError(), + FailedWithMessage("a csect auxiliary entry is not found")); +}