Skip to content

Commit

Permalink
[AIX][XCOFF] parsing xcoff object file auxiliary header
Browse files Browse the repository at this point in the history
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
  • Loading branch information
diggerlin committed Oct 26, 2021
1 parent 025988d commit 158083f
Show file tree
Hide file tree
Showing 13 changed files with 454 additions and 2 deletions.
9 changes: 9 additions & 0 deletions llvm/docs/CommandGuide/llvm-readobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----------

Expand Down
99 changes: 99 additions & 0 deletions llvm/include/llvm/Object/XCOFFObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 19 additions & 2 deletions llvm/lib/Object/XCOFFObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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.
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions llvm/test/tools/llvm-readobj/XCOFF/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
if not 'PowerPC' in config.root.targets:
config.unsupported = True
125 changes: 125 additions & 0 deletions llvm/test/tools/llvm-readobj/XCOFF/xcoff-auxiliary-header.test
Original file line number Diff line number Diff line change
@@ -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: }

3 changes: 3 additions & 0 deletions llvm/tools/llvm-readobj/ObjDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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() { }
Expand Down
4 changes: 4 additions & 0 deletions llvm/tools/llvm-readobj/Opts.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;

Expand Down
Loading

0 comments on commit 158083f

Please sign in to comment.