forked from OSchip/llvm-project
[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
This commit is contained in:
parent
025988ded6
commit
158083f0de
|
@ -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
|
||||
-----------
|
||||
|
||||
|
|
|
@ -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 @@ public:
|
|||
// 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;
|
||||
|
|
|
@ -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.
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
if not 'PowerPC' in config.root.targets:
|
||||
config.unsupported = True
|
|
@ -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: }
|
||||
|
|
@ -97,6 +97,9 @@ public:
|
|||
llvm::codeview::GlobalTypeTableBuilder &GlobalCVTypes,
|
||||
bool GHash) {}
|
||||
|
||||
// Only implement for XCOFF
|
||||
virtual void printAuxiliaryHeader() {}
|
||||
|
||||
// Only implemented for MachO.
|
||||
virtual void printMachODataInCode() { }
|
||||
virtual void printMachOVersionMin() { }
|
||||
|
|
|
@ -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">;
|
||||
|
||||
|
|
|
@ -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 @@ public:
|
|||
: 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 @@ private:
|
|||
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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue