Index: llvm/include/llvm/BinaryFormat/XCOFF.h =================================================================== --- llvm/include/llvm/BinaryFormat/XCOFF.h +++ llvm/include/llvm/BinaryFormat/XCOFF.h @@ -19,12 +19,18 @@ namespace XCOFF { // Constants used in the XCOFF definition. -enum { SectionNameSize = 8, SymbolNameSize = 8 }; +enum { + FileNamePadSize = 6, + SectionNameSize = 8, + SymbolNameSize = 8, + NameSize = 8 +}; + enum ReservedSectionNum { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 }; // x_smclas field of x_csect from system header: /usr/include/syms.h /// Storage Mapping Class definitions. -enum StorageMappingClass { +enum StorageMappingClass : uint8_t { // READ ONLY CLASSES XMC_PR = 0, ///< Program Code XMC_RO = 1, ///< Read Only Constant @@ -147,6 +153,13 @@ XTY_CM = 3 ///< Common csect definition. For uninitialized storage. }; +enum CFileStringType : uint8_t { + XFT_FN = 0, ///< Specifies the source-file name. + XFT_CT = 1, ///< Specifies the compiler time stamp. + XFT_CV = 2, ///< Specifies the compiler version number. + XFT_CD = 128 ///< Specifies compiler-defined information. +}; + } // end namespace XCOFF } // end namespace llvm Index: llvm/include/llvm/Object/XCOFFObjectFile.h =================================================================== --- llvm/include/llvm/Object/XCOFFObjectFile.h +++ llvm/include/llvm/Object/XCOFFObjectFile.h @@ -48,7 +48,7 @@ }; struct XCOFFSectionHeader32 { - char Name[XCOFF::SectionNameSize]; + char Name[XCOFF::NameSize]; support::ubig32_t PhysicalAddress; support::ubig32_t VirtualAddress; support::ubig32_t SectionSize; @@ -63,7 +63,7 @@ }; struct XCOFFSectionHeader64 { - char Name[XCOFF::SectionNameSize]; + char Name[XCOFF::NameSize]; support::ubig64_t PhysicalAddress; support::ubig64_t VirtualAddress; support::ubig64_t SectionSize; @@ -91,7 +91,7 @@ } CFileLanguageIdAndTypeIdType; union { - char SymbolName[XCOFF::SymbolNameSize]; + char SymbolName[XCOFF::NameSize]; NameInStrTblType NameInStrTbl; }; @@ -112,6 +112,38 @@ const char *Data; }; +struct XCOFFCSectAuxEnt { + support::ubig32_t SectionLen; + support::ubig32_t ParameterHash; + support::ubig16_t TypeChkSectNum; + uint8_t SymbolAlignmentAndType; + XCOFF::StorageMappingClass StorageMappingClass; + support::ubig32_t Stab; + support::ubig16_t Snstab; +}; + +struct XCOFFFileAuxEnt { + typedef struct { + support::big32_t Magic; // Zero indicates name in string table. + support::ubig32_t Offset; + char NamePad[XCOFF::FileNamePadSize]; + } NameInStrTblType; + union { + char Name[XCOFF::NameSize + XCOFF::FileNamePadSize]; + NameInStrTblType NameInStrTbl; + }; + XCOFF::CFileStringType Type; + uint8_t ReservedZero[2]; + uint8_t AuxType; +}; + +struct XCOFFSectAuxEntForStat { + support::ubig32_t SectionLength; + support::ubig16_t NumberOfRelocEnt; + support::ubig16_t NumberOfLineNum; + uint8_t Pad[10]; +}; + class XCOFFObjectFile : public ObjectFile { private: const void *FileHeader = nullptr; @@ -138,11 +170,7 @@ // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily // null-terminated. const char *getSectionNameInternal(DataRefImpl Sec) const; - - int32_t getSectionFlags(DataRefImpl Sec) const; - static bool isReservedSectionNumber(int16_t SectionNumber); - Expected getSectionByNum(int16_t Num) const; // Constructor and "create" factory function. The constructor is only a thin // wrapper around the base constructor. The "create" function fills out the @@ -238,15 +266,38 @@ uint32_t getLogicalNumberOfSymbolTableEntries32() const; uint32_t getNumberOfSymbolTableEntries64() const; + uint32_t getSymbolIndex(const uintptr_t *SymEntPtr) const; + Expected getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const; uint16_t getOptionalHeaderSize() const; uint16_t getFlags() const; // Section header table related interfaces. ArrayRef sections32() const; ArrayRef sections64() const; + + int32_t getSectionFlags(DataRefImpl Sec) const; + Expected getSectionByNum(int16_t Num) const; }; // XCOFFObjectFile +class XCOFFSymbolRef { + DataRefImpl SymEntDataRef; + const XCOFFObjectFile *OwningObjectPtr; + +public: + XCOFFSymbolRef(DataRefImpl SymEntDataRef, + const XCOFFObjectFile *owningObjectPtr) + : SymEntDataRef(SymEntDataRef), OwningObjectPtr(owningObjectPtr){}; + + XCOFF::StorageClass getStorageClass() const; + uint8_t getNumberOfAuxEntries() const; + const XCOFFCSectAuxEnt *getXCoffCSectAuxEnt() const; + uint16_t getType() const; + int16_t getSectionNumber() const; + bool hasCSectAuxEnt() const; + bool isFunction() const; +}; + } // namespace object } // namespace llvm Index: llvm/lib/Object/XCOFFObjectFile.cpp =================================================================== --- llvm/lib/Object/XCOFFObjectFile.cpp +++ llvm/lib/Object/XCOFFObjectFile.cpp @@ -17,6 +17,13 @@ namespace llvm { namespace object { +enum { + FUNCTION_SYM = 0x20, + RELOC_OVERFLOW = 65535, + SYM_TAB_ENTRY_SIZE = 18, + SYM_TYPE_MASK = 0x07 +}; + // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer // 'M'. Returns a pointer to the underlying object on success. template @@ -37,10 +44,11 @@ return reinterpret_cast(in); } -static StringRef generateStringRef(const char *Name, uint64_t Size) { - auto NulCharPtr = static_cast(memchr(Name, '\0', Size)); +static StringRef generateStringRef(const char *Name) { + auto NulCharPtr = + static_cast(memchr(Name, '\0', XCOFF::NameSize)); return NulCharPtr ? StringRef(Name, NulCharPtr - Name) - : StringRef(Name, Size); + : StringRef(Name, XCOFF::NameSize); } void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, @@ -110,11 +118,29 @@ Symb.p = reinterpret_cast(SymEntPtr); } +Expected +XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { + + if (CFileEntPtr->NameInStrTbl.Magic != + XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) + return generateStringRef(CFileEntPtr->Name); + + uint32_t Offset = CFileEntPtr->NameInStrTbl.Offset; + if (Offset < 4) + return StringRef(nullptr, 0); + + if (StringTable.Data != nullptr && StringTable.Size > Offset) + return (StringTable.Data + Offset); + + return make_error("CFile Name parse failed.", + object_error::parse_failed); +} + Expected XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) - return generateStringRef(SymEntPtr->SymbolName, XCOFF::SymbolNameSize); + return generateStringRef(SymEntPtr->SymbolName); // A storage class value with the high-order bit on indicates that the name is // a symbolic debugger stabstring. @@ -144,6 +170,7 @@ } uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { + assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); return toSymbolEntry(Symb)->Value; } @@ -180,7 +207,7 @@ } Expected XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { - return generateStringRef(getSectionNameInternal(Sec), XCOFF::SectionNameSize); + return generateStringRef(getSectionNameInternal(Sec)); } uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { @@ -388,8 +415,7 @@ default: Expected SecRef = getSectionByNum(SectionNum); if (SecRef) - return generateStringRef(getSectionNameInternal(SecRef.get()), - XCOFF::SectionNameSize); + return generateStringRef(getSectionNameInternal(SecRef.get())); return SecRef.takeError(); } } @@ -437,6 +463,22 @@ return fileHeader64()->NumberOfSymTableEntries; } +uint32_t XCOFFObjectFile::getSymbolIndex(const uintptr_t *SymbolEntPtr) const { + uint32_t Offset = reinterpret_cast(SymbolEntPtr) - + reinterpret_cast(SymbolTblPtr); + +#ifndef NDEBUG + if (SymbolEntPtr < reinterpret_cast(SymbolTblPtr)) + report_fatal_error("Symbol table entry is outside of symbol table."); + + if (Offset % SYM_TAB_ENTRY_SIZE != 0) + report_fatal_error( + "Symbol table entry position is not valid inside of symbol table."); +#endif + + return Offset / SYM_TAB_ENTRY_SIZE; +} + uint16_t XCOFFObjectFile::getFlags() const { return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; } @@ -568,11 +610,63 @@ } StringRef XCOFFSectionHeader32::getName() const { - return generateStringRef(Name, XCOFF::SectionNameSize); + return generateStringRef(Name); } StringRef XCOFFSectionHeader64::getName() const { - return generateStringRef(Name, XCOFF::SectionNameSize); + return generateStringRef(Name); +} + +XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const { + return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass; +} + +uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const { + return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries; +} + +const XCOFFCSectAuxEnt *XCOFFSymbolRef::getXCoffCSectAuxEnt() const { + assert(hasCSectAuxEnt()); + uintptr_t AuxAddr = getWithOffset( + SymEntDataRef.p, SYM_TAB_ENTRY_SIZE * getNumberOfAuxEntries()); + return reinterpret_cast(AuxAddr); +} + +uint16_t XCOFFSymbolRef::getType() const { + return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType; +} + +int16_t XCOFFSymbolRef::getSectionNumber() const { + return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber; +} + +bool XCOFFSymbolRef::hasCSectAuxEnt() const { + XCOFF::StorageClass Sc = getStorageClass(); + return (Sc == XCOFF::C_EXT || Sc == XCOFF::C_WEAKEXT || + Sc == XCOFF::C_HIDEXT); +} + +bool XCOFFSymbolRef::isFunction() const { + if (getType() & FUNCTION_SYM) + return true; + + if (!hasCSectAuxEnt()) + return false; + + const XCOFFCSectAuxEnt *CSectAuxEnt = getXCoffCSectAuxEnt(); + // The symbol is label definition. + if ((CSectAuxEnt->SymbolAlignmentAndType & SYM_TYPE_MASK) != XCOFF::XTY_LD) + return false; + + if (CSectAuxEnt->StorageMappingClass != XCOFF::XMC_PR) + return false; + + int16_t SectNum = getSectionNumber(); + Expected SI = OwningObjectPtr->getSectionByNum(SectNum); + if (!SI) + return false; + + return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); } } // namespace object Index: llvm/test/tools/llvm-readobj/xcoff-symbols.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-readobj/xcoff-symbols.test @@ -0,0 +1,446 @@ +# The object file used is generated by the following source file +# and command on AIX: +# +# > cat aix_xcoff_xlc_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 -c aix_xcoff_xlc_test8.c + +# RUN: llvm-readobj --symbols %p/Inputs/aix_xcoff_xlc_test8.o | \ +# RUN: FileCheck --check-prefix=SYMBOL32 %s +SYMBOL32: File: {{.*}}aix_xcoff_xlc_test8.o +SYMBOL32-NEXT: Format: aixcoff-rs6000 +SYMBOL32-NEXT: Arch: powerpc +SYMBOL32-NEXT: AddressSize: 32bit +SYMBOL32-NEXT: Symbols [ +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 0 +SYMBOL32-NEXT: Name: .file +SYMBOL32-NEXT: Value (SymbolTableIndex): 0x0 +SYMBOL32-NEXT: Section: N_DEBUG +SYMBOL32-NEXT: Source Language ID: 0 +SYMBOL32-NEXT: CPU Version ID: 3 +SYMBOL32-NEXT: StorageClass: C_FILE (0x67) +SYMBOL32-NEXT: NumberOfAuxEntries: 3 +SYMBOL32-NEXT: File Auxiliary Entry { +SYMBOL32-NEXT: Index: 1 +SYMBOL32-NEXT: Name: test8.c +SYMBOL32-NEXT: Type: XFT_FN (0x0) +SYMBOL32-NEXT: AuxType: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: File Auxiliary Entry { +SYMBOL32-NEXT: Index: 2 +SYMBOL32-NEXT: Name: Sun Apr 28 15:56:49 2019 +SYMBOL32-NEXT: Type: XFT_CT (0x1) +SYMBOL32-NEXT: AuxType: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: File Auxiliary Entry { +SYMBOL32-NEXT: Index: 3 +SYMBOL32-NEXT: Name: IBM XL C for AIX, Version 16.1.0.2 +SYMBOL32-NEXT: Type: XFT_CV (0x2) +SYMBOL32-NEXT: AuxType: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 4 +SYMBOL32-NEXT: Name: .text +SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +SYMBOL32-NEXT: Section: .text +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_STAT (0x3) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: Sect Auxiliary Entry For Stat { +SYMBOL32-NEXT: Index: 5 +SYMBOL32-NEXT: SectionLength: 256 +SYMBOL32-NEXT: NumberOfRelocEnt: 4 +SYMBOL32-NEXT: NumberOfLineNum: 0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 6 +SYMBOL32-NEXT: Name: .data +SYMBOL32-NEXT: Value (RelocatableAddress): 0x100 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_STAT (0x3) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: Sect Auxiliary Entry For Stat { +SYMBOL32-NEXT: Index: 7 +SYMBOL32-NEXT: SectionLength: 60 +SYMBOL32-NEXT: NumberOfRelocEnt: 11 +SYMBOL32-NEXT: NumberOfLineNum: 0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 8 +SYMBOL32-NEXT: Name: .bss +SYMBOL32-NEXT: Value (RelocatableAddress): 0x13C +SYMBOL32-NEXT: Section: .bss +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_STAT (0x3) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: Sect Auxiliary Entry For Stat { +SYMBOL32-NEXT: Index: 9 +SYMBOL32-NEXT: SectionLength: 4 +SYMBOL32-NEXT: NumberOfRelocEnt: 0 +SYMBOL32-NEXT: NumberOfLineNum: 0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 10 +SYMBOL32-NEXT: Name: +SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +SYMBOL32-NEXT: Section: .text +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 11 +SYMBOL32-NEXT: SectionLen: 256 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 7 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 12 +SYMBOL32-NEXT: Name: .fun1 +SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +SYMBOL32-NEXT: Section: .text +SYMBOL32-NEXT: Type: 0x20 +SYMBOL32-NEXT: StorageClass: C_EXT (0x2) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 13 +SYMBOL32-NEXT: ContainingCSectSymbolIndex: 10 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 0 +SYMBOL32-NEXT: SymbolType: XTY_LD (0x2) +SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 14 +SYMBOL32-NEXT: Name: .main +SYMBOL32-NEXT: Value (RelocatableAddress): 0x60 +SYMBOL32-NEXT: Section: .text +SYMBOL32-NEXT: Type: 0x20 +SYMBOL32-NEXT: StorageClass: C_EXT (0x2) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 15 +SYMBOL32-NEXT: ContainingCSectSymbolIndex: 10 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 0 +SYMBOL32-NEXT: SymbolType: XTY_LD (0x2) +SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 16 +SYMBOL32-NEXT: Name: TOC +SYMBOL32-NEXT: Value (RelocatableAddress): 0x100 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 17 +SYMBOL32-NEXT: SectionLen: 0 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_TC0 (0xF) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 18 +SYMBOL32-NEXT: Name: +SYMBOL32-NEXT: Value (RelocatableAddress): 0x114 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 19 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 20 +SYMBOL32-NEXT: Name: +SYMBOL32-NEXT: Value (RelocatableAddress): 0x134 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 21 +SYMBOL32-NEXT: SectionLen: 5 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 3 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_RO (0x1) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 22 +SYMBOL32-NEXT: Name: _$STATIC_BSS +SYMBOL32-NEXT: Value (RelocatableAddress): 0x13C +SYMBOL32-NEXT: Section: .bss +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 23 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_CM (0x3) +SYMBOL32-NEXT: StorageMappingClass: XMC_RW (0x5) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 24 +SYMBOL32-NEXT: Name: _$STATIC_BSS +SYMBOL32-NEXT: Value (RelocatableAddress): 0x104 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 25 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 26 +SYMBOL32-NEXT: Name: fun1 +SYMBOL32-NEXT: Value (RelocatableAddress): 0x118 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_EXT (0x2) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 27 +SYMBOL32-NEXT: SectionLen: 12 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_DS (0xA) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 28 +SYMBOL32-NEXT: Name: fun1 +SYMBOL32-NEXT: Value (RelocatableAddress): 0x100 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 29 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 30 +SYMBOL32-NEXT: Name: p +SYMBOL32-NEXT: Value (RelocatableAddress): 0x130 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_EXT (0x2) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 31 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_RW (0x5) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 32 +SYMBOL32-NEXT: Name: p +SYMBOL32-NEXT: Value (RelocatableAddress): 0x108 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 33 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 34 +SYMBOL32-NEXT: Name: main +SYMBOL32-NEXT: Value (RelocatableAddress): 0x124 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_EXT (0x2) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 35 +SYMBOL32-NEXT: SectionLen: 12 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_DS (0xA) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 36 +SYMBOL32-NEXT: Name: main +SYMBOL32-NEXT: Value (RelocatableAddress): 0x10C +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 37 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 38 +SYMBOL32-NEXT: Name: i +SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +SYMBOL32-NEXT: Section: N_UNDEF +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_EXT (0x2) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 39 +SYMBOL32-NEXT: SectionLen: 0 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 0 +SYMBOL32-NEXT: SymbolType: XTY_ER (0x0) +SYMBOL32-NEXT: StorageMappingClass: XMC_UA (0x4) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 40 +SYMBOL32-NEXT: Name: i +SYMBOL32-NEXT: Value (RelocatableAddress): 0x110 +SYMBOL32-NEXT: Section: .data +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_HIDEXT (0x6B) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 41 +SYMBOL32-NEXT: SectionLen: 4 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 2 +SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +SYMBOL32-NEXT: StorageMappingClass: XMC_TC (0x3) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: Symbol { +SYMBOL32-NEXT: Index: 42 +SYMBOL32-NEXT: Name: .fun +SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +SYMBOL32-NEXT: Section: N_UNDEF +SYMBOL32-NEXT: Type: 0x0 +SYMBOL32-NEXT: StorageClass: C_EXT (0x2) +SYMBOL32-NEXT: NumberOfAuxEntries: 1 +SYMBOL32-NEXT: CSect Auxiliary Entry { +SYMBOL32-NEXT: Index: 43 +SYMBOL32-NEXT: SectionLen: 0 +SYMBOL32-NEXT: ParameterHash: 0x0 +SYMBOL32-NEXT: TypeChkSectNum: 0x0 +SYMBOL32-NEXT: SymbolAlignmentLog2: 0 +SYMBOL32-NEXT: SymbolType: XTY_ER (0x0) +SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0) +SYMBOL32-NEXT: Stab: 0x0 +SYMBOL32-NEXT: Snstab: 0x0 +SYMBOL32-NEXT: } +SYMBOL32-NEXT: } +SYMBOL32-NEXT: ] Index: llvm/tools/llvm-readobj/XCOFFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -22,6 +22,12 @@ namespace { class XCOFFDumper : public ObjDumper { + enum { + SymbolTypeMask = 0x07, + SymbolAlignmentMask = 0xF8, + SymbolTypeBits = 3 + }; + public: XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer) : ObjDumper(Writer), Obj(Obj) {} @@ -37,11 +43,14 @@ private: template void printSectionHeaders(ArrayRef Sections); - - const XCOFFObjectFile &Obj; + void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr); + void printCSectAuxEnt(const XCOFFCSectAuxEnt *AuxEntPtr); + void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr); + void printSymbol(const SymbolRef &); // Least significant 3 bits are reserved. static constexpr unsigned SectionFlagsReservedMask = 0x7; + const XCOFFObjectFile &Obj; }; } // anonymous namespace @@ -102,9 +111,214 @@ void XCOFFDumper::printRelocations() { llvm_unreachable("Unimplemented functionality for XCOFFDumper"); } +static const EnumEntry FileStringType[] = { +#define ECase(X) \ + { #X, XCOFF::X } + ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD) +#undef ECase +}; + +void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) { + StringRef FileName = unwrapOrError(Obj.getCFileName(AuxEntPtr)); + DictScope SymDs(W, "File Auxiliary Entry"); + W.printNumber("Index", Obj.getSymbolIndex( + reinterpret_cast(AuxEntPtr))); + W.printString("Name", FileName); + W.printEnum("Type", (uint8_t)AuxEntPtr->Type, makeArrayRef(FileStringType)); + W.printHex("AuxType", AuxEntPtr->AuxType); +} + +static const EnumEntry CSectStorageMappingClass[] = + { +#define ECase(X) \ + { #X, XCOFF::X } + ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), + ECase(XMC_GL), ECase(XMC_XO), ECase(XMC_SV), + ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI), + ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0), + ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), + ECase(XMC_UA), ECase(XMC_BS), ECase(XMC_UC), + ECase(XMC_TL), ECase(XMC_TE) +#undef ECase +}; + +static const EnumEntry CSectSymbolTypeClass[] = { +#define ECase(X) \ + { #X, XCOFF::X } + ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM) +#undef ECase +}; + +void XCOFFDumper::printCSectAuxEnt(const XCOFFCSectAuxEnt *AuxEntPtr) { + DictScope SymDs(W, "CSect Auxiliary Entry"); + W.printNumber("Index", Obj.getSymbolIndex( + reinterpret_cast(AuxEntPtr))); + if ((AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask) == XCOFF::XTY_LD) + W.printNumber("ContainingCSectSymbolIndex", AuxEntPtr->SectionLen); + else + W.printNumber("SectionLen", AuxEntPtr->SectionLen); + W.printHex("ParameterHash", AuxEntPtr->ParameterHash); + W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum); + // Print out symbol alignment and type. + W.printNumber("SymbolAlignmentLog2", + (AuxEntPtr->SymbolAlignmentAndType & SymbolAlignmentMask) >> + SymbolTypeBits); + W.printEnum("SymbolType", + ((uint8_t)AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask), + makeArrayRef(CSectSymbolTypeClass)); + W.printEnum("StorageMappingClass", (uint8_t)AuxEntPtr->StorageMappingClass, + makeArrayRef(CSectStorageMappingClass)); + W.printHex("Stab", AuxEntPtr->Stab); + W.printHex("Snstab", AuxEntPtr->Snstab); +} + +void XCOFFDumper::printSectAuxEntForStat( + const XCOFFSectAuxEntForStat *AuxEntPtr) { + DictScope SymDs(W, "Sect Auxiliary Entry For Stat"); + W.printNumber("Index", Obj.getSymbolIndex( + reinterpret_cast(AuxEntPtr))); + W.printNumber("SectionLength", AuxEntPtr->SectionLength); + W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt); + W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum); +} + +static const EnumEntry SymStorageClass[] = { +#define ECase(X) \ + { #X, XCOFF::X } + ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT), + ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL), + ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU), + ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG), + ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK), + ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE), + ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL), + ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF), + ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM), + ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM), + ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY), + ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS), + ECase(C_STTLS), ECase(C_EFCN) +#undef ECase +}; + +static StringRef GetSymbolValueName(XCOFF::StorageClass SC) { + switch (SC) { + case XCOFF::C_EXT: + case XCOFF::C_WEAKEXT: + case XCOFF::C_HIDEXT: + case XCOFF::C_STAT: + return "Value (RelocatableAddress)"; + case XCOFF::C_FILE: + return "Value (SymbolTableIndex)"; + case XCOFF::C_FCN: + case XCOFF::C_BLOCK: + case XCOFF::C_FUN: + case XCOFF::C_STSYM: + case XCOFF::C_BINCL: + case XCOFF::C_EINCL: + case XCOFF::C_INFO: + case XCOFF::C_BSTAT: + case XCOFF::C_LSYM: + case XCOFF::C_PSYM: + case XCOFF::C_RPSYM: + case XCOFF::C_RSYM: + case XCOFF::C_ECOML: + case XCOFF::C_DWARF: + llvm_unreachable("This StorageClass for the symbol is not yet implemented"); + default: + return "Value"; + } +} +void XCOFFDumper::printSymbol(const SymbolRef &S) { + DataRefImpl SymbolDRI = S.getRawDataRefImpl(); + const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI); + XCOFFSymbolRef XCoffSymRef(SymbolDRI, &Obj); + uint8_t NumberOfAuxEntries = XCoffSymRef.getNumberOfAuxEntries(); + + DictScope SymDs(W, "Symbol"); + + StringRef SymbolName = unwrapOrError(Obj.getSymbolName(SymbolDRI)); + + W.printNumber("Index", Obj.getSymbolIndex(reinterpret_cast( + SymbolEntPtr))); + W.printString("Name", SymbolName); + W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass), + SymbolEntPtr->Value); + + StringRef SectionName = unwrapOrError(Obj.getSymbolSectionName(SymbolEntPtr)); + + W.printString("Section", SectionName); + if (XCoffSymRef.getStorageClass() == XCOFF::C_FILE) { + W.printNumber("Source Language ID", + SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId); + W.printNumber("CPU Version ID", + SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId); + } else + W.printHex("Type", SymbolEntPtr->SymbolType); + + W.printEnum("StorageClass", (uint8_t)SymbolEntPtr->StorageClass, + makeArrayRef(SymStorageClass)); + W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries); + + if (NumberOfAuxEntries == 0) + return; + + switch (XCoffSymRef.getStorageClass()) { + case XCOFF::C_FILE: + // If the symbol is C_FILE and has auxiliary entires. + if (SymbolName.equals(".file")) + for (int i = 1; i <= NumberOfAuxEntries; i++) { + const XCOFFFileAuxEnt *FileAuxEntPtr = + reinterpret_cast(SymbolEntPtr + i); + printFileAuxEnt(FileAuxEntPtr); + } + break; + case XCOFF::C_EXT: + case XCOFF::C_WEAKEXT: + case XCOFF::C_HIDEXT: + // If the symbol is Function. + if (XCoffSymRef.isFunction() && NumberOfAuxEntries >= 2) + report_fatal_error("Function auxiliary entry printing is unimplemented."); + + // If more than 2,Instead of printing out error information, + // Print out the raw Auxiliary entry between 2 and NumberOfAuxEntries-1 + for (int i = 2; i < NumberOfAuxEntries; i++) { + W.startLine() << "!Unexpected raw auxiliary entry data are print out:\n"; + W.startLine() << format_bytes(ArrayRef( + (const uint8_t *)(SymbolEntPtr + i), sizeof(XCOFFSymbolEntry))); + } + // The symbol has a CSect Auxiliary Entry. + const XCOFFCSectAuxEnt *CSectAuxEntPtr; + CSectAuxEntPtr = reinterpret_cast( + SymbolEntPtr + NumberOfAuxEntries); + printCSectAuxEnt(CSectAuxEntPtr); + break; + case XCOFF::C_STAT: + const XCOFFSectAuxEntForStat *StatAuxEntPtr; + StatAuxEntPtr = + reinterpret_cast(SymbolEntPtr + 1); + printSectAuxEntForStat(StatAuxEntPtr); + break; + case XCOFF::C_DWARF: + case XCOFF::C_BLOCK: + case XCOFF::C_FCN: + report_fatal_error("Symbol table entry printing for this storage class " + "type is unimplemented."); + break; + default: + for (int i = 1; i <= NumberOfAuxEntries; i++) { + W.startLine() << "!Unexpected raw auxiliary entry data are print out:\n"; + W.startLine() << format_bytes(ArrayRef( + (const uint8_t *)(SymbolEntPtr + i), sizeof(XCOFFSymbolEntry))); + } + break; + } +} void XCOFFDumper::printSymbols() { - llvm_unreachable("Unimplemented functionality for XCOFFDumper"); + ListScope Group(W, "Symbols"); + for (const SymbolRef &S : Obj.symbols()) + printSymbol(S); } void XCOFFDumper::printDynamicSymbols() {