[llvm] [llvm-objdump] Implement decoding auxiliary header for xcoff with llvm-objdump --private-headers (PR #105682)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 22 08:52:43 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-binary-utilities
Author: zhijian lin (diggerlin)
<details>
<summary>Changes</summary>
Implement decoding auxiliary header for xcoff with llvm-objdump --private-headers
---
Full diff: https://github.com/llvm/llvm-project/pull/105682.diff
2 Files Affected:
- (added) llvm/test/tools/llvm-objdump/XCOFF/private-header-auxiliary.test (+126)
- (modified) llvm/tools/llvm-objdump/XCOFFDump.cpp (+184-4)
``````````diff
diff --git a/llvm/test/tools/llvm-objdump/XCOFF/private-header-auxiliary.test b/llvm/test/tools/llvm-objdump/XCOFF/private-header-auxiliary.test
new file mode 100644
index 00000000000000..848b43b5db2d74
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/XCOFF/private-header-auxiliary.test
@@ -0,0 +1,126 @@
+## Test that `the llvm-objdump --private-headers` print out the auxiliary header of XCOFF object file.
+
+# RUN: yaml2obj %s -o %t1
+# RUN: llvm-objdump --private-headers %t1 | FileCheck %s --check-prefix=CHECK32
+# RUN: cp %t1 %t1_err1
+# RUN: python -c "with open(r'%t1_err1', 'r+b') as input: input.seek(17); input.write(b'\x45')"
+# RUN: python -c "with open(r'%t1_err1', 'r+b') as input: input.seek(4); input.write(b'\x00')"
+# RUN: llvm-objdump --private-headers %t1_err1 2>&1 | FileCheck %s --check-prefix=WARN1
+# RUN: cp %t1 %t1_extra
+# RUN: python -c "with open(r'%t1_extra', 'r+b') as input: input.seek(4); input.write(b'\x00')"
+# RUN: python -c "with open(r'%t1_extra', 'r+b') as input: input.seek(17); input.write(b'\x4f')"
+# RUN: llvm-objdump --private-headers %t1_extra 2>&1 | FileCheck %s --check-prefix=EXTRA
+# RUN: yaml2obj %s -DMAGIC=0x1F7 -DFLAG64=0x2 -o %t2
+# RUN: llvm-objdump --private-headers %t2 | FileCheck %s --check-prefix=CHECK64
+
+
+# CHECK32: ---Auxiliary Header:
+# CHECK32-NEXT: Magic: 0x10b
+# CHECK32-NEXT: Version: 0x1
+# CHECK32-NEXT: Size of .text section: 0x8
+# CHECK32-NEXT: Size of .data section: 0x9
+# CHECK32-NEXT: Size of .bss section: 0x10
+# CHECK32-NEXT: Entry point address: 0x1111
+# CHECK32-NEXT: .text section start address: 0x2222
+# CHECK32-NEXT: .data section start address; 0x3333
+# CHECK32-NEXT: TOC anchor address: 0x4444
+# CHECK32-NEXT: Section number of entryPoint: 1
+# CHECK32-NEXT: Section number of .text: 2
+# CHECK32-NEXT: Section number of .data: 3
+# CHECK32-NEXT: Section number of TOC: 4
+# CHECK32-NEXT: Section number of loader data: 5
+# CHECK32-NEXT: Section number of .bss: 6
+# CHECK32-NEXT: Maxium alignment of .text: 0x7
+# CHECK32-NEXT: Maxium alignment of .data: 0x3
+# CHECK32-NEXT: Module type; 0x0
+# CHECK32-NEXT: CPU type of objects: 0x1
+# CHECK32-NEXT: (Reserved): 0x0
+# CHECK32-NEXT: Maximum stack size: 0x0
+# CHECK32-NEXT: Maximum data size: 0x0
+# CHECK32-NEXT: Reserved for debugger: 0x0
+# CHECK32-NEXT: Text page size: 0x1
+# CHECK32-NEXT: Data page size: 0x1
+# CHECK32-NEXT: Stack page size: 0x1
+# CHECK32-NEXT: Flag: 0x0
+# CHECK32-NEXT: Alignment of thread-local storage: 0x1
+# CHECK32-NEXT: Section number for .tdata: 7
+# CHECK32-NEXT: Section number for .tbss: 8
+
+# CHECK64: ---Auxiliary Header:
+# CHECK64-NEXT: Magic: 0x10b
+# CHECK64-NEXT: Version: 0x1
+# CHECK64-NEXT: Reserved for debugger: 0x0
+# CHECK64-NEXT: .text section start address: 0x2222
+# CHECK64-NEXT: .data section start address: 0x3333
+# CHECK64-NEXT: TOC anchor address: 0x4444
+# CHECK64-NEXT: Section number of entryPoint: 1
+# CHECK64-NEXT: Section number of .text: 2
+# CHECK64-NEXT: Section number of .data: 3
+# CHECK64-NEXT: Section number of TOC: 4
+# CHECK64-NEXT: Section number of loader data: 5
+# CHECK64-NEXT: Section number of .bss: 6
+# CHECK64-NEXT: Maxium alignment of .text: 0x7
+# CHECK64-NEXT: Maxium alignment of .data: 0x3
+# CHECK64-NEXT: Module type: 0x0
+# CHECK64-NEXT: CPU type of objects: 0x1
+# CHECK64-NEXT: (Reserved): 0x0
+# CHECK64-NEXT: Text page size: 0x1
+# CHECK64-NEXT: Data page size: 0x1
+# CHECK64-NEXT: Stack page size: 0x1
+# CHECK64-NEXT: Flag: 0x0
+# CHECK64-NEXT: Alignment of thread-local storage: 0x1
+# CHECK64-NEXT: Size of .text section: 0x8
+# CHECK64-NEXT: Size of .data section: 0x9
+# CHECK64-NEXT: Size of .bss section: 0x10
+# CHECK64-NEXT: Entry point address: 0x1111
+# CHECK64-NEXT: Maximum stack size: 0x0
+# CHECK64-NEXT: Maximum data size: 0x0
+# CHECK64-NEXT: Section number for .tdata: 7
+# CHECK64-NEXT: Section number for .tbss: 8
+# CHECK64-NEXT: Additional flags 64-bit XCOFF: 0x2
+
+# WARN1: {{.*}}: only partial field for Section number for .tdata: at offset (68)
+# WARN1-NEXT: Raw data (00)
+
+# EXTRA: Extra raw data (00000000 000000)
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: [[MAGIC=0x1DF]]
+AuxiliaryHeader:
+ Magic: 0x10B
+ Version: 0x1
+ TextSectionSize: 0x8
+ DataSectionSize: 0x9
+ BssSectionSize: 0x10
+ EntryPointAddr: 0x1111
+ TextStartAddr: 0x2222
+ DataStartAddr: 0x3333
+ TOCAnchorAddr: 0x4444
+ SecNumOfEntryPoint: 1
+ SecNumOfText: 2
+ SecNumOfData: 3
+ SecNumOfTOC: 4
+ SecNumOfLoader: 5
+ SecNumOfBSS: 6
+ MaxAlignOfText: 0x7
+ MaxAlignOfData: 0x3
+ ModuleType: 0x1
+ TextPageSize: 0x1
+ DataPageSize: 0x1
+ StackPageSize: 0x1
+ SecNumOfTData: 7
+ SecNumOfTBSS: 8
+ FlagAndTDataAlignment: 0x1
+ Flag: [[FLAG64=<none>]]
+Sections:
+ - Flags: [ STYP_TEXT ]
+ SectionData: "1232"
+ - Flags: [ STYP_DATA ]
+ SectionData: "5678"
+ - Flags: [ STYP_BSS ]
+ SectionData: "9101"
+ - Flags: [ STYP_TDATA ]
+ SectionData: "1112"
+ - Flags: [ STYP_TBSS ]
+ SectionData: "1314"
diff --git a/llvm/tools/llvm-objdump/XCOFFDump.cpp b/llvm/tools/llvm-objdump/XCOFFDump.cpp
index 524bf07c372a9b..34718fedfc14b5 100644
--- a/llvm/tools/llvm-objdump/XCOFFDump.cpp
+++ b/llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -37,18 +37,26 @@ class XCOFFDumper : public objdump::Dumper {
public:
XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O), Obj(O) {}
+ void printBinary(StringRef Name, ArrayRef<uint8_t> B);
+ void printHex(StringRef Name, uint64_t Value);
+ void printNumber(StringRef Name, uint64_t Value);
private:
void printPrivateHeaders() override;
void printFileHeader();
+ void printAuxiliaryHeader();
+ void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
+ void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
FormattedString formatName(StringRef Name);
- void printHex(StringRef Name, uint64_t Value);
- void printNumber(StringRef Name, uint64_t Value);
void printStrHex(StringRef Name, StringRef Str, uint64_t Value);
void setWidth(unsigned W) { Width = W; };
+ unsigned getWidth() { return Width; }
};
-void XCOFFDumper::printPrivateHeaders() { printFileHeader(); }
+void XCOFFDumper::printPrivateHeaders() {
+ printFileHeader();
+ printAuxiliaryHeader();
+}
FormattedString XCOFFDumper::formatName(StringRef Name) {
return FormattedString(Name, Width, FormattedString::JustifyLeft);
@@ -67,6 +75,179 @@ void XCOFFDumper::printStrHex(StringRef Name, StringRef Str, uint64_t Value) {
<< ")\n";
}
+void XCOFFDumper::printBinary(StringRef Name, ArrayRef<uint8_t> B) {
+ unsigned OrgWidth = getWidth();
+ setWidth(0);
+ outs() << formatName(Name) << " (" << format_bytes(B) << ")\n";
+ setWidth(OrgWidth);
+}
+
+void XCOFFDumper::printAuxiliaryHeader() {
+ setWidth(36);
+ if (Obj.is64Bit())
+ printAuxiliaryHeader(Obj.auxiliaryHeader64());
+ else
+ printAuxiliaryHeader(Obj.auxiliaryHeader32());
+}
+
+enum PrintStyle { Hex, Number };
+template <typename T, typename V>
+static void printAuxMemberHelper(PrintStyle Style, const char *MemberName,
+ const T &Member, const V *AuxHeader,
+ uint16_t AuxSize, uint16_t &PartialFieldOffset,
+ const char *&PartialFieldName,
+ XCOFFDumper *Dumper) {
+ ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -
+ reinterpret_cast<const char *>(AuxHeader);
+ if (Offset + sizeof(Member) <= AuxSize)
+ Style == Hex ? Dumper->printHex(MemberName, Member)
+ : Dumper->printNumber(MemberName, Member);
+ else if (Offset < AuxSize) {
+ PartialFieldOffset = Offset;
+ PartialFieldName = MemberName;
+ }
+}
+
+template <class T>
+void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,
+ uint16_t PartialFieldOffset,
+ uint16_t AuxSize, T &AuxHeader,
+ XCOFFDumper *Dumper) {
+ if (PartialFieldOffset < AuxSize) {
+ Dumper->reportUniqueWarning(Twine("only partial field for ") +
+ PartialFieldName + " at offset (" +
+ Twine(PartialFieldOffset) + ")");
+ Dumper->printBinary(
+ "Raw data",
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
+ PartialFieldOffset,
+ AuxSize - PartialFieldOffset));
+ } else if (sizeof(AuxHeader) < AuxSize)
+ Dumper->printBinary(
+ "Extra raw data",
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
+ sizeof(AuxHeader),
+ AuxSize - sizeof(AuxHeader)));
+}
+
+void XCOFFDumper::printAuxiliaryHeader(
+ const XCOFFAuxiliaryHeader32 *AuxHeader) {
+ if (AuxHeader == nullptr)
+ return;
+ outs() << "\n---Auxiliary Header:\n";
+ uint16_t AuxSize = Obj.getOptionalHeaderSize();
+ uint16_t PartialFieldOffset = AuxSize;
+ const char *PartialFieldName = nullptr;
+
+ auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
+ auto &Member) {
+ printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
+ PartialFieldOffset, PartialFieldName, this);
+ };
+
+ PrintAuxMember(Hex, "Magic:", AuxHeader->AuxMagic);
+ PrintAuxMember(Hex, "Version:", AuxHeader->Version);
+ PrintAuxMember(Hex, "Size of .text section:", AuxHeader->TextSize);
+ PrintAuxMember(Hex, "Size of .data section:", AuxHeader->InitDataSize);
+ PrintAuxMember(Hex, "Size of .bss section:", AuxHeader->BssDataSize);
+ PrintAuxMember(Hex, "Entry point address:", AuxHeader->EntryPointAddr);
+ PrintAuxMember(Hex, ".text section start address:", AuxHeader->TextStartAddr);
+ PrintAuxMember(Hex, ".data section start address;", AuxHeader->DataStartAddr);
+ PrintAuxMember(Hex, "TOC anchor address:", AuxHeader->TOCAnchorAddr);
+ PrintAuxMember(
+ Number, "Section number of entryPoint:", AuxHeader->SecNumOfEntryPoint);
+ PrintAuxMember(Number, "Section number of .text:", AuxHeader->SecNumOfText);
+ PrintAuxMember(Number, "Section number of .data:", AuxHeader->SecNumOfData);
+ PrintAuxMember(Number, "Section number of TOC:", AuxHeader->SecNumOfTOC);
+ PrintAuxMember(Number,
+ "Section number of loader data:", AuxHeader->SecNumOfLoader);
+ PrintAuxMember(Number, "Section number of .bss:", AuxHeader->SecNumOfBSS);
+ PrintAuxMember(Hex, "Maxium alignment of .text:", AuxHeader->MaxAlignOfText);
+ PrintAuxMember(Hex, "Maxium alignment of .data:", AuxHeader->MaxAlignOfData);
+ PrintAuxMember(Hex, "Module type;", AuxHeader->ModuleType);
+ PrintAuxMember(Hex, "CPU type of objects:", AuxHeader->CpuFlag);
+ PrintAuxMember(Hex, "(Reserved):", AuxHeader->CpuType);
+ PrintAuxMember(Hex, "Maximum stack size:", AuxHeader->MaxStackSize);
+ PrintAuxMember(Hex, "Maximum data size:", AuxHeader->MaxDataSize);
+ PrintAuxMember(Hex, "Reserved for debugger:", AuxHeader->ReservedForDebugger);
+ PrintAuxMember(Hex, "Text page size:", AuxHeader->TextPageSize);
+ PrintAuxMember(Hex, "Data page size:", AuxHeader->DataPageSize);
+ PrintAuxMember(Hex, "Stack page size:", AuxHeader->StackPageSize);
+ if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +
+ sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=
+ AuxSize) {
+ printHex("Flag:", AuxHeader->getFlag());
+ printHex("Alignment of thread-local storage:",
+ AuxHeader->getTDataAlignment());
+ }
+
+ PrintAuxMember(Number,
+ "Section number for .tdata:", AuxHeader->SecNumOfTData);
+ PrintAuxMember(Number, "Section number for .tbss:", AuxHeader->SecNumOfTBSS);
+
+ checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
+ AuxSize, *AuxHeader, this);
+}
+
+void XCOFFDumper::printAuxiliaryHeader(
+ const XCOFFAuxiliaryHeader64 *AuxHeader) {
+ if (AuxHeader == nullptr)
+ return;
+ uint16_t AuxSize = Obj.getOptionalHeaderSize();
+ outs() << "\n---Auxiliary Header:\n";
+ uint16_t PartialFieldOffset = AuxSize;
+ const char *PartialFieldName = nullptr;
+
+ auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
+ auto &Member) {
+ printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
+ PartialFieldOffset, PartialFieldName, this);
+ };
+
+ PrintAuxMember(Hex, "Magic:", AuxHeader->AuxMagic);
+ PrintAuxMember(Hex, "Version:", AuxHeader->Version);
+ PrintAuxMember(Hex, "Reserved for debugger:", AuxHeader->ReservedForDebugger);
+ PrintAuxMember(Hex, ".text section start address:", AuxHeader->TextStartAddr);
+ PrintAuxMember(Hex, ".data section start address:", AuxHeader->DataStartAddr);
+ PrintAuxMember(Hex, "TOC anchor address:", AuxHeader->TOCAnchorAddr);
+ PrintAuxMember(
+ Number, "Section number of entryPoint:", AuxHeader->SecNumOfEntryPoint);
+ PrintAuxMember(Number, "Section number of .text:", AuxHeader->SecNumOfText);
+ PrintAuxMember(Number, "Section number of .data:", AuxHeader->SecNumOfData);
+ PrintAuxMember(Number, "Section number of TOC:", AuxHeader->SecNumOfTOC);
+ PrintAuxMember(Number,
+ "Section number of loader data:", AuxHeader->SecNumOfLoader);
+ PrintAuxMember(Number, "Section number of .bss:", AuxHeader->SecNumOfBSS);
+ PrintAuxMember(Hex, "Maxium alignment of .text:", AuxHeader->MaxAlignOfText);
+ PrintAuxMember(Hex, "Maxium alignment of .data:", AuxHeader->MaxAlignOfData);
+ PrintAuxMember(Hex, "Module type:", AuxHeader->ModuleType);
+ PrintAuxMember(Hex, "CPU type of objects:", AuxHeader->CpuFlag);
+ PrintAuxMember(Hex, "(Reserved):", AuxHeader->CpuType);
+ PrintAuxMember(Hex, "Text page size:", AuxHeader->TextPageSize);
+ PrintAuxMember(Hex, "Data page size:", AuxHeader->DataPageSize);
+ PrintAuxMember(Hex, "Stack page size:", AuxHeader->StackPageSize);
+ if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +
+ sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=
+ AuxSize) {
+ printHex("Flag:", AuxHeader->getFlag());
+ printHex("Alignment of thread-local storage:",
+ AuxHeader->getTDataAlignment());
+ }
+ PrintAuxMember(Hex, "Size of .text section:", AuxHeader->TextSize);
+ PrintAuxMember(Hex, "Size of .data section:", AuxHeader->InitDataSize);
+ PrintAuxMember(Hex, "Size of .bss section:", AuxHeader->BssDataSize);
+ PrintAuxMember(Hex, "Entry point address:", AuxHeader->EntryPointAddr);
+ PrintAuxMember(Hex, "Maximum stack size:", AuxHeader->MaxStackSize);
+ PrintAuxMember(Hex, "Maximum data size:", AuxHeader->MaxDataSize);
+ PrintAuxMember(Number,
+ "Section number for .tdata:", AuxHeader->SecNumOfTData);
+ PrintAuxMember(Number, "Section number for .tbss:", AuxHeader->SecNumOfTBSS);
+ PrintAuxMember(Hex, "Additional flags 64-bit XCOFF:", AuxHeader->XCOFF64Flag);
+
+ checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
+ AuxSize, *AuxHeader, this);
+}
+
void XCOFFDumper::printFileHeader() {
setWidth(20);
outs() << "\n---File Header:\n";
@@ -112,7 +293,6 @@ void XCOFFDumper::printFileHeader() {
printHex("OptionalHeaderSize:", Obj.getOptionalHeaderSize());
printHex("Flags:", Obj.getFlags());
}
-
} // namespace
std::unique_ptr<objdump::Dumper>
``````````
</details>
https://github.com/llvm/llvm-project/pull/105682
More information about the llvm-commits
mailing list