Skip to content

Commit 29b0a25

Browse files
authored
[llvm-objdump] Print out xcoff file header for xcoff object file with option private-headers (llvm#96350)
Print out the XCOFF file header and load section header for the XCOFF object file using llvm-objdump with the --private-headers option.
1 parent 7332713 commit 29b0a25

File tree

2 files changed

+132
-2
lines changed

2 files changed

+132
-2
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
## Test the --private-headers option for XCOFF object files.
2+
3+
# RUN: yaml2obj -DMAGIC=0x1DF --docnum=1 %s -o %t_xcoff32.o
4+
# RUN: yaml2obj -DMAGIC=0x1F7 --docnum=1 %s -o %t_xcoff64.o
5+
# RUN: llvm-objdump --private-headers %t_xcoff32.o | \
6+
# RUN: FileCheck %s --check-prefixes=CHECK32 --match-full-lines --strict-whitespace
7+
# RUN: llvm-objdump --private-headers %t_xcoff64.o | \
8+
# RUN: FileCheck %s --check-prefixes=CHECK64 --match-full-lines --strict-whitespace
9+
10+
--- !XCOFF
11+
FileHeader:
12+
MagicNumber: [[MAGIC]]
13+
CreationTime: 1234
14+
Sections:
15+
- Name: .text
16+
Flags: [ STYP_TEXT ]
17+
SectionData: "9061FFF880820000"
18+
- Name: .data
19+
Flags: [ STYP_DATA ]
20+
SectionData: "0000000000000FC0"
21+
22+
# CHECK32:---File Header:
23+
# CHECK32-NEXT:Magic: 0x1df
24+
# CHECK32-NEXT:NumberOfSections: 2
25+
# CHECK32-NEXT:Timestamp: 1970-01-01 00:20:34 (1234)
26+
# CHECK32-NEXT:SymbolTableOffset: 0x0
27+
# CHECK32-NEXT:SymbolTableEntries: 0
28+
# CHECK32-NEXT:OptionalHeaderSize: 0x0
29+
# CHECK32-NEXT:Flags: 0x0
30+
31+
# CHECK64:---File Header:
32+
# CHECK64-NEXT:Magic: 0x1f7
33+
# CHECK64-NEXT:NumberOfSections: 2
34+
# CHECK64-NEXT:Timestamp: 1970-01-01 00:20:34 (1234)
35+
# CHECK64-NEXT:SymbolTableOffset: 0x0
36+
# CHECK64-NEXT:SymbolTableEntries: 0
37+
# CHECK64-NEXT:OptionalHeaderSize: 0x0
38+
# CHECK64-NEXT:Flags: 0x0
39+
40+
## Test if the creation time of XCOFF is zero and the number of symbols is negative.
41+
# RUN: yaml2obj -DMAGIC=0x1DF --docnum=2 %s -o %t_xcoff_timestamp.o
42+
# RUN: llvm-objdump --private-headers %t_xcoff_timestamp.o | \
43+
# RUN: FileCheck %s --match-full-lines
44+
45+
--- !XCOFF
46+
FileHeader:
47+
MagicNumber: 0x1DF
48+
CreationTime: 0
49+
EntriesInSymbolTable: -1
50+
51+
# CHECK: Timestamp: None (0)
52+
# CHECK: SymbolTableEntries: Reserved Value (-1)

llvm/tools/llvm-objdump/XCOFFDump.cpp

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include "llvm/MC/MCSubtargetInfo.h"
2121
#include "llvm/Support/Casting.h"
2222
#include "llvm/Support/Endian.h"
23+
#include "llvm/Support/Format.h"
2324
#include "llvm/Support/FormattedStream.h"
25+
#include "llvm/Support/raw_ostream.h"
2426
#include <algorithm>
2527

2628
using namespace llvm;
@@ -30,10 +32,86 @@ using namespace llvm::support;
3032

3133
namespace {
3234
class XCOFFDumper : public objdump::Dumper {
35+
const XCOFFObjectFile &Obj;
36+
unsigned Width;
37+
3338
public:
34-
XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {}
35-
void printPrivateHeaders() override {}
39+
XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O), Obj(O) {}
40+
41+
private:
42+
void printPrivateHeaders() override;
43+
void printFileHeader();
44+
FormattedString formatName(StringRef Name);
45+
void printHex(StringRef Name, uint64_t Value);
46+
void printNumber(StringRef Name, uint64_t Value);
47+
void printStrHex(StringRef Name, StringRef Str, uint64_t Value);
48+
void setWidth(unsigned W) { Width = W; };
3649
};
50+
51+
void XCOFFDumper::printPrivateHeaders() { printFileHeader(); }
52+
53+
FormattedString XCOFFDumper::formatName(StringRef Name) {
54+
return FormattedString(Name, Width, FormattedString::JustifyLeft);
55+
}
56+
57+
void XCOFFDumper::printHex(StringRef Name, uint64_t Value) {
58+
outs() << formatName(Name) << format_hex(Value, 0) << "\n";
59+
}
60+
61+
void XCOFFDumper::printNumber(StringRef Name, uint64_t Value) {
62+
outs() << formatName(Name) << format_decimal(Value, 0) << "\n";
63+
}
64+
65+
void XCOFFDumper::printStrHex(StringRef Name, StringRef Str, uint64_t Value) {
66+
outs() << formatName(Name) << Str << " (" << format_decimal(Value, 0)
67+
<< ")\n";
68+
}
69+
70+
void XCOFFDumper::printFileHeader() {
71+
setWidth(20);
72+
outs() << "\n---File Header:\n";
73+
printHex("Magic:", Obj.getMagic());
74+
printNumber("NumberOfSections:", Obj.getNumberOfSections());
75+
76+
int32_t Timestamp = Obj.getTimeStamp();
77+
if (Timestamp > 0) {
78+
// This handling of the timestamp assumes that the host system's time_t is
79+
// compatible with AIX time_t. If a platform is not compatible, the lit
80+
// tests will let us know.
81+
time_t TimeDate = Timestamp;
82+
83+
char FormattedTime[20] = {};
84+
85+
size_t BytesFormatted = std::strftime(FormattedTime, sizeof(FormattedTime),
86+
"%F %T", std::gmtime(&TimeDate));
87+
assert(BytesFormatted && "The size of the buffer FormattedTime is less "
88+
"than the size of the date/time string.");
89+
printStrHex("Timestamp:", FormattedTime, Timestamp);
90+
} else {
91+
// Negative timestamp values are reserved for future use.
92+
printStrHex("Timestamp:", Timestamp == 0 ? "None" : "Reserved Value",
93+
Timestamp);
94+
}
95+
96+
// The number of symbol table entries is an unsigned value in 64-bit objects
97+
// and a signed value (with negative values being 'reserved') in 32-bit
98+
// objects.
99+
if (Obj.is64Bit()) {
100+
printHex("SymbolTableOffset:", Obj.getSymbolTableOffset64());
101+
printNumber("SymbolTableEntries:", Obj.getNumberOfSymbolTableEntries64());
102+
} else {
103+
printHex("SymbolTableOffset:", Obj.getSymbolTableOffset32());
104+
int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
105+
if (SymTabEntries >= 0)
106+
printNumber("SymbolTableEntries:", SymTabEntries);
107+
else
108+
printStrHex("SymbolTableEntries:", "Reserved Value", SymTabEntries);
109+
}
110+
111+
printHex("OptionalHeaderSize:", Obj.getOptionalHeaderSize());
112+
printHex("Flags:", Obj.getFlags());
113+
}
114+
37115
} // namespace
38116

39117
std::unique_ptr<objdump::Dumper>

0 commit comments

Comments
 (0)