diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst index eb1bb933eccaf3..64373755fdf319 100644 --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -338,6 +338,10 @@ The following options are implemented only for the XCOFF file format. Display XCOFF loader section header. +.. option:: --loader-section-symbols + + Display symbol table of loader section. + EXIT STATUS ----------- diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h index da27fc0b52a649..2becf56c2079d9 100644 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -204,6 +204,10 @@ struct LoaderSectionHeader32 { support::big32_t OffsetToImpid; support::ubig32_t LengthOfStrTbl; support::big32_t OffsetToStrTbl; + + uint64_t getOffsetToSymTbl() const { + return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32); + } }; struct LoaderSectionHeader64 { @@ -217,6 +221,39 @@ struct LoaderSectionHeader64 { support::big64_t OffsetToStrTbl; support::big64_t OffsetToSymTbl; support::big64_t OffsetToRelEnt; + + uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; } +}; + +struct LoaderSectionSymbolEntry32 { + struct NameOffsetInStrTbl { + support::big32_t IsNameInStrTbl; // Zero indicates name in string table. + support::ubig32_t Offset; + }; + + char SymbolName[XCOFF::NameSize]; + support::ubig32_t Value; // The virtual address of the symbol. + support::big16_t SectionNumber; + uint8_t SymbolType; + XCOFF::StorageClass StorageClass; + support::ubig32_t ImportFileID; + support::ubig32_t ParameterTypeCheck; + + Expected + getSymbolName(const LoaderSectionHeader32 *LoaderSecHeader) const; +}; + +struct LoaderSectionSymbolEntry64 { + support::ubig64_t Value; // The virtual address of the symbol. + support::ubig32_t Offset; + support::big16_t SectionNumber; + uint8_t SymbolType; + XCOFF::StorageClass StorageClass; + support::ubig32_t ImportFileID; + support::ubig32_t ParameterTypeCheck; + + Expected + getSymbolName(const LoaderSectionHeader64 *LoaderSecHeader) const; }; template struct ExceptionSectionEntry { diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp index c758e3508fd898..061c47d3eb56d2 100644 --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -89,6 +89,34 @@ uint8_t XCOFFRelocation::getRelocatedLength() const { template struct ExceptionSectionEntry; template struct ExceptionSectionEntry; +template +Expected getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader, + uint64_t Offset) { + if (LoaderSecHeader->LengthOfStrTbl > Offset) + return (reinterpret_cast(LoaderSecHeader) + + LoaderSecHeader->OffsetToStrTbl + Offset); + + return createError("entry with offset 0x" + Twine::utohexstr(Offset) + + " in the loader section's string table with size 0x" + + Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) + + " is invalid"); +} + +Expected LoaderSectionSymbolEntry32::getSymbolName( + const LoaderSectionHeader32 *LoaderSecHeader32) const { + const NameOffsetInStrTbl *NameInStrTbl = + reinterpret_cast(SymbolName); + if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) + return generateXCOFFFixedNameStringRef(SymbolName); + + return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset); +} + +Expected LoaderSectionSymbolEntry64::getSymbolName( + const LoaderSectionHeader64 *LoaderSecHeader64) const { + return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset); +} + uintptr_t XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, uint32_t Distance) { diff --git a/llvm/test/tools/llvm-readobj/XCOFF/loader-section-invalid-stringtable-offset.test b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-invalid-stringtable-offset.test new file mode 100644 index 00000000000000..d6cb1d4f9e7111 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-invalid-stringtable-offset.test @@ -0,0 +1,38 @@ +## Test invalid offset to symbol string table of loader section for --loader-section-symbols option. + +# RUN: yaml2obj %s -o %t_xcoff.o +# RUN: llvm-readobj --loader-section-symbols %t_xcoff.o 2>&1 | FileCheck -DFILE=%t_xcoff.o %s + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Sections: + - Name: .loader + Flags: [ STYP_LOADER ] + SectionData: "0000000100000002000000050000016D00000001000000A40000000c000000506d79696e747661722000028000021105000000000000000000000000000000A2200002840002110a0000000000000000000a66756e63305f5f467600" +## ^------- -Version=1 +## ^------- -NumberOfSymbolEntries=2 +## ^------- -NumberOfRelocationEntries=5 +## ^------- -LengthOfImportFileIDStringTable=365 +## ^------- -NumberOfImportFileIDs=1 +## ^------- -OffsetToImportFileIDs=0xA4 +## ^------- -LengthOfStringTable=12 +## ^------- -OffsetToStringTable=0x050 +## ^--------------- SymbolName=myintvar +## ^------- Value=0x20000280 +## ^--- sectionNumber = 2 +## ^- SymbolType=0x11 +## ^- StorageClass=0x0a +## ^------- ImportFileID=0 +## ^-------ParameterCheckType=0 +## ^-------SymbolZero=0 +## ^-------OffsetToStringTbl=0xA2 (Invalid) +## ^------- Value=20000284 +## ^--- sectionNumber = 2 +## ^- SymbolType=0x11 +## ^- StorageClass=0x0a +## ^------- ImportFileID=0 +## ^-------ParameterCheckType=0 +## ^StringTable + +# CHECK: warning: '[[FILE]]': entry with offset 0xa2 in the loader section's string table with size 0xc is invalid diff --git a/llvm/test/tools/llvm-readobj/XCOFF/loader-section-symbol.test b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-symbol.test new file mode 100644 index 00000000000000..6e532dfbf2feb2 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-symbol.test @@ -0,0 +1,124 @@ +## Test the --loader-section-symbols option. + +# RUN: yaml2obj --docnum=1 -DSYMNUM=2 %s -o %t_xcoff32.o +# RUN: yaml2obj --docnum=1 -DSYMNUM=4 %s -o %t_xcoff32_invalid.o +# RUN: yaml2obj --docnum=2 %s -o %t_xcoff64.o + +# RUN: llvm-readobj --loader-section-symbols %t_xcoff32.o |\ +# RUN: FileCheck %s --check-prefixes=CHECK32 +# RUN: llvm-readobj --loader-section-symbols %t_xcoff32_invalid.o 2>&1 |\ +# RUN: FileCheck -DFILE=%t_xcoff32_invalid.o %s --check-prefixes=CHECK32,WARN +# RUN: llvm-readobj --loader-section-symbols %t_xcoff64.o |\ +# RUN: FileCheck %s --check-prefixes=CHECK64 + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Sections: + - Name: .loader + Flags: [ STYP_LOADER ] + SectionData: "000000010000000[[SYMNUM]]000000050000016D00000001000000A40000000c000000506d79696e74766172200002800002110500000000000000000000000000000002200002840002110a0000000000000000000a66756e63305f5f467600" +## ^------- -Version=1 +## ^---------------- -NumberOfSymbolEntries=SYMNUM +## ^------- -NumberOfRelocationEntries=5 +## ^------- -LengthOfImportFileIDStringTable=365 +## ^------- -NumberOfImportFileIDs=1 +## ^------- -OffsetToImportFileIDs=0xA4 +## ^------- -LengthOfStringTable=12 +## ^------- -OffsetToStringTable=0x050 +## ^--------------- SymbolName=myintvar +## ^------- Value=0x20000280 +## ^--- sectionNumber = 2 +## ^- SymbolType=0x11 +## ^- StorageClass=0x05 +## ^------- ImportFileID=0 +## ^-------ParameterCheckType=0 +## ^-------SymbolZero=0 +## ^-------OffsetToSymTbl=2 +## ^------- Value=20000284 +## ^--- sectionNumber = 2 +## ^- SymbolType=0x11 +## ^- StorageClass=0x0a +## ^------- ImportFileID=0 +## ^-------ParameterCheckType=0 +## ^StringTable + +--- !XCOFF +FileHeader: + MagicNumber: 0x1F7 +Sections: + - Name: .loader + Flags: [ STYP_LOADER ] + SectionData: "0000000200000002000000050000016D000000010000001200000000000000D000000000000000680000000000000038000000000000008000000001100003000000000200021105000000000000000000000001100003080000000d0002110a000000000000000000096d79696e7476617200000a5f5a3566756e6330760000" +## ^------- -Version=2 +## ^------- -NumberOfSymbolEntries=2 +## ^------- -NumberOfRelocationEntries=5 +## ^------- -LengthOfImportFileIDStringTable=365 +## ^------- -NumberOfImportFileIDs=1 +## ^------- --LengthOfStringTable=0x12 +## ^--------------- -OffsetToImportFileIDs=0xD0 +## ^--------------- -OffsetToStringTable=0x68 +## ^--------------- -OffsetToSymbolTable=0x38 +## ^--------------- -OffsetToRelocationEntries=0x80 +## ^--------------- Value=0x0000000110000300 +## ^------- OffsetToStringTbl=2 +## ^--- sectionNumber = 2 +## ^- SymbolType=0x11 +## ^- StorageClass=0x05 +## ^------- ImportFileID=0 +## ^-------ParameterCheckType=0 +## ^--------------- Value=0x0000000110000308 +## ^------- OffsetToStringTbl= 0x0d +## ^--- sectionNumber = 2 +## ^- SymbolType=0x11 +## ^- StorageClass=0x0a +## ^------- ImportFileID=0 +## ^-------ParameterCheckType=0 +## ^StringTable + +# CHECK32: Loader Section { +# CHECK32-NEXT: Loader Section Symbols { +# CHECK32-NEXT: Symbol { +# CHECK32-NEXT: Name: myintvar +# CHECK32-NEXT: Virtual Address: 0x20000280 +# CHECK32-NEXT: SectionNum: 2 +# CHECK32-NEXT: SymbolType: 0x11 +# CHECK32-NEXT: StorageClass: C_EXTDEF (0x5) +# CHECK32-NEXT: ImportFileID: 0x0 +# CHECK32-NEXT: ParameterTypeCheck: 0 +# CHECK32-NEXT: } +# CHECK32-NEXT: Symbol { +# CHECK32-NEXT: Name: func0__Fv +# CHECK32-NEXT: Virtual Address: 0x20000284 +# CHECK32-NEXT: SectionNum: 2 +# CHECK32-NEXT: SymbolType: 0x11 +# CHECK32-NEXT: StorageClass: C_STRTAG (0xA) +# CHECK32-NEXT: ImportFileID: 0x0 +# CHECK32-NEXT: ParameterTypeCheck: 0 +# CHECK32-NEXT: } +# WARN: warning: '[[FILE]]': The end of the file was unexpectedly encountered +# CHECK32-NEXT: } +# CHECK32-NEXT: } + +# CHECK64: Loader Section { +# CHECK64-NEXT: Loader Section Symbols { +# CHECK64-NEXT: Symbol { +# CHECK64-NEXT: Name: myintvar +# CHECK64-NEXT: Virtual Address: 0x110000300 +# CHECK64-NEXT: SectionNum: 2 +# CHECK64-NEXT: SymbolType: 0x11 +# CHECK64-NEXT: StorageClass: C_EXTDEF (0x5) +# CHECK64-NEXT: ImportFileID: 0x0 +# CHECK64-NEXT: ParameterTypeCheck: 0 +# CHECK64-NEXT: } +# CHECK64-NEXT: Symbol { +# CHECK64-NEXT: Name: _Z5func0v +# CHECK64-NEXT: Virtual Address: 0x110000308 +# CHECK64-NEXT: SectionNum: 2 +# CHECK64-NEXT: SymbolType: 0x11 +# CHECK64-NEXT: StorageClass: C_STRTAG (0xA) +# CHECK64-NEXT: ImportFileID: 0x0 +# CHECK64-NEXT: ParameterTypeCheck: 0 +# CHECK64-NEXT: } +# CHECK64-NEXT: } +# CHECK64-NEXT: } diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h index 2a6af54eb14a16..4aff9fb7a3d918 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -158,7 +158,7 @@ class ObjDumper { // Only implement for XCOFF virtual void printAuxiliaryHeader() {} virtual void printExceptionSection() {} - virtual void printLoaderSection(bool PrintHeader) {} + virtual void printLoaderSection(bool PrintHeader, bool PrintSymbolTable) {} // Only implemented for MachO. virtual void printMachODataInCode() { } diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index 4f126d673c462a..7d0e64ad42c045 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -90,6 +90,7 @@ def grp_xcoff : OptionGroup<"kind">, HelpText<"OPTIONS (XCOFF specific)">; def auxiliary_header : FF<"auxiliary-header" , "Display the auxiliary header">, Group; def exception_section : FF<"exception-section" , "Display the exception section entries">, Group; def loader_section_header : FF<"loader-section-header" , "Display the loader section header">, Group; +def loader_section_symbols : FF<"loader-section-symbols" , "Display the loader section symbol table">, Group; def help : FF<"help", "Display this help">; def version : FF<"version", "Display the version">; diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp index 9e52f86a08fc98..c03cdd14c0e75e 100644 --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -40,7 +40,7 @@ class XCOFFDumper : public ObjDumper { void printNeededLibraries() override; void printStringTable() override; void printExceptionSection() override; - void printLoaderSection(bool PrintHeader) override; + void printLoaderSection(bool PrintHeader, bool PrintSymbolTable) override; ScopedPrinter &getScopedPrinter() const { return W; } @@ -68,6 +68,9 @@ class XCOFFDumper : public ObjDumper { void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader); void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader); void printLoaderSectionHeader(uintptr_t LoaderSectAddr); + void printLoaderSectionSymbols(uintptr_t LoaderSectAddr); + template + void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr); const XCOFFObjectFile &Obj; }; } // anonymous namespace @@ -135,7 +138,7 @@ void XCOFFDumper::printSectionHeaders() { printSectionHeaders(Obj.sections32()); } -void XCOFFDumper::printLoaderSection(bool PrintHeader) { +void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbolTable) { DictScope DS(W, "Loader Section"); Expected LoaderSectionAddrOrError = Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER); @@ -145,13 +148,18 @@ void XCOFFDumper::printLoaderSection(bool PrintHeader) { } uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); + if (LoaderSectionAddr == 0) + return; + W.indent(); if (PrintHeader) printLoaderSectionHeader(LoaderSectionAddr); - // TODO: Need to print symbol table, relocation entry of loader section later. + + if (PrintSymbolTable) + printLoaderSectionSymbols(LoaderSectionAddr); + + // TODO: Need to add printing of relocation entry of loader section later. // For example: - // if (PrintSymbolTable) - // printLoaderSectionSymbolTable(); // if (PrintRelocation) // printLoaderSectionRelocationEntry(); W.unindent(); @@ -185,6 +193,73 @@ void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) { } } +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 +}; + +template +void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) { + const LoaderSectionHeader *LoadSecHeader = + reinterpret_cast(LoaderSectionAddr); + const LoaderSectionSymbolEntry *LoadSecSymEntPtr = + reinterpret_cast( + LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl())); + + for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt; + ++i, ++LoadSecSymEntPtr) { + if (Error E = Binary::checkOffset( + Obj.getMemoryBufferRef(), + LoaderSectionAddr + (i * sizeof(LoaderSectionSymbolEntry)), + sizeof(LoaderSectionSymbolEntry))) { + reportUniqueWarning(std::move(E)); + return; + } + + Expected SymbolNameOrErr = + LoadSecSymEntPtr->getSymbolName(LoadSecHeader); + if (!SymbolNameOrErr) { + reportUniqueWarning(SymbolNameOrErr.takeError()); + return; + } + + DictScope DS(W, "Symbol"); + W.printString("Name", SymbolNameOrErr.get()); + W.printHex("Virtual Address", LoadSecSymEntPtr->Value); + W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber); + W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType); + W.printEnum("StorageClass", + static_cast(LoadSecSymEntPtr->StorageClass), + makeArrayRef(SymStorageClass)); + W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID); + W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck); + } +} + +void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) { + DictScope DS(W, "Loader Section Symbols"); + if (Obj.is64Bit()) + printLoaderSectionSymbolsHelper(LoaderSectionAddr); + else + printLoaderSectionSymbolsHelper(LoaderSectionAddr); +} + template void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const { if (ExceptionSectEnt.getReason()) @@ -468,25 +543,6 @@ void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) { makeArrayRef(SymAuxType)); } -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: diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index fadf1445b76dde..ac1d9d9d1b3a00 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -163,6 +163,7 @@ static bool COFFTLSDirectory; // XCOFF specific options. static bool XCOFFAuxiliaryHeader; static bool XCOFFLoaderSectionHeader; +static bool XCOFFLoaderSectionSymbol; static bool XCOFFExceptionSection; OutputStyleTy Output = OutputStyleTy::LLVM; @@ -305,6 +306,7 @@ static void parseOptions(const opt::InputArgList &Args) { // XCOFF specific options. opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header); opts::XCOFFLoaderSectionHeader = Args.hasArg(OPT_loader_section_header); + opts::XCOFFLoaderSectionSymbol = Args.hasArg(OPT_loader_section_symbols); opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section); opts::InputFilenames = Args.getAllArgValues(OPT_INPUT); @@ -510,8 +512,9 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, } if (Obj.isXCOFF()) { - if (opts::XCOFFLoaderSectionHeader) - Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader); + if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol) + Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader, + opts::XCOFFLoaderSectionSymbol); if (opts::XCOFFExceptionSection) Dumper->printExceptionSection();