diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -348,6 +348,57 @@ uint8_t Pad[10]; }; // 32-bit XCOFF file only. +struct XCOFFFunctionAuxEnt32 { + support::ubig32_t OffsetToExceptionTbl; + support::ubig32_t SizeOfFunction; + support::ubig32_t PtrToLineNum; + support::big32_t SymIdxOfNextBeyond; + uint8_t Pad[2]; +}; + +struct XCOFFFunctionAuxEnt64 { + support::ubig64_t PtrToLineNum; + support::ubig32_t SizeOfFunction; + support::big32_t SymIdxOfNextBeyond; + uint8_t Pad; + XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry +}; + +struct XCOFFExceptionAuxEnt { + support::ubig64_t OffsetToExceptionTbl; + support::ubig32_t SizeOfFunction; + support::big32_t SymIdxOfNextBeyond; + uint8_t Pad; + XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry +}; + +struct XCOFFBlockAuxEnt32 { + uint8_t ReservedZeros1[2]; + support::ubig16_t LineNumHi; + support::ubig16_t LineNumLo; + uint8_t ReservedZeros2[12]; +}; + +struct XCOFFBlockAuxEnt64 { + support::ubig32_t LineNum; + uint8_t Pad[13]; + XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry +}; + +struct XCOFFSectAuxEntForDWARF32 { + support::ubig32_t LengthOfSectionPortion; + uint8_t Pad1[4]; + support::ubig32_t NumberOfRelocEnt; + uint8_t Pad2[6]; +}; + +struct XCOFFSectAuxEntForDWARF64 { + support::ubig64_t LengthOfSectionPortion; + support::ubig64_t NumberOfRelocEnt; + uint8_t Pad; + XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry +}; + template struct XCOFFRelocation { // Masks for packing/unpacking the r_rsize field of relocations. diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -1112,8 +1112,12 @@ return true; Expected ExpCsectAuxEnt = getXCOFFCsectAuxRef(); - if (!ExpCsectAuxEnt) + if (!ExpCsectAuxEnt) { + // If we could not get the CSECT auxiliary entry, then this symbol should + // not be a function. So consume the error and return `false` to move on. + consumeError(ExpCsectAuxEnt.takeError()); return false; + } const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); diff --git a/llvm/test/tools/llvm-readobj/XCOFF/symbols-invalid.test b/llvm/test/tools/llvm-readobj/XCOFF/symbols-invalid.test --- a/llvm/test/tools/llvm-readobj/XCOFF/symbols-invalid.test +++ b/llvm/test/tools/llvm-readobj/XCOFF/symbols-invalid.test @@ -1,23 +1,68 @@ -## This file tests the raw data output ability when a file auxiliary entry does +## Test that we report warnings or dump raw data when symbols are invalid. + +# RUN: yaml2obj %s --docnum=1 -o %t1 +# RUN: llvm-readobj --syms %t1 2>&1 | FileCheck %s -DFILE=%t1 --check-prefix=CASE1 + +# CASE1: llvm-readobj: warning: '[[FILE]]': the non-function C_EXT symbol at index 1 should have only 1 auxiliary entry, i.e. the CSECT auxiliary entry + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Symbols: + - Name: .sym + - Name: .fun + StorageClass: [[STORAGECLASS='C_EXT']] + NumberOfAuxEntries: 2 + +# RUN: yaml2obj %s --docnum=1 -DSTORAGECLASS='C_WEAKEXT' -o %t2 +# RUN: llvm-readobj --syms %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=CASE2 + +# CASE2: llvm-readobj: warning: '[[FILE]]': the non-function C_WEAKEXT symbol at index 1 should have only 1 auxiliary entry, i.e. the CSECT auxiliary entry + +# RUN: yaml2obj %s --docnum=1 -DSTORAGECLASS='C_HIDEXT' -o %t3 +# RUN: llvm-readobj --syms %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=CASE3 + +# CASE3: llvm-readobj: warning: '[[FILE]]': the non-function C_HIDEXT symbol at index 1 should have only 1 auxiliary entry, i.e. the CSECT auxiliary entry + +# RUN: yaml2obj %s --docnum=1 -DSTORAGECLASS='C_STAT' -o %t4 +# RUN: llvm-readobj --syms %t4 2>&1 | FileCheck %s -DFILE=%t4 --check-prefix=CASE4 + +# CASE4: llvm-readobj: warning: '[[FILE]]': the C_STAT symbol at index 1 should not have more than 1 auxiliary entry + +# RUN: yaml2obj %s --docnum=1 -DSTORAGECLASS='C_DWARF' -o %t5 +# RUN: llvm-readobj --syms %t5 2>&1 | FileCheck %s -DFILE=%t5 --check-prefix=CASE5 + +# CASE5: llvm-readobj: warning: '[[FILE]]': the C_DWARF symbol at index 1 should not have more than 1 auxiliary entry + +# RUN: yaml2obj %s --docnum=1 -DSTORAGECLASS='C_BLOCK' -o %t6 +# RUN: llvm-readobj --syms %t6 2>&1 | FileCheck %s -DFILE=%t6 --check-prefix=CASE6 + +# CASE6: llvm-readobj: warning: '[[FILE]]': the C_BLOCK symbol at index 1 should not have more than 1 auxiliary entry + +# RUN: yaml2obj %s --docnum=1 -DSTORAGECLASS='C_FCN' -o %t7 +# RUN: llvm-readobj --syms %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=CASE7 + +# CASE7: llvm-readobj: warning: '[[FILE]]': the C_FCN symbol at index 1 should not have more than 1 auxiliary entry + +## This case tests the raw data output ability when a file auxiliary entry does ## not have the matching auxiliary type. +# RUN: yaml2obj %s --docnum=2 -o %t8 +# RUN: llvm-readobj --syms %t8 | FileCheck %s --strict-whitespace --match-full-lines --check-prefix=CASE8 -# RUN: yaml2obj %s -o %t -# RUN: llvm-readobj --syms %t | FileCheck %s - -# CHECK: Symbols [ -# CHECK-NEXT: Symbol { -# CHECK-NEXT: Index: 0 -# CHECK-NEXT: Name: .fun -# CHECK-NEXT: Value (SymbolTableIndex): 0x0 -# CHECK-NEXT: Section: N_UNDEF -# CHECK-NEXT: Source Language ID: TB_C (0x0) -# CHECK-NEXT: CPU Version ID: 0x0 -# CHECK-NEXT: StorageClass: C_FILE (0x67) -# CHECK-NEXT: NumberOfAuxEntries: 1 -# CHECK-NEXT: !Unexpected raw auxiliary entry data: -# CHECK-NEXT: 00000000 00000001 00020300 00000000 00fb -# CHECK-NEXT: } -# CHECK-NEXT: ] + # CASE8:Symbols [ +# CASE8-NEXT: Symbol { +# CASE8-NEXT: Index: 0 +# CASE8-NEXT: Name: .fun +# CASE8-NEXT: Value (SymbolTableIndex): 0x0 +# CASE8-NEXT: Section: N_UNDEF +# CASE8-NEXT: Source Language ID: TB_C (0x0) +# CASE8-NEXT: CPU Version ID: 0x0 +# CASE8-NEXT: StorageClass: C_FILE (0x67) +# CASE8-NEXT: NumberOfAuxEntries: 1 +# CASE8-NEXT: !Unexpected raw auxiliary entry data: +# CASE8-NEXT: 00000000 00000001 00020300 00000000 00fb +# CASE8-NEXT: } +# CASE8-NEXT:] --- !XCOFF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/XCOFF/symbols.test b/llvm/test/tools/llvm-readobj/XCOFF/symbols.test --- a/llvm/test/tools/llvm-readobj/XCOFF/symbols.test +++ b/llvm/test/tools/llvm-readobj/XCOFF/symbols.test @@ -87,6 +87,52 @@ SectionOrLength: 256 StabInfoIndex: 2 StabSectNum: 3 +## The C_WEAKEXT symbol with a Function auxiliary entry and a CSECT auxiliary entry. + - Name: .fun3 + Value: 0x0 + Section: N_DEBUG + Type: 0x20 + StorageClass: C_WEAKEXT + NumberOfAuxEntries: 2 + AuxEntries: + - Type: AUX_FCN + OffsetToExceptionTbl: 2 + SizeOfFunction: 3 + SymIdxOfNextBeyond: 4 + PtrToLineNum: 5 + - Type: AUX_CSECT + ParameterHashIndex: 11 + TypeChkSectNum: 22 + SymbolAlignmentAndType: 33 + StorageMappingClass: XMC_PR + SectionOrLength: 256 + StabInfoIndex: 44 + StabSectNum: 55 +## The C_DWARF symbol with a SECT auxiliary entry. + - Name: .fun4 + Section: N_DEBUG + StorageClass: C_DWARF + NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_SECT + LengthOfSectionPortion: 2 + NumberOfRelocEnt: 3 +## The C_BLOCK symbol with a Block auxiliary entry. + - Name: .fun5 + StorageClass: C_BLOCK + NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_SYM + LineNumHi: 2 + LineNumLo: 3 +## The C_FCN symbol with a Block auxiliary entry. + - Name: .fun6 + StorageClass: C_FCN + NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_SYM + LineNumHi: 2 + LineNumLo: 3 # SYMBOL32: Symbols [ # SYMBOL32-NEXT: Symbol { @@ -189,4 +235,73 @@ # SYMBOL32-NEXT: StabSectNum: 0x3 # SYMBOL32-NEXT: } # SYMBOL32-NEXT: } +# SYMBOL32-NEXT: Symbol { +# SYMBOL32-NEXT: Index: 12 +# SYMBOL32-NEXT: Name: .fun3 +# SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL32-NEXT: Section: N_DEBUG +# SYMBOL32-NEXT: Type: 0x20 +# SYMBOL32-NEXT: StorageClass: C_WEAKEXT (0x6F) +# SYMBOL32-NEXT: NumberOfAuxEntries: 2 +# SYMBOL32-NEXT: Function Auxiliary Entry { +# SYMBOL32-NEXT: Index: 13 +# SYMBOL32-NEXT: OffsetToExceptionTable: 0x2 +# SYMBOL32-NEXT: SizeOfFunction: 0x3 +# SYMBOL32-NEXT: PointerToLineNum: 0x5 +# SYMBOL32-NEXT: SymbolIndexOfNextBeyond: 4 +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: CSECT Auxiliary Entry { +# SYMBOL32-NEXT: Index: 14 +# SYMBOL32-NEXT: SectionLen: 256 +# SYMBOL32-NEXT: ParameterHashIndex: 0xB +# SYMBOL32-NEXT: TypeChkSectNum: 0x16 +# SYMBOL32-NEXT: SymbolAlignmentLog2: 4 +# SYMBOL32-NEXT: SymbolType: XTY_SD (0x1) +# SYMBOL32-NEXT: StorageMappingClass: XMC_PR (0x0) +# SYMBOL32-NEXT: StabInfoIndex: 0x2C +# SYMBOL32-NEXT: StabSectNum: 0x37 +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: Symbol { +# SYMBOL32-NEXT: Index: 15 +# SYMBOL32-NEXT: Name: .fun4 +# SYMBOL32-NEXT: Value (OffsetInDWARF): 0x0 +# SYMBOL32-NEXT: Section: N_DEBUG +# SYMBOL32-NEXT: Type: 0x0 +# SYMBOL32-NEXT: StorageClass: C_DWARF (0x70) +# SYMBOL32-NEXT: NumberOfAuxEntries: 1 +# SYMBOL32-NEXT: Sect Auxiliary Entry For DWARF { +# SYMBOL32-NEXT: Index: 16 +# SYMBOL32-NEXT: LengthOfSectionPortion: 0x2 +# SYMBOL32-NEXT: NumberOfRelocEntries: 3 +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: Symbol { +# SYMBOL32-NEXT: Index: 17 +# SYMBOL32-NEXT: Name: .fun5 +# SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL32-NEXT: Section: N_UNDEF +# SYMBOL32-NEXT: Type: 0x0 +# SYMBOL32-NEXT: StorageClass: C_BLOCK (0x64) +# SYMBOL32-NEXT: NumberOfAuxEntries: 1 +# SYMBOL32-NEXT: Block Auxiliary Entry { +# SYMBOL32-NEXT: Index: 18 +# SYMBOL32-NEXT: LineNumber (High 2 Bytes): 0x2 +# SYMBOL32-NEXT: LineNumber (Low 2 Bytes): 0x3 +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: Symbol { +# SYMBOL32-NEXT: Index: 19 +# SYMBOL32-NEXT: Name: .fun6 +# SYMBOL32-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL32-NEXT: Section: N_UNDEF +# SYMBOL32-NEXT: Type: 0x0 +# SYMBOL32-NEXT: StorageClass: C_FCN (0x65) +# SYMBOL32-NEXT: NumberOfAuxEntries: 1 +# SYMBOL32-NEXT: Block Auxiliary Entry { +# SYMBOL32-NEXT: Index: 20 +# SYMBOL32-NEXT: LineNumber (High 2 Bytes): 0x2 +# SYMBOL32-NEXT: LineNumber (Low 2 Bytes): 0x3 +# SYMBOL32-NEXT: } +# SYMBOL32-NEXT: } # SYMBOL32-NEXT: ] diff --git a/llvm/test/tools/llvm-readobj/XCOFF/symbols64.test b/llvm/test/tools/llvm-readobj/XCOFF/symbols64.test --- a/llvm/test/tools/llvm-readobj/XCOFF/symbols64.test +++ b/llvm/test/tools/llvm-readobj/XCOFF/symbols64.test @@ -72,6 +72,71 @@ StorageMappingClass: XMC_PR SectionOrLengthLo: 2 SectionOrLengthHi: 3 +## The C_WEAKEXT symbol with a Function auxiliary entry and a CSECT auxiliary entry. + - Name: .fun3 + Value: 0x0 + Section: N_DEBUG + Type: 0x20 + StorageClass: C_WEAKEXT + NumberOfAuxEntries: 2 + AuxEntries: + - Type: AUX_FCN + SizeOfFunction: 3 + SymIdxOfNextBeyond: 4 + PtrToLineNum: 5 + - Type: AUX_CSECT + ParameterHashIndex: 2 + TypeChkSectNum: 3 + SymbolAlignmentAndType: 1 + StorageMappingClass: XMC_PR + SectionOrLengthLo: 4 + SectionOrLengthHi: 5 +## The C_EXT symbol with a Function auxiliary entry, a CSECT auxiliary entry, and an Exception auxiliary entry. + - Name: .fun4 + Value: 0x0 + Section: .text + Type: 0x20 + StorageClass: C_EXT + NumberOfAuxEntries: 3 + AuxEntries: + - Type: AUX_FCN + SizeOfFunction: 3 + SymIdxOfNextBeyond: 4 + PtrToLineNum: 5 + - Type: AUX_EXCEPT + OffsetToExceptionTbl: 2 + SizeOfFunction: 3 + SymIdxOfNextBeyond: 4 + - Type: AUX_CSECT + ParameterHashIndex: 2 + TypeChkSectNum: 3 + SymbolAlignmentAndType: 1 + StorageMappingClass: XMC_PR + SectionOrLengthLo: 4 + SectionOrLengthHi: 5 +## The C_DWARF symbol with a SECT auxiliary entry. + - Name: .fun5 + Section: N_DEBUG + StorageClass: C_DWARF + NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_SECT + LengthOfSectionPortion: 2 + NumberOfRelocEnt: 3 +## The C_BLOCK symbol with a Block auxiliary entry. + - Name: .fun6 + StorageClass: C_BLOCK + NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_SYM + LineNum: 3 +## The C_FCN symbol with a Block auxiliary entry. + - Name: .fun7 + StorageClass: C_FCN + NumberOfAuxEntries: 1 + AuxEntries: + - Type: AUX_SYM + LineNum: 3 # SYMBOL64: Symbols [ # SYMBOL64-NEXT: Symbol { @@ -159,4 +224,106 @@ # SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) # SYMBOL64-NEXT: } # SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 10 +# SYMBOL64-NEXT: Name: .fun3 +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: N_DEBUG +# SYMBOL64-NEXT: Type: 0x20 +# SYMBOL64-NEXT: StorageClass: C_WEAKEXT (0x6F) +# SYMBOL64-NEXT: NumberOfAuxEntries: 2 +# SYMBOL64-NEXT: Function Auxiliary Entry { +# SYMBOL64-NEXT: Index: 11 +# SYMBOL64-NEXT: SizeOfFunction: 0x3 +# SYMBOL64-NEXT: PointerToLineNum: 0x5 +# SYMBOL64-NEXT: SymbolIndexOfNextBeyond: 4 +# SYMBOL64-NEXT: Auxiliary Type: AUX_FCN (0xFE) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 12 +# SYMBOL64-NEXT: SectionLen: 21474836484 +# SYMBOL64-NEXT: ParameterHashIndex: 0x2 +# SYMBOL64-NEXT: TypeChkSectNum: 0x3 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 0 +# 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: 13 +# SYMBOL64-NEXT: Name: .fun4 +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: .text +# SYMBOL64-NEXT: Type: 0x20 +# SYMBOL64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOL64-NEXT: NumberOfAuxEntries: 3 +# SYMBOL64-NEXT: Function Auxiliary Entry { +# SYMBOL64-NEXT: Index: 14 +# SYMBOL64-NEXT: SizeOfFunction: 0x3 +# SYMBOL64-NEXT: PointerToLineNum: 0x5 +# SYMBOL64-NEXT: SymbolIndexOfNextBeyond: 4 +# SYMBOL64-NEXT: Auxiliary Type: AUX_FCN (0xFE) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Exception Auxiliary Entry { +# SYMBOL64-NEXT: Index: 15 +# SYMBOL64-NEXT: OffsetToExceptionTable: 0x2 +# SYMBOL64-NEXT: SizeOfFunction: 0x3 +# SYMBOL64-NEXT: SymbolIndexOfNextBeyond: 4 +# SYMBOL64-NEXT: Auxiliary Type: AUX_EXCEPT (0xFF) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: CSECT Auxiliary Entry { +# SYMBOL64-NEXT: Index: 16 +# SYMBOL64-NEXT: SectionLen: 21474836484 +# SYMBOL64-NEXT: ParameterHashIndex: 0x2 +# SYMBOL64-NEXT: TypeChkSectNum: 0x3 +# SYMBOL64-NEXT: SymbolAlignmentLog2: 0 +# 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: 17 +# SYMBOL64-NEXT: Name: .fun5 +# SYMBOL64-NEXT: Value (OffsetInDWARF): 0x0 +# SYMBOL64-NEXT: Section: N_DEBUG +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_DWARF (0x70) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: Sect Auxiliary Entry For DWARF { +# SYMBOL64-NEXT: Index: 18 +# SYMBOL64-NEXT: LengthOfSectionPortion: 0x2 +# SYMBOL64-NEXT: NumberOfRelocEntries: 3 +# SYMBOL64-NEXT: Auxiliary Type: AUX_SECT (0xFA) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 19 +# SYMBOL64-NEXT: Name: .fun6 +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: N_UNDEF +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_BLOCK (0x64) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: Block Auxiliary Entry { +# SYMBOL64-NEXT: Index: 20 +# SYMBOL64-NEXT: LineNumber: 0x3 +# SYMBOL64-NEXT: Auxiliary Type: AUX_SYM (0xFD) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: Symbol { +# SYMBOL64-NEXT: Index: 21 +# SYMBOL64-NEXT: Name: .fun7 +# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0 +# SYMBOL64-NEXT: Section: N_UNDEF +# SYMBOL64-NEXT: Type: 0x0 +# SYMBOL64-NEXT: StorageClass: C_FCN (0x65) +# SYMBOL64-NEXT: NumberOfAuxEntries: 1 +# SYMBOL64-NEXT: Block Auxiliary Entry { +# SYMBOL64-NEXT: Index: 22 +# SYMBOL64-NEXT: LineNumber: 0x3 +# SYMBOL64-NEXT: Auxiliary Type: AUX_SYM (0xFD) +# SYMBOL64-NEXT: } +# SYMBOL64-NEXT: } # SYMBOL64-NEXT: ] diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -44,9 +44,16 @@ template void printSectionHeaders(ArrayRef Sections); template void printGenericSectionHeader(T &Sec) const; template void printOverflowSectionHeader(T &Sec) const; + template const T *getAuxEntPtr(uintptr_t AuxAddress); void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr); void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef); void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr); + void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr); + void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr); + void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr); + void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr); + void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr); + template void printSectAuxEntForDWARF(const T *AuxEntPtr); void printSymbol(const SymbolRef &); template void printRelocations(ArrayRef Sections); @@ -56,6 +63,15 @@ }; } // anonymous namespace +template +static std::string enum2String(T Value, + ArrayRef> EnumValues) { + for (const EnumEntry &EnumItem : EnumValues) + if (EnumItem.Value == Value) + return std::string(EnumItem.AltName); + return to_hexString(Value, false); +} + void XCOFFDumper::printFileHeaders() { DictScope DS(W, "FileHeader"); W.printHex("Magic", Obj.getMagic()); @@ -279,6 +295,77 @@ W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum); } +void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) { + assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file."); + + DictScope SymDs(W, "Exception Auxiliary Entry"); + W.printNumber("Index", + Obj.getSymbolIndex(reinterpret_cast(AuxEntPtr))); + W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl); + W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction); + W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond); + W.printEnum("Auxiliary Type", static_cast(AuxEntPtr->AuxType), + makeArrayRef(SymAuxType)); +} + +void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) { + assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file."); + + DictScope SymDs(W, "Function Auxiliary Entry"); + W.printNumber("Index", + Obj.getSymbolIndex(reinterpret_cast(AuxEntPtr))); + W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl); + W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction); + W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum); + W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond); +} + +void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) { + assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file."); + + DictScope SymDs(W, "Function Auxiliary Entry"); + W.printNumber("Index", + Obj.getSymbolIndex(reinterpret_cast(AuxEntPtr))); + W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction); + W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum); + W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond); + W.printEnum("Auxiliary Type", static_cast(AuxEntPtr->AuxType), + makeArrayRef(SymAuxType)); +} + +void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) { + assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file."); + + DictScope SymDs(W, "Block Auxiliary Entry"); + W.printNumber("Index", + Obj.getSymbolIndex(reinterpret_cast(AuxEntPtr))); + W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi); + W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo); +} + +void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) { + assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file."); + + DictScope SymDs(W, "Block Auxiliary Entry"); + W.printNumber("Index", + Obj.getSymbolIndex(reinterpret_cast(AuxEntPtr))); + W.printHex("LineNumber", AuxEntPtr->LineNum); + W.printEnum("Auxiliary Type", static_cast(AuxEntPtr->AuxType), + makeArrayRef(SymAuxType)); +} + +template +void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) { + DictScope SymDs(W, "Sect Auxiliary Entry For DWARF"); + W.printNumber("Index", + Obj.getSymbolIndex(reinterpret_cast(AuxEntPtr))); + W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion); + W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt); + if (Obj.is64Bit()) + W.printEnum("Auxiliary Type", static_cast(XCOFF::AUX_SECT), + makeArrayRef(SymAuxType)); +} + const EnumEntry SymStorageClass[] = { #define ECase(X) \ { #X, XCOFF::X } @@ -304,11 +391,13 @@ case XCOFF::C_WEAKEXT: case XCOFF::C_HIDEXT: case XCOFF::C_STAT: + case XCOFF::C_FCN: + case XCOFF::C_BLOCK: return "Value (RelocatableAddress)"; case XCOFF::C_FILE: return "Value (SymbolTableIndex)"; - case XCOFF::C_FCN: - case XCOFF::C_BLOCK: + case XCOFF::C_DWARF: + return "Value (OffsetInDWARF)"; case XCOFF::C_FUN: case XCOFF::C_STSYM: case XCOFF::C_BINCL: @@ -320,7 +409,6 @@ case XCOFF::C_RPSYM: case XCOFF::C_RSYM: case XCOFF::C_ECOML: - case XCOFF::C_DWARF: assert(false && "This StorageClass for the symbol is not yet implemented."); return ""; default: @@ -342,6 +430,22 @@ #undef ECase }; +template const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) { + const T *AuxEntPtr = reinterpret_cast(AuxAddress); + Obj.checkSymbolEntryPointer(reinterpret_cast(AuxEntPtr)); + return AuxEntPtr; +} + +static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) { + W.startLine() << "!Unexpected raw auxiliary entry data:\n"; + W.startLine() << format_bytes( + ArrayRef( + reinterpret_cast(AuxAddress), + XCOFF::SymbolTableEntrySize), + None, XCOFF::SymbolTableEntrySize) + << "\n"; +} + void XCOFFDumper::printSymbol(const SymbolRef &S) { DataRefImpl SymbolDRI = S.getRawDataRefImpl(); XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI); @@ -353,16 +457,18 @@ StringRef SymbolName = unwrapOrError(Obj.getFileName(), SymbolEntRef.getName()); - W.printNumber("Index", Obj.getSymbolIndex(SymbolEntRef.getEntryAddress())); + uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()); + XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass(); + + W.printNumber("Index", SymbolIdx); W.printString("Name", SymbolName); - W.printHex(GetSymbolValueName(SymbolEntRef.getStorageClass()), - SymbolEntRef.getValue()); + W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue()); StringRef SectionName = unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef)); W.printString("Section", SectionName); - if (SymbolEntRef.getStorageClass() == XCOFF::C_FILE) { + if (SymbolClass == XCOFF::C_FILE) { W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(), makeArrayRef(CFileLangIdClass)); W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(), @@ -370,15 +476,14 @@ } else W.printHex("Type", SymbolEntRef.getSymbolType()); - W.printEnum("StorageClass", - static_cast(SymbolEntRef.getStorageClass()), + W.printEnum("StorageClass", static_cast(SymbolClass), makeArrayRef(SymStorageClass)); W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries); if (NumberOfAuxEntries == 0) return; - switch (SymbolEntRef.getStorageClass()) { + switch (SymbolClass) { case XCOFF::C_FILE: // If the symbol is C_FILE and has auxiliary entries... for (int I = 1; I <= NumberOfAuxEntries; I++) { @@ -387,55 +492,62 @@ if (Obj.is64Bit() && *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) { - W.startLine() << "!Unexpected raw auxiliary entry data:\n"; - W.startLine() << format_bytes( - ArrayRef( - reinterpret_cast(AuxAddress), - XCOFF::SymbolTableEntrySize), - 0, XCOFF::SymbolTableEntrySize) - << "\n"; + printUnexpectedRawAuxEnt(W, AuxAddress); continue; } const XCOFFFileAuxEnt *FileAuxEntPtr = - reinterpret_cast(AuxAddress); -#ifndef NDEBUG - Obj.checkSymbolEntryPointer(reinterpret_cast(FileAuxEntPtr)); -#endif + getAuxEntPtr(AuxAddress); printFileAuxEnt(FileAuxEntPtr); } break; case XCOFF::C_EXT: case XCOFF::C_WEAKEXT: 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 (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 - // error information, print out the raw Auxiliary entry. - // For 32-bit object, print from first to the last - 1. The last one must be - // a CSECT Auxiliary Entry. - // For 64-bit object, print from first to last and skips if SymbolAuxType is - // AUX_CSECT. + if (!SymbolEntRef.isFunction() && NumberOfAuxEntries > 1) + reportUniqueWarning("the non-function " + + enum2String(static_cast(SymbolClass), + makeArrayRef(SymStorageClass)) + + " symbol at index " + Twine(SymbolIdx) + + " should have only 1 auxiliary entry, i.e. the CSECT " + "auxiliary entry"); + + // For 32-bit objects, print the function auxiliary symbol table entry. The + // last one must be a CSECT auxiliary entry. + // For 64-bit objects, both a function auxiliary entry and an exception + // auxiliary entry may appear, print them in the loop and skip printing the + // CSECT auxiliary entry, which will be printed outside the loop. for (int I = 1; I <= NumberOfAuxEntries; I++) { - if (I == NumberOfAuxEntries && !Obj.is64Bit()) + if ((I == NumberOfAuxEntries && !Obj.is64Bit()) || + !SymbolEntRef.isFunction()) break; uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( SymbolEntRef.getEntryAddress(), I); - if (Obj.is64Bit() && - *Obj.getSymbolAuxType(AuxAddress) == XCOFF::SymbolAuxType::AUX_CSECT) - continue; - W.startLine() << "!Unexpected raw auxiliary entry data:\n"; - W.startLine() << format_bytes( - ArrayRef(reinterpret_cast(AuxAddress), - XCOFF::SymbolTableEntrySize)); + if (Obj.is64Bit()) { + XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress); + if (Type == XCOFF::SymbolAuxType::AUX_CSECT) + continue; + else if (Type == XCOFF::SymbolAuxType::AUX_FCN) { + const XCOFFFunctionAuxEnt64 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + printFunctionAuxEnt(AuxEntPtr); + } else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) { + const XCOFFExceptionAuxEnt *AuxEntPtr = + getAuxEntPtr(AuxAddress); + printExceptionAuxEnt(AuxEntPtr); + } else { + printUnexpectedRawAuxEnt(W, AuxAddress); + } + } else { + const XCOFFFunctionAuxEnt32 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + printFunctionAuxEnt(AuxEntPtr); + } } + // Print the CSECT auxiliary entry. auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef(); if (!ErrOrCsectAuxRef) reportUniqueWarning(ErrOrCsectAuxRef.takeError()); @@ -444,34 +556,66 @@ break; } - case XCOFF::C_STAT: + 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( - XCOFFObjectFile::getAdvancedSymbolEntryAddress( - SymbolEntRef.getEntryAddress(), 1)); -#ifndef NDEBUG - Obj.checkSymbolEntryPointer(reinterpret_cast(StatAuxEntPtr)); -#endif + reportUniqueWarning("the C_STAT symbol at index " + Twine(SymbolIdx) + + " should not have more than 1 auxiliary entry"); + + const XCOFFSectAuxEntForStat *StatAuxEntPtr = + getAuxEntPtr( + XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), 1)); printSectAuxEntForStat(StatAuxEntPtr); break; - case XCOFF::C_DWARF: + } + case XCOFF::C_DWARF: { + if (NumberOfAuxEntries > 1) + reportUniqueWarning("the C_DWARF symbol at index " + Twine(SymbolIdx) + + " should not have more than 1 auxiliary entry"); + + uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), 1); + + if (Obj.is64Bit()) { + const XCOFFSectAuxEntForDWARF64 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + printSectAuxEntForDWARF(AuxEntPtr); + } else { + const XCOFFSectAuxEntForDWARF32 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + printSectAuxEntForDWARF(AuxEntPtr); + } + break; + } case XCOFF::C_BLOCK: - case XCOFF::C_FCN: - report_fatal_error("Symbol table entry printing for this storage class " - "type is unimplemented."); + case XCOFF::C_FCN: { + if (NumberOfAuxEntries > 1) + reportUniqueWarning("the " + + enum2String(static_cast(SymbolClass), + makeArrayRef(SymStorageClass)) + + " symbol at index " + Twine(SymbolIdx) + + " should not have more than 1 " + "auxiliary entry"); + + uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), 1); + + if (Obj.is64Bit()) { + const XCOFFBlockAuxEnt64 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + printBlockAuxEnt(AuxEntPtr); + } else { + const XCOFFBlockAuxEnt32 *AuxEntPtr = + getAuxEntPtr(AuxAddress); + printBlockAuxEnt(AuxEntPtr); + } break; + } default: for (int i = 1; i <= NumberOfAuxEntries; i++) { - W.startLine() << "!Unexpected raw auxiliary entry data:\n"; - W.startLine() << format_bytes( - ArrayRef(reinterpret_cast( - XCOFFObjectFile::getAdvancedSymbolEntryAddress( - SymbolEntRef.getEntryAddress(), i)), - XCOFF::SymbolTableEntrySize)); + printUnexpectedRawAuxEnt(W, + XCOFFObjectFile::getAdvancedSymbolEntryAddress( + SymbolEntRef.getEntryAddress(), i)); } break; }