[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