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 @@ -311,6 +311,15 @@ Display the .rsrc section. +XCOFF SPECIFIC OPTIONS +---------------------- + +The following options are implemented only for the XCOFF file format. + +.. option:: --auxiliary-header + + Display XCOFF Auxiliary 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 @@ -51,6 +51,101 @@ support::ubig32_t NumberOfSymTableEntries; }; +template struct XCOFFAuxiliaryHeader { + static constexpr uint8_t AuxiHeaderFlagMask = 0xF0; + static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F; + +public: + uint8_t getFlag() const { + return static_cast(this)->FlagAndTDataAlignment & + AuxiHeaderFlagMask; + } + uint8_t getTDataAlignment() const { + return static_cast(this)->FlagAndTDataAlignment & + AuxiHeaderTDataAlignmentMask; + } +}; + +struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader { + support::ubig16_t + AuxMagic; ///< If the value of the o_vstamp field is greater than 1, the + ///< o_mflags field is reserved for future use and it should + ///< contain 0. Otherwise, this field is not used. + support::ubig16_t + Version; ///< The valid values are 1 and 2. When the o_vstamp field is 2 + ///< in an XCOFF32 file, the new interpretation of the n_type + ///< field in the symbol table entry is used. + support::ubig32_t TextSize; + support::ubig32_t InitDataSize; + support::ubig32_t BssDataSize; + support::ubig32_t EntryPointAddr; + support::ubig32_t TextStartAddr; + support::ubig32_t DataStartAddr; + support::ubig32_t TOCAnchorAddr; + support::ubig16_t SecNumOfEntryPoint; + support::ubig16_t SecNumOfText; + support::ubig16_t SecNumOfData; + support::ubig16_t SecNumOfTOC; + support::ubig16_t SecNumOfLoader; + support::ubig16_t SecNumOfBSS; + support::ubig16_t MaxAlignOfText; + support::ubig16_t MaxAlignOfData; + support::ubig16_t ModuleType; + uint8_t CpuFlag; + uint8_t CpuType; + support::ubig32_t MaxStackSize; ///< If the value is 0, the system default + ///< maximum stack size is used. + support::ubig32_t MaxDataSize; ///< If the value is 0, the system default + ///< maximum data size is used. + support::ubig32_t + ReservedForDebugger; ///< This field should contain 0. When a loaded + ///< program is being debugged, the memory image of + ///< this field may be modified by a debugger to + ///< insert a trap instruction. + uint8_t TextPageSize; ///< Specifies the size of pages for the exec text. The + ///< default value is 0 (system-selected page size). + uint8_t DataPageSize; ///< Specifies the size of pages for the exec data. The + ///< default value is 0 (system-selected page size). + uint8_t StackPageSize; ///< Specifies the size of pages for the stack. The + ///< default value is 0 (system-selected page size). + uint8_t FlagAndTDataAlignment; + support::ubig16_t SecNumOfTData; + support::ubig16_t SecNumOfTBSS; +}; + +struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader { + support::ubig16_t AuxMagic; + support::ubig16_t Version; + support::ubig32_t ReservedForDebugger; + support::ubig64_t TextStartAddr; + support::ubig64_t DataStartAddr; + support::ubig64_t TOCAnchorAddr; + support::ubig16_t SecNumOfEntryPoint; + support::ubig16_t SecNumOfText; + support::ubig16_t SecNumOfData; + support::ubig16_t SecNumOfTOC; + support::ubig16_t SecNumOfLoader; + support::ubig16_t SecNumOfBSS; + support::ubig16_t MaxAlignOfText; + support::ubig16_t MaxAlignOfData; + support::ubig16_t ModuleType; + uint8_t CpuFlag; + uint8_t CpuType; + uint8_t TextPageSize; + uint8_t DataPageSize; + uint8_t StackPageSize; + uint8_t FlagAndTDataAlignment; + support::ubig64_t TextSize; + support::ubig64_t InitDataSize; + support::ubig64_t BssDataSize; + support::ubig64_t EntryPointAddr; + support::ubig64_t MaxStackSize; + support::ubig64_t MaxDataSize; + support::ubig16_t SecNumOfTData; + support::ubig16_t SecNumOfTBSS; + support::ubig16_t XCOFF64Flag; +}; + template struct XCOFFSectionHeader { // Least significant 3 bits are reserved. static constexpr unsigned SectionFlagsReservedMask = 0x7; @@ -296,6 +391,7 @@ class XCOFFObjectFile : public ObjectFile { private: const void *FileHeader = nullptr; + const void *AuxiliaryHeader = nullptr; const void *SectionHeaderTable = nullptr; const void *SymbolTblPtr = nullptr; @@ -402,6 +498,9 @@ // Below here is the non-inherited interface. bool is64Bit() const; + const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const; + const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const; + const void *getPointerToSymbolTable() const { return SymbolTblPtr; } Expected getSymbolSectionName(XCOFFSymbolRef Ref) const; 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 @@ -149,6 +149,16 @@ return static_cast(FileHeader); } +const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const { + assert(!is64Bit() && "32-bit interface called on 64-bit object file."); + return static_cast(AuxiliaryHeader); +} + +const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const { + assert(is64Bit() && "64-bit interface called on a 32-bit object file."); + return static_cast(AuxiliaryHeader); +} + template const T *XCOFFObjectFile::sectionHeaderTable() const { return static_cast(SectionHeaderTable); } @@ -1027,8 +1037,15 @@ Obj->FileHeader = FileHeaderOrErr.get(); CurOffset += Obj->getFileHeaderSize(); - // TODO FIXME we don't have support for an optional header yet, so just skip - // past it. + + if (Obj->getOptionalHeaderSize()) { + auto AuxiliaryHeaderOrErr = + getObject(Data, Base + CurOffset, Obj->getOptionalHeaderSize()); + if (Error E = AuxiliaryHeaderOrErr.takeError()) + return std::move(E); + Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get(); + } + CurOffset += Obj->getOptionalHeaderSize(); // Parse the section header table if it is present. diff --git a/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-exec b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-exec new file mode 100755 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@&1 | \ +# RUN: FileCheck --check-prefixes=XLC64EXEC,WARN64 %s + +# RUN: llvm-readobj --auxiliary-header %p/Inputs/xcoff-32-xlc-exec | \ +# RUN: FileCheck --check-prefix=XLC32EXEC %s + +# RUN: llvm-readobj --auxiliary-header %p/Inputs/xcoff-32-xlc-obj.o | \ +# RUN: FileCheck --check-prefix=XLC32OBJ %s + +# RUN: llvm-readobj --headers %p/Inputs/xcoff-32-xlc-obj.o | \ +# RUN: FileCheck --check-prefix=XLC32OBJ %s + +# RUN: llvm-readobj --auxiliary-header %p/Inputs/xcoff-32-xlc-obj-malform.o 2>&1 | \ +# RUN: FileCheck --check-prefixes=XLC32OBJ-PART,WARN-PART %s + +# XLC32EXEC: File: {{.*}}xcoff-32-xlc-exec +# XLC32EXEC-NEXT: Format: aixcoff-rs6000 +# XLC32EXEC-NEXT: Arch: powerpc +# XLC32EXEC-NEXT: AddressSize: 32bit +# XLC32EXEC-NEXT: AuxiliaryHeader { +# XLC32EXEC-NEXT: Magic: 0x10B +# XLC32EXEC-NEXT: Version: 0x1 +# XLC32EXEC-NEXT: Size of .text section: 0x498 +# XLC32EXEC-NEXT: Size of .data section: 0xF0 +# XLC32EXEC-NEXT: Size of .bss section: 0x4 +# XLC32EXEC-NEXT: Entry point address: 0x20000658 +# XLC32EXEC-NEXT: .text section start address: 0x10000128 +# XLC32EXEC-NEXT: .data section start address: 0x200005C0 +# XLC32EXEC-NEXT: TOC anchor address: 0x2000066C +# XLC32EXEC-NEXT: Section number of entryPoint: 2 +# XLC32EXEC-NEXT: Section number of .text: 1 +# XLC32EXEC-NEXT: Section number of .data: 2 +# XLC32EXEC-NEXT: Section number of TOC: 2 +# XLC32EXEC-NEXT: Section number of loader data: 4 +# XLC32EXEC-NEXT: Section number of .bss: 3 +# XLC32EXEC-NEXT: Maxium alignment of .text: 0x7 +# XLC32EXEC-NEXT: Maxium alignment of .data: 0x3 +# XLC32EXEC-NEXT: Module type: 0x314C +# XLC32EXEC-NEXT: CPU type of objects: 0x0 +# XLC32EXEC-NEXT: (Reserved): 0x0 +# XLC32EXEC-NEXT: Maximum stack size: 0x0 +# XLC32EXEC-NEXT: Maximum data size: 0x0 +# XLC32EXEC-NEXT: Reserved for debugger: 0x0 +# XLC32EXEC-NEXT: Text page size: 0x0 +# XLC32EXEC-NEXT: Data page size: 0x0 +# XLC32EXEC-NEXT: Stack page size: 0x0 +# XLC32EXEC-NEXT: Flag: 0x0 +# XLC32EXEC-NEXT: Alignment of thread-local storage: 0x0 +# XLC32EXEC-NEXT: Section number for .tdata: 0 +# XLC32EXEC-NEXT: Section number for .tbss: 0 +# XLC32EXEC-NEXT: } + + +# XLC64EXEC: File: {{.*}}xcoff-64-xlc-exec +# XLC64EXEC-NEXT: Format: aix5coff64-rs6000 +# XLC64EXEC-NEXT: Arch: powerpc64 +# XLC64EXEC-NEXT: AddressSize: 64bit +# XLC64EXEC-NEXT: AuxiliaryHeader { +# XLC64EXEC-NEXT: Magic: 0x10B +# XLC64EXEC-NEXT: Version: 0x1 +# XLC64EXEC-NEXT: Reserved for debugger: 0x0 +# XLC64EXEC-NEXT: .text section start address: 0x1000001F8 +# XLC64EXEC-NEXT: .data section start address: 0x110000640 +# XLC64EXEC-NEXT: TOC anchor address: 0x110000738 +# XLC64EXEC-NEXT: Section number of entryPoint: 2 +# XLC64EXEC-NEXT: Section number of .text: 1 +# XLC64EXEC-NEXT: Section number of .data: 2 +# XLC64EXEC-NEXT: Section number of TOC: 2 +# XLC64EXEC-NEXT: Section number of loader data: 4 +# XLC64EXEC-NEXT: Section number of .bss: 3 +# XLC64EXEC-NEXT: Maxium alignment of .text: 0x7 +# XLC64EXEC-NEXT: Maxium alignment of .data: 0x3 +# XLC64EXEC-NEXT: Module type: 0x314C +# XLC64EXEC-NEXT: CPU type of objects: 0x0 +# XLC64EXEC-NEXT: (Reserved): 0x0 +# XLC64EXEC-NEXT: Text page size: 0x0 +# XLC64EXEC-NEXT: Data page size: 0x0 +# XLC64EXEC-NEXT: Stack page size: 0x0 +# XLC64EXEC-NEXT: Flag: 0x0 +# XLC64EXEC-NEXT: Alignment of thread-local storage: 0x0 +# XLC64EXEC-NEXT: Size of .text section: 0x448 +# XLC64EXEC-NEXT: Size of .data section: 0x180 +# XLC64EXEC-NEXT: Size of .bss section: 0x8 +# XLC64EXEC-NEXT: Entry point address: 0x110000710 +# XLC64EXEC-NEXT: Maximum stack size: 0x0 +# XLC64EXEC-NEXT: Maximum data size: 0x0 +# XLC64EXEC-NEXT: Section number for .tdata: 0 +# XLC64EXEC-NEXT: Section number for .tbss: 0 +# XLC64EXEC-NEXT: Additional flags 64-bit XCOFF: 0x0 +# WARN64: {{.*}}llvm-readobj: warning: '': There are extra data beyond auxiliary header +# XLC64EXEC-NEXT: Extra raw data: (00 00 00 00 00 00 00 00 00 00) +# XLC64EXEC-NEXT: } + +# XLC32OBJ: File: {{.*}}xcoff-32-xlc-obj.o +# XLC32OBJ-NEXT: Format: aixcoff-rs6000 +# XLC32OBJ-NEXT: Arch: powerpc +# XLC32OBJ-NEXT: AddressSize: 32bit +# XLC32OBJ: AuxiliaryHeader { +# XLC32OBJ-NEXT: Magic: 0x10B +# XLC32OBJ-NEXT: Version: 0x0 +# XLC32OBJ-NEXT: Size of .text section: 0x200 +# XLC32OBJ-NEXT: Size of .data section: 0x3C +# XLC32OBJ-NEXT: Size of .bss section: 0x0 +# XLC32OBJ-NEXT: Entry point address: 0x0 +# XLC32OBJ-NEXT: .text section start address: 0x0 +# XLC32OBJ-NEXT: .data section start address: 0x200 +# XLC32OBJ-NEXT: } + +# XLC32OBJ-PART: File: {{.*}}xcoff-32-xlc-obj-malform.o +# XLC32OBJ-PART-NEXT: Format: aixcoff-rs6000 +# XLC32OBJ-PART-NEXT: Arch: powerpc +# XLC32OBJ-PART-NEXT: AddressSize: 32bit +# XLC32OBJ-PART-NEXT: AuxiliaryHeader { +# XLC32OBJ-PART-NEXT: Magic: 0x10B +# XLC32OBJ-PART-NEXT: Version: 0x0 +# XLC32OBJ-PART-NEXT: Size of .text section: 0x200 +# XLC32OBJ-PART-NEXT: Size of .data section: 0x3C +# XLC32OBJ-PART-NEXT: Size of .bss section: 0x0 +# XLC32OBJ-PART-NEXT: Entry point address: 0x0 +# XLC32OBJ-PART-NEXT: .text section start address: 0x0 +# WARN-PART: {{.*}}llvm-readobj: warning: '': Only partial field for .data section start address at offset (24). +# XLC32OBJ-PART-NEXT: Raw data: (00 00 02) +# XLC32OBJ-PART-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 @@ -97,6 +97,9 @@ llvm::codeview::GlobalTypeTableBuilder &GlobalCVTypes, bool GHash) {} + // Only implement for XCOFF + virtual void printAuxiliaryHeader() {} + // Only implemented for MachO. virtual void printMachODataInCode() { } virtual void printMachOVersionMin() { } 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 @@ -83,6 +83,10 @@ def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group; def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group; +// XCOFF specific options. +def grp_xcoff : OptionGroup<"kind">, HelpText<"OPTIONS (XCOFF specific)">; +def auxiliary_header : FF<"auxiliary-header" , "display the auxiliary 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 @@ -16,6 +16,8 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ScopedPrinter.h" +#include + using namespace llvm; using namespace object; @@ -28,6 +30,7 @@ : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {} void printFileHeaders() override; + void printAuxiliaryHeader() override; void printSectionHeaders() override; void printRelocations() override; void printSymbols() override; @@ -47,6 +50,8 @@ void printSymbol(const SymbolRef &); template void printRelocations(ArrayRef Sections); + void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader); + void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader); const XCOFFObjectFile &Obj; }; } // anonymous namespace @@ -98,6 +103,13 @@ // XCOFFObjectFile has the necessary support. } +void XCOFFDumper::printAuxiliaryHeader() { + if (Obj.is64Bit()) + printAuxiliaryHeader(Obj.auxiliaryHeader64()); + else + printAuxiliaryHeader(Obj.auxiliaryHeader32()); +} + void XCOFFDumper::printSectionHeaders() { if (Obj.is64Bit()) printSectionHeaders(Obj.sections64()); @@ -578,6 +590,176 @@ W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers); } +void XCOFFDumper::printAuxiliaryHeader( + const XCOFFAuxiliaryHeader32 *AuxHeader) { + if (AuxHeader == nullptr) + return; + uint16_t AuxSize = Obj.getOptionalHeaderSize(); + uint16_t PartialFieldOffset = AuxSize; + const char *PartialFieldName = nullptr; + + DictScope DS(W, "AuxiliaryHeader"); + +#define PrintAuxMember32(H, S, T) \ + if (offsetof(XCOFFAuxiliaryHeader32, T) + \ + sizeof(XCOFFAuxiliaryHeader32::T) <= \ + AuxSize) \ + W.print##H(S, AuxHeader->T); \ + else if (offsetof(XCOFFAuxiliaryHeader32, T) < AuxSize) { \ + PartialFieldOffset = offsetof(XCOFFAuxiliaryHeader32, T); \ + PartialFieldName = S; \ + } + + PrintAuxMember32(Hex, "Magic", AuxMagic); + PrintAuxMember32(Hex, "Version", Version); + PrintAuxMember32(Hex, "Size of .text section", TextSize); + PrintAuxMember32(Hex, "Size of .data section", InitDataSize); + PrintAuxMember32(Hex, "Size of .bss section", BssDataSize); + PrintAuxMember32(Hex, "Entry point address", EntryPointAddr); + PrintAuxMember32(Hex, ".text section start address", TextStartAddr); + PrintAuxMember32(Hex, ".data section start address", DataStartAddr); + PrintAuxMember32(Hex, "TOC anchor address", TOCAnchorAddr); + PrintAuxMember32(Number, "Section number of entryPoint", SecNumOfEntryPoint); + PrintAuxMember32(Number, "Section number of .text", SecNumOfText); + PrintAuxMember32(Number, "Section number of .data", SecNumOfData); + PrintAuxMember32(Number, "Section number of TOC", SecNumOfTOC); + PrintAuxMember32(Number, "Section number of loader data", SecNumOfLoader); + PrintAuxMember32(Number, "Section number of .bss", SecNumOfBSS); + PrintAuxMember32(Hex, "Maxium alignment of .text", MaxAlignOfText); + PrintAuxMember32(Hex, "Maxium alignment of .data", MaxAlignOfData); + PrintAuxMember32(Hex, "Module type", ModuleType); + PrintAuxMember32(Hex, "CPU type of objects", CpuFlag); + PrintAuxMember32(Hex, "(Reserved)", CpuType); + PrintAuxMember32(Hex, "Maximum stack size", MaxStackSize); + PrintAuxMember32(Hex, "Maximum data size", MaxDataSize); + PrintAuxMember32(Hex, "Reserved for debugger", ReservedForDebugger); + PrintAuxMember32(Hex, "Text page size", TextPageSize); + PrintAuxMember32(Hex, "Data page size", DataPageSize); + PrintAuxMember32(Hex, "Stack page size", StackPageSize); + if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) + + sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <= + AuxSize) { + W.printHex("Flag", AuxHeader->getFlag()); + W.printHex("Alignment of thread-local storage", + AuxHeader->getTDataAlignment()); + } + + PrintAuxMember32(Number, "Section number for .tdata", SecNumOfTData); + PrintAuxMember32(Number, "Section number for .tbss", SecNumOfTBSS); + + // Deal with error. + if (PartialFieldOffset < AuxSize) { + std::string ErrInfo; + llvm::raw_string_ostream StringOS(ErrInfo); + StringOS << "Only partial field for " << PartialFieldName << " at offset (" + << PartialFieldOffset << ")."; + StringOS.flush(); + reportWarning( + make_error(ErrInfo, object_error::parse_failed), + "-"); + W.printBinary( + "Raw data", "", + ArrayRef((const uint8_t *)(AuxHeader) + PartialFieldOffset, + AuxSize - PartialFieldOffset)); + } else if (sizeof(XCOFFAuxiliaryHeader32) < AuxSize) { + reportWarning(make_error( + "There are extra data beyond auxiliary header", + object_error::parse_failed), + "-"); + W.printBinary("Extra raw data", "", + ArrayRef((const uint8_t *)(AuxHeader) + + sizeof(XCOFFAuxiliaryHeader32), + AuxSize - sizeof(XCOFFAuxiliaryHeader32))); + } + +#undef PrintAuxMember32 +} + +void XCOFFDumper::printAuxiliaryHeader( + const XCOFFAuxiliaryHeader64 *AuxHeader) { + if (AuxHeader == nullptr) + return; + uint16_t AuxSize = Obj.getOptionalHeaderSize(); + uint16_t PartialFieldOffset = AuxSize; + const char *PartialFieldName = nullptr; + + DictScope DS(W, "AuxiliaryHeader"); + +#define PrintAuxMember64(H, S, T) \ + if (offsetof(XCOFFAuxiliaryHeader64, T) + \ + sizeof(XCOFFAuxiliaryHeader64::T) <= \ + AuxSize) \ + W.print##H(S, AuxHeader->T); \ + else if (offsetof(XCOFFAuxiliaryHeader64, T) < AuxSize) { \ + PartialFieldOffset = offsetof(XCOFFAuxiliaryHeader64, T); \ + PartialFieldName = S; \ + } + + PrintAuxMember64(Hex, "Magic", AuxMagic); + PrintAuxMember64(Hex, "Version", Version); + PrintAuxMember64(Hex, "Reserved for debugger", ReservedForDebugger); + PrintAuxMember64(Hex, ".text section start address", TextStartAddr); + PrintAuxMember64(Hex, ".data section start address", DataStartAddr); + PrintAuxMember64(Hex, "TOC anchor address", TOCAnchorAddr); + PrintAuxMember64(Number, "Section number of entryPoint", SecNumOfEntryPoint); + PrintAuxMember64(Number, "Section number of .text", SecNumOfText); + PrintAuxMember64(Number, "Section number of .data", SecNumOfData); + PrintAuxMember64(Number, "Section number of TOC", SecNumOfTOC); + PrintAuxMember64(Number, "Section number of loader data", SecNumOfLoader); + PrintAuxMember64(Number, "Section number of .bss", SecNumOfBSS); + PrintAuxMember64(Hex, "Maxium alignment of .text", MaxAlignOfText); + PrintAuxMember64(Hex, "Maxium alignment of .data", MaxAlignOfData); + PrintAuxMember64(Hex, "Module type", ModuleType); + PrintAuxMember64(Hex, "CPU type of objects", CpuFlag); + PrintAuxMember64(Hex, "(Reserved)", CpuType); + PrintAuxMember64(Hex, "Text page size", TextPageSize); + PrintAuxMember64(Hex, "Data page size", DataPageSize); + PrintAuxMember64(Hex, "Stack page size", StackPageSize); + if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) + + sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <= + AuxSize) { + W.printHex("Flag", AuxHeader->getFlag()); + W.printHex("Alignment of thread-local storage", + AuxHeader->getTDataAlignment()); + } + PrintAuxMember64(Hex, "Size of .text section", TextSize); + PrintAuxMember64(Hex, "Size of .data section", InitDataSize); + PrintAuxMember64(Hex, "Size of .bss section", BssDataSize); + PrintAuxMember64(Hex, "Entry point address", EntryPointAddr); + PrintAuxMember64(Hex, "Maximum stack size", MaxStackSize); + PrintAuxMember64(Hex, "Maximum data size", MaxDataSize); + PrintAuxMember64(Number, "Section number for .tdata", SecNumOfTData); + PrintAuxMember64(Number, "Section number for .tbss", SecNumOfTBSS); + PrintAuxMember64(Hex, "Additional flags 64-bit XCOFF", XCOFF64Flag); + + if (PartialFieldOffset < AuxSize) { + std::string ErrInfo; + llvm::raw_string_ostream StringOS(ErrInfo); + StringOS << "Only partial field for " << PartialFieldName << " at offset (" + << PartialFieldOffset << ")."; + StringOS.flush(); + reportWarning( + make_error(ErrInfo, object_error::parse_failed), + "-"); + ; + W.printBinary( + "Raw data", "", + ArrayRef((const uint8_t *)(AuxHeader) + PartialFieldOffset, + AuxSize - PartialFieldOffset)); + } else if (sizeof(XCOFFAuxiliaryHeader64) < AuxSize) { + reportWarning(make_error( + "There are extra data beyond auxiliary header", + object_error::parse_failed), + "-"); + W.printBinary("Extra raw data", "", + ArrayRef((const uint8_t *)(AuxHeader) + + sizeof(XCOFFAuxiliaryHeader64), + AuxSize - sizeof(XCOFFAuxiliaryHeader64))); + } + +#undef PrintAuxMember64 +} + template void XCOFFDumper::printSectionHeaders(ArrayRef Sections) { ListScope Group(W, "Sections"); 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 @@ -149,6 +149,9 @@ static bool COFFResources; static bool COFFTLSDirectory; +// XCOFF specific options. +static bool XCOFFAuxiliaryHeader; + OutputStyleTy Output = OutputStyleTy::LLVM; static std::vector InputFilenames; } // namespace opts @@ -268,6 +271,9 @@ opts::COFFResources = Args.hasArg(OPT_coff_resources); opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory); + // XCOFF specific options. + opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header); + opts::InputFilenames = Args.getAllArgValues(OPT_INPUT); } @@ -343,6 +349,9 @@ if (opts::FileHeaders) Dumper->printFileHeaders(); + if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader) + Dumper->printAuxiliaryHeader(); + // This is only used for ELF currently. In some cases, when an object is // corrupt (e.g. truncated), we can't dump anything except the file header. if (!ContentErrString.empty()) @@ -577,6 +586,7 @@ if (opts::All) { opts::FileHeaders = true; + opts::XCOFFAuxiliaryHeader = true; opts::ProgramHeaders = true; opts::SectionHeaders = true; opts::Symbols = true; @@ -595,6 +605,7 @@ if (opts::Headers) { opts::FileHeaders = true; + opts::XCOFFAuxiliaryHeader = true; opts::ProgramHeaders = true; opts::SectionHeaders = true; }