diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -334,6 +334,10 @@ Display XCOFF exception section entries. +.. option:: --loader-section-header + + Display XCOFF loader section header. + EXIT STATUS ----------- 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 @@ -216,8 +216,7 @@ support::big64_t OffsetToImpid; support::big64_t OffsetToStrTbl; support::big64_t OffsetToSymTbl; - char Padding[16]; - support::big32_t OffsetToRelEnt; + support::big64_t OffsetToRelEnt; }; template struct ExceptionSectionEntry { @@ -494,8 +493,6 @@ DataRefImpl getSectionByType(XCOFF::SectionTypeFlags SectType) const; uint64_t getSectionFileOffsetToRawData(DataRefImpl Sec) const; - Expected - getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const; // This returns a pointer to the start of the storage for the name field of // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily @@ -638,6 +635,9 @@ int32_t getSectionFlags(DataRefImpl Sec) const; Expected getSectionByNum(int16_t Num) const; + Expected + getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const; + void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const; // Relocation-related interfaces. diff --git a/llvm/test/tools/llvm-readobj/XCOFF/loader-section-header.test b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-header.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-header.test @@ -0,0 +1,71 @@ +## Test the --loader-section-header option. + +# RUN: yaml2obj --docnum=1 %s -o %t_xcoff32.o +# RUN: yaml2obj --docnum=2 %s -o %t_xcoff64.o +# RUN: llvm-readobj --loader-section-header %t_xcoff32.o |\ +# RUN: FileCheck %s --check-prefixes=CHECK32 +# RUN: llvm-readobj --loader-section-header %t_xcoff64.o |\ +# RUN: FileCheck %s --check-prefixes=CHECK64 + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF +Sections: + - Name: .loader + Flags: [ STYP_LOADER ] + SectionData: "0000000100000003000000050000016D00000001000000A40000001800000211" +## ^------- -Version=1 +## ^------- -NumberOfSymbolEntries=3 +## ^------- -NumberOfRelocationEntries=5 +## ^------- -LengthOfImportFileIDStringTable=365 +## ^------- -NumberOfImportFileIDs=1 +## ^------- -OffsetToImportFileIDs=0xA4 +## ^------- -LengthOfStringTable=24 +## ^------- -OffsetToStringTable=0x211 + + +--- !XCOFF +FileHeader: + MagicNumber: 0x1F7 +Sections: + - Name: .loader + Flags: [ STYP_LOADER ] + SectionData: "0000000200000003000000050000016D000000010000002300000000000000D0000000000000023D00000000000000380000000000000080" +## ^------- -Version=2 +## ^------- -NumberOfSymbolEntries=3 +## ^------- -NumberOfRelocationEntries=5 +## ^------- -LengthOfImportFileIDStringTable=365 +## ^------- -NumberOfImportFileIDs=1 +## ^------- --LengthOfStringTable=0x23 +## ^--------------- -OffsetToImportFileIDs=0xD0 +## ^--------------- -OffsetToStringTable=0x23D +## ^-------------- -OffsetToSymbolTable=0x38 +## ^--------------- -OffsetToRelocationEntries=0x80 + +# CHECK32: Loader Section { +# CHECK32-NEXT: Loader Section Header { +# CHECK32-NEXT: Version: 1 +# CHECK32-NEXT: NumberOfSymbolEntries: 3 +# CHECK32-NEXT: NumberOfRelocationEntries: 5 +# CHECK32-NEXT: LengthOfImportFileIDStringTable: 365 +# CHECK32-NEXT: NumberOfImportFileIDs: 1 +# CHECK32-NEXT: OffsetToImportFileIDs: 0xA4 +# CHECK32-NEXT: LengthOfStringTable: 24 +# CHECK32-NEXT: OffsetToStringTable: 0x211 +# CHECK32-NEXT: } +# CHECK32-NEXT: } + +# CHECK64: Loader Section { +# CHECK64-NEXT: Loader Section Header { +# CHECK64-NEXT: Version: 2 +# CHECK64-NEXT: NumberOfSymbolEntries: 3 +# CHECK64-NEXT: NumberOfRelocationEntries: 5 +# CHECK64-NEXT: LengthOfImportFileIDStringTable: 365 +# CHECK64-NEXT: NumberOfImportFileIDs: 1 +# CHECK64-NEXT: OffsetToImportFileIDs: 0xD0 +# CHECK64-NEXT: LengthOfStringTable: 35 +# CHECK64-NEXT: OffsetToStringTable: 0x23D +# CHECK64-NEXT: OffsetToSymbolTable: 0x38 +# CHECK64-NEXT: OffsetToRelocationEntries: 0x80 +# CHECK64-NEXT: } +# CHECK64-NEXT: } diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -158,6 +158,7 @@ // Only implement for XCOFF virtual void printAuxiliaryHeader() {} virtual void printExceptionSection() {} + virtual void printLoaderSection(bool PrintHeader) {} // Only implemented for MachO. virtual void printMachODataInCode() { } diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -89,6 +89,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 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 --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -40,6 +40,7 @@ void printNeededLibraries() override; void printStringTable() override; void printExceptionSection() override; + void printLoaderSection(bool PrintHeader) override; ScopedPrinter &getScopedPrinter() const { return W; } @@ -66,6 +67,7 @@ void printRelocations(ArrayRef Sections); void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader); void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader); + void printLoaderSectionHeader(uintptr_t LoaderSectAddr); const XCOFFObjectFile &Obj; }; } // anonymous namespace @@ -133,6 +135,56 @@ printSectionHeaders(Obj.sections32()); } +void XCOFFDumper::printLoaderSection(bool PrintHeader) { + DictScope DS(W, "Loader Section"); + Expected LoaderSectionAddrOrError = + Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER); + if (!LoaderSectionAddrOrError) { + reportUniqueWarning(LoaderSectionAddrOrError.takeError()); + return; + } + uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); + + W.indent(); + if (PrintHeader) + printLoaderSectionHeader(LoaderSectionAddr); + // TODO: Need to print symbol table, relocation entry of loader section later. + // For example: + // if (PrintSymbolTable) + // printLoaderSectionSymbolTable(); + // if (PrintRelocation) + // printLoaderSectionRelocationEntry(); + W.unindent(); +} + +void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) { + DictScope DS(W, "Loader Section Header"); + + auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) { + W.printNumber("Version", LDHeader->Version); + W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt); + W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt); + W.printNumber("LengthOfImportFileIDStringTable", + LDHeader->LengthOfImpidStrTbl); + W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid); + W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid); + W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl); + W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl); + }; + + if (Obj.is64Bit()) { + const LoaderSectionHeader64 *LoaderSec64 = + reinterpret_cast(LoaderSectionAddr); + PrintLoadSecHeaderCommon(LoaderSec64); + W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl); + W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt); + } else { + const LoaderSectionHeader32 *LoaderSec32 = + reinterpret_cast(LoaderSectionAddr); + PrintLoadSecHeaderCommon(LoaderSec32); + } +} + template void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const { if (ExceptionSectEnt.getReason()) diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -162,6 +162,7 @@ // XCOFF specific options. static bool XCOFFAuxiliaryHeader; +static bool XCOFFLoaderSectionHeader; static bool XCOFFExceptionSection; OutputStyleTy Output = OutputStyleTy::LLVM; @@ -303,6 +304,7 @@ // XCOFF specific options. opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header); + opts::XCOFFLoaderSectionHeader = Args.hasArg(OPT_loader_section_header); opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section); opts::InputFilenames = Args.getAllArgValues(OPT_INPUT); @@ -507,8 +509,13 @@ Dumper->printCGProfile(); } - if (Obj.isXCOFF() && opts::XCOFFExceptionSection) - Dumper->printExceptionSection(); + if (Obj.isXCOFF()) { + if (opts::XCOFFLoaderSectionHeader) + Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader); + + if (opts::XCOFFExceptionSection) + Dumper->printExceptionSection(); + } if (opts::PrintStackMap) Dumper->printStackMap();