[llvm] 158083f - [AIX][XCOFF] parsing xcoff object file auxiliary header
via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 26 07:40:51 PDT 2021
Author: zhijian
Date: 2021-10-26T10:40:25-04:00
New Revision: 158083f0de033dec4f4f9a68f558da6e68d30c35
URL: https://github.com/llvm/llvm-project/commit/158083f0de033dec4f4f9a68f558da6e68d30c35
DIFF: https://github.com/llvm/llvm-project/commit/158083f0de033dec4f4f9a68f558da6e68d30c35.diff
LOG: [AIX][XCOFF] parsing xcoff object file auxiliary header
Summary:
The patch supports parsing the xcoff object file auxiliary header with llvm-readobj with option "auxiliary-headers"
the format of auxiliary header as
https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/filesreference/XCOFF.html#XCOFF__fyovh386shar
Reviewers: James Henderson, Jason Liu, Hubert Tong, Esme yi, Sean Fertile.
Differential Revision: https://reviews.llvm.org/D82549
Added:
llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-exec
llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj-malform.o
llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj.o
llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-64-xlc-exec
llvm/test/tools/llvm-readobj/XCOFF/lit.local.cfg
llvm/test/tools/llvm-readobj/XCOFF/xcoff-auxiliary-header.test
Modified:
llvm/docs/CommandGuide/llvm-readobj.rst
llvm/include/llvm/Object/XCOFFObjectFile.h
llvm/lib/Object/XCOFFObjectFile.cpp
llvm/tools/llvm-readobj/ObjDumper.h
llvm/tools/llvm-readobj/Opts.td
llvm/tools/llvm-readobj/XCOFFDumper.cpp
llvm/tools/llvm-readobj/llvm-readobj.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index 2fb639fc3009..068808e42c4d 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -311,6 +311,15 @@ The following options are implemented only for the PE/COFF file format.
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
index 4b195f13e509..94136afc45ea 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -51,6 +51,101 @@ struct XCOFFFileHeader64 {
support::ubig32_t NumberOfSymTableEntries;
};
+template <typename T> struct XCOFFAuxiliaryHeader {
+ static constexpr uint8_t AuxiHeaderFlagMask = 0xF0;
+ static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F;
+
+public:
+ uint8_t getFlag() const {
+ return static_cast<const T *>(this)->FlagAndTDataAlignment &
+ AuxiHeaderFlagMask;
+ }
+ uint8_t getTDataAlignment() const {
+ return static_cast<const T *>(this)->FlagAndTDataAlignment &
+ AuxiHeaderTDataAlignmentMask;
+ }
+};
+
+struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader32> {
+ 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<XCOFFAuxiliaryHeader32> {
+ 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 <typename T> struct XCOFFSectionHeader {
// Least significant 3 bits are reserved.
static constexpr unsigned SectionFlagsReservedMask = 0x7;
@@ -296,6 +391,7 @@ class XCOFFSymbolRef;
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 @@ class XCOFFObjectFile : public ObjectFile {
// 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<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const;
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 1a3a394ce9cb..9b0a5efacba7 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -149,6 +149,16 @@ const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
return static_cast<const XCOFFFileHeader64 *>(FileHeader);
}
+const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
+ assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+ return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
+}
+
+const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
+ assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+ return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
+}
+
template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
return static_cast<const T *>(SectionHeaderTable);
}
@@ -1027,8 +1037,15 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
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<void>(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 000000000000..f06f5993efba
Binary files /dev/null and b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-exec
diff er
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj-malform.o b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj-malform.o
new file mode 100644
index 000000000000..678b83fae26c
Binary files /dev/null and b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj-malform.o
diff er
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj.o b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj.o
new file mode 100644
index 000000000000..109177cac74c
Binary files /dev/null and b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-32-xlc-obj.o
diff er
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-64-xlc-exec b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-64-xlc-exec
new file mode 100755
index 000000000000..52a48863881a
Binary files /dev/null and b/llvm/test/tools/llvm-readobj/XCOFF/Inputs/xcoff-64-xlc-exec
diff er
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/lit.local.cfg b/llvm/test/tools/llvm-readobj/XCOFF/lit.local.cfg
new file mode 100644
index 000000000000..091332439b18
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/XCOFF/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'PowerPC' in config.root.targets:
+ config.unsupported = True
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/xcoff-auxiliary-header.test b/llvm/test/tools/llvm-readobj/XCOFF/xcoff-auxiliary-header.test
new file mode 100644
index 000000000000..7bffb5d68bac
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/XCOFF/xcoff-auxiliary-header.test
@@ -0,0 +1,125 @@
+## This file tests the ability of llvm-readobj to display the auxiliary header for 64 bits XCOFF and 32 bits XCOFF object file.
+# RUN: llvm-readobj --auxiliary-header %p/Inputs/xcoff-64-xlc-exec 2>&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: '<stdin>': 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: '<stdin>': 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
index e6178f78ef9e..b395a95f3cb4 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -97,6 +97,9 @@ class ObjDumper {
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
index fac7e3b8d866..7723691e8225 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -83,6 +83,10 @@ def coff_load_config : FF<"coff-load-config", "Display load config">, Group<grp_
def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group<grp_coff>;
def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group<grp_coff>;
+// XCOFF specific options.
+def grp_xcoff : OptionGroup<"kind">, HelpText<"OPTIONS (XCOFF specific)">;
+def auxiliary_header : FF<"auxiliary-header" , "display the auxiliary header">, Group<grp_xcoff>;
+
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 9967915fd3dc..c67edd6a98bc 100644
--- 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 <stddef.h>
+
using namespace llvm;
using namespace object;
@@ -28,6 +30,7 @@ class XCOFFDumper : public ObjDumper {
: 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 @@ class XCOFFDumper : public ObjDumper {
void printSymbol(const SymbolRef &);
template <typename Shdr, typename RelTy>
void printRelocations(ArrayRef<Shdr> Sections);
+ void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
+ void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
const XCOFFObjectFile &Obj;
};
} // anonymous namespace
@@ -98,6 +103,13 @@ void XCOFFDumper::printFileHeaders() {
// 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 @@ void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
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<GenericBinaryError>(ErrInfo, object_error::parse_failed),
+ "-");
+ W.printBinary(
+ "Raw data", "",
+ ArrayRef<uint8_t>((const uint8_t *)(AuxHeader) + PartialFieldOffset,
+ AuxSize - PartialFieldOffset));
+ } else if (sizeof(XCOFFAuxiliaryHeader32) < AuxSize) {
+ reportWarning(make_error<GenericBinaryError>(
+ "There are extra data beyond auxiliary header",
+ object_error::parse_failed),
+ "-");
+ W.printBinary("Extra raw data", "",
+ ArrayRef<uint8_t>((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<GenericBinaryError>(ErrInfo, object_error::parse_failed),
+ "-");
+ ;
+ W.printBinary(
+ "Raw data", "",
+ ArrayRef<uint8_t>((const uint8_t *)(AuxHeader) + PartialFieldOffset,
+ AuxSize - PartialFieldOffset));
+ } else if (sizeof(XCOFFAuxiliaryHeader64) < AuxSize) {
+ reportWarning(make_error<GenericBinaryError>(
+ "There are extra data beyond auxiliary header",
+ object_error::parse_failed),
+ "-");
+ W.printBinary("Extra raw data", "",
+ ArrayRef<uint8_t>((const uint8_t *)(AuxHeader) +
+ sizeof(XCOFFAuxiliaryHeader64),
+ AuxSize - sizeof(XCOFFAuxiliaryHeader64)));
+ }
+
+#undef PrintAuxMember64
+}
+
template <typename T>
void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
ListScope Group(W, "Sections");
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 001dace9b86b..a598e2c28832 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -149,6 +149,9 @@ static bool COFFLoadConfig;
static bool COFFResources;
static bool COFFTLSDirectory;
+// XCOFF specific options.
+static bool XCOFFAuxiliaryHeader;
+
OutputStyleTy Output = OutputStyleTy::LLVM;
static std::vector<std::string> InputFilenames;
} // namespace opts
@@ -268,6 +271,9 @@ static void parseOptions(const opt::InputArgList &Args) {
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 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
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 @@ int main(int argc, char *argv[]) {
if (opts::All) {
opts::FileHeaders = true;
+ opts::XCOFFAuxiliaryHeader = true;
opts::ProgramHeaders = true;
opts::SectionHeaders = true;
opts::Symbols = true;
@@ -595,6 +605,7 @@ int main(int argc, char *argv[]) {
if (opts::Headers) {
opts::FileHeaders = true;
+ opts::XCOFFAuxiliaryHeader = true;
opts::ProgramHeaders = true;
opts::SectionHeaders = true;
}
More information about the llvm-commits
mailing list