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 @@ -195,7 +195,32 @@ char Padding[4]; }; -struct LoaderSectionHeader32 { +template struct LoaderSectionHeader { + uint32_t getVersion() const { return static_cast(this)->Version; } + uint32_t getNumOfSymTblEnt() const { + return static_cast(this)->NumberOfSymTabEnt; + } + uint32_t getNumOfRelTbleEnt() const { + return static_cast(this)->NumberOfRelTabEnt; + } + uint32_t getLengthOfImpidStrTbl() const { + return static_cast(this)->LengthOfImpidStrTbl; + } + uint32_t getNumberOfImpIds() const { + return static_cast(this)->NumberOfImpid; + } + uint64_t getOffsetToImpids() const { + return static_cast(this)->OffsetToImpid; + } + uint32_t getLengthOfStrTbl() const { + return static_cast(this)->LengthOfStrTbl; + } + uint64_t getOffsetToStrTbl() const { + return static_cast(this)->OffsetToStrTbl; + } +}; + +struct LoaderSectionHeader32 : LoaderSectionHeader { support::ubig32_t Version; support::ubig32_t NumberOfSymTabEnt; support::ubig32_t NumberOfRelTabEnt; @@ -206,7 +231,7 @@ support::big32_t OffsetToStrTbl; }; -struct LoaderSectionHeader64 { +struct LoaderSectionHeader64 : LoaderSectionHeader { support::ubig32_t Version; support::ubig32_t NumberOfSymTabEnt; support::ubig32_t NumberOfRelTabEnt; @@ -216,8 +241,10 @@ support::big64_t OffsetToImpid; support::big64_t OffsetToStrTbl; support::big64_t OffsetToSymTbl; - char Padding[16]; - support::big32_t OffsetToRelEnt; + support::big64_t OffsetToRelEnt; + + uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; } + uint64_t getOffsetToRelEnt() const { return OffsetToRelEnt; } }; template struct ExceptionSectionEntry { @@ -494,8 +521,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 +663,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.test b/llvm/test/tools/llvm-readobj/XCOFF/loader-section.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/XCOFF/loader-section.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=1 +## ^------- -NumberOfSymbolEntries=3 +## ^------- -NumberOfRelocationEntries=5 +## ^------- -LengthOfImportFileIDStringTable=365 +## ^------- -NumberOfImportFileIDs=1 +## ^------- --LengthOfStringTable=0xA4 +## ^--------------- -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,8 @@ // Only implement for XCOFF virtual void printAuxiliaryHeader() {} virtual void printExceptionSection() {} + virtual void printLoaderSection() {} + virtual void setPrintLoaderSectionHeader() {} // 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,11 @@ void printNeededLibraries() override; void printStringTable() override; void printExceptionSection() override; + void printLoaderSection() override; + + void setPrintLoaderSectionHeader() override { + PrintLoaderSectionHeader = true; + } ScopedPrinter &getScopedPrinter() const { return W; } @@ -66,7 +71,9 @@ void printRelocations(ArrayRef Sections); void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader); void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader); + void printLoaderSectionHeader(uintptr_t LoaderSectAddr); const XCOFFObjectFile &Obj; + bool PrintLoaderSectionHeader = false; }; } // anonymous namespace @@ -133,6 +140,57 @@ printSectionHeaders(Obj.sections32()); } +void XCOFFDumper::printLoaderSection() { + 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 (PrintLoaderSectionHeader) + XCOFFDumper::printLoaderSectionHeader(LoaderSectionAddr); + // TODO: Need to print symbol table, relocation entry of loader section later. + // For example: + // if (PrintLoaderSectionSymbolTable) + // XCOFFDumper::printLoaderSectionSymbolTable(); + // if (PrintLoaderSectionRelocationEntry) + // XCOFFDumper::printLoaderSectionRelocationEntry(); + W.unindent(); +} + +void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) { + + DictScope DS(W, "Loader Section Header"); + + auto printLoadSecHeaderCommon = [&](auto *LDHeader) { + W.printNumber("Version", LDHeader->getVersion()); + W.printNumber("NumberOfSymbolEntries", LDHeader->getNumOfSymTblEnt()); + W.printNumber("NumberOfRelocationEntries", LDHeader->getNumOfRelTbleEnt()); + W.printNumber("LengthOfImportFileIDStringTable", + LDHeader->getLengthOfImpidStrTbl()); + W.printNumber("NumberOfImportFileIDs", LDHeader->getNumberOfImpIds()); + W.printHex("OffsetToImportFileIDs", LDHeader->getOffsetToImpids()); + W.printNumber("LengthOfStringTable", LDHeader->getLengthOfStrTbl()); + W.printHex("OffsetToStringTable", LDHeader->getOffsetToStrTbl()); + }; + + if (Obj.is64Bit()) { + const LoaderSectionHeader64 *LoaderSec64 = + reinterpret_cast(LoaderSectionAddr); + printLoadSecHeaderCommon(LoaderSec64); + W.printHex("OffsetToSymbolTable", LoaderSec64->getOffsetToSymTbl()); + W.printHex("OffsetToRelocationEntries", LoaderSec64->getOffsetToRelEnt()); + } 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,14 @@ Dumper->printCGProfile(); } - if (Obj.isXCOFF() && opts::XCOFFExceptionSection) - Dumper->printExceptionSection(); + if (Obj.isXCOFF()) { + if (opts::XCOFFLoaderSectionHeader) { + Dumper->setPrintLoaderSectionHeader(); + Dumper->printLoaderSection(); + } + if (opts::XCOFFExceptionSection) + Dumper->printExceptionSection(); + } if (opts::PrintStackMap) Dumper->printStackMap();