1 //===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements an XCOFF specific dumper for llvm-readobj.
11 //===----------------------------------------------------------------------===//
14 #include "ObjDumper.h"
15 #include "llvm-readobj.h"
16 #include "llvm/Object/XCOFFObjectFile.h"
17 #include "llvm/Support/ScopedPrinter.h"
20 using namespace object
;
24 class XCOFFDumper
: public ObjDumper
{
26 XCOFFDumper(const XCOFFObjectFile
&Obj
, ScopedPrinter
&Writer
)
27 : ObjDumper(Writer
), Obj(Obj
) {}
29 void printFileHeaders() override
;
30 void printSectionHeaders() override
;
31 void printRelocations() override
;
32 void printSymbols() override
;
33 void printDynamicSymbols() override
;
34 void printUnwindInfo() override
;
35 void printStackMap() const override
;
36 void printNeededLibraries() override
;
39 template <typename T
> void printSectionHeaders(ArrayRef
<T
> Sections
);
41 const XCOFFObjectFile
&Obj
;
43 // Least significant 3 bits are reserved.
44 static constexpr unsigned SectionFlagsReservedMask
= 0x7;
46 } // anonymous namespace
48 void XCOFFDumper::printFileHeaders() {
49 DictScope
DS(W
, "FileHeader");
50 W
.printHex("Magic", Obj
.getMagic());
51 W
.printNumber("NumberOfSections", Obj
.getNumberOfSections());
53 // Negative timestamp values are reserved for future use.
54 int32_t TimeStamp
= Obj
.getTimeStamp();
56 // This handling of the time stamp assumes that the host system's time_t is
57 // compatible with AIX time_t. If a platform is not compatible, the lit
58 // tests will let us know.
59 time_t TimeDate
= TimeStamp
;
61 char FormattedTime
[21] = {};
63 strftime(FormattedTime
, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate
));
65 W
.printHex("TimeStamp", FormattedTime
, TimeStamp
);
67 W
.printHex("Timestamp", TimeStamp
);
69 W
.printHex("TimeStamp", TimeStamp
== 0 ? "None" : "Reserved Value",
73 // The number of symbol table entries is an unsigned value in 64-bit objects
74 // and a signed value (with negative values being 'reserved') in 32-bit
77 W
.printHex("SymbolTableOffset", Obj
.getSymbolTableOffset64());
78 W
.printNumber("SymbolTableEntries", Obj
.getNumberOfSymbolTableEntries64());
80 W
.printHex("SymbolTableOffset", Obj
.getSymbolTableOffset32());
81 int32_t SymTabEntries
= Obj
.getRawNumberOfSymbolTableEntries32();
82 if (SymTabEntries
>= 0)
83 W
.printNumber("SymbolTableEntries", SymTabEntries
);
85 W
.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries
);
88 W
.printHex("OptionalHeaderSize", Obj
.getOptionalHeaderSize());
89 W
.printHex("Flags", Obj
.getFlags());
91 // TODO FIXME Add support for the auxiliary header (if any) once
92 // XCOFFObjectFile has the necessary support.
95 void XCOFFDumper::printSectionHeaders() {
97 printSectionHeaders(Obj
.sections64());
99 printSectionHeaders(Obj
.sections32());
102 void XCOFFDumper::printRelocations() {
103 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
106 void XCOFFDumper::printSymbols() {
107 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
110 void XCOFFDumper::printDynamicSymbols() {
111 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
114 void XCOFFDumper::printUnwindInfo() {
115 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
118 void XCOFFDumper::printStackMap() const {
119 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
122 void XCOFFDumper::printNeededLibraries() {
123 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
126 static const EnumEntry
<XCOFF::SectionTypeFlags
> SectionTypeFlagsNames
[] = {
129 ECase(STYP_PAD
), ECase(STYP_DWARF
), ECase(STYP_TEXT
),
130 ECase(STYP_DATA
), ECase(STYP_BSS
), ECase(STYP_EXCEPT
),
131 ECase(STYP_INFO
), ECase(STYP_TDATA
), ECase(STYP_TBSS
),
132 ECase(STYP_LOADER
), ECase(STYP_DEBUG
), ECase(STYP_TYPCHK
),
137 template <typename T
>
138 void XCOFFDumper::printSectionHeaders(ArrayRef
<T
> Sections
) {
139 ListScope
Group(W
, "Sections");
142 for (const T
&Sec
: Sections
) {
143 DictScope
SecDS(W
, "Section");
145 W
.printNumber("Index", Index
++);
146 W
.printString("Name", Sec
.getName());
148 W
.printHex("PhysicalAddress", Sec
.PhysicalAddress
);
149 W
.printHex("VirtualAddress", Sec
.VirtualAddress
);
150 W
.printHex("Size", Sec
.SectionSize
);
151 W
.printHex("RawDataOffset", Sec
.FileOffsetToRawData
);
152 W
.printHex("RelocationPointer", Sec
.FileOffsetToRelocationInfo
);
153 W
.printHex("LineNumberPointer", Sec
.FileOffsetToLineNumberInfo
);
155 // TODO Need to add overflow handling when NumberOfX == _OVERFLOW_MARKER
156 // in 32-bit object files.
157 W
.printNumber("NumberOfRelocations", Sec
.NumberOfRelocations
);
158 W
.printNumber("NumberOfLineNumbers", Sec
.NumberOfLineNumbers
);
160 // The most significant 16-bits represent the DWARF section subtype. For
161 // now we just dump the section type flags.
162 uint16_t Flags
= Sec
.Flags
& 0xffffu
;
163 if (Flags
& SectionFlagsReservedMask
)
164 W
.printHex("Flags", "Reserved", Flags
);
166 W
.printEnum("Type", Flags
, makeArrayRef(SectionTypeFlagsNames
));
169 if (opts::SectionRelocations
)
170 report_fatal_error("Dumping section relocations is unimplemented");
172 if (opts::SectionSymbols
)
173 report_fatal_error("Dumping symbols is unimplemented");
175 if (opts::SectionData
)
176 report_fatal_error("Dumping section data is unimplemented");
180 std::error_code
createXCOFFDumper(const object::ObjectFile
*Obj
,
181 ScopedPrinter
&Writer
,
182 std::unique_ptr
<ObjDumper
> &Result
) {
183 const XCOFFObjectFile
*XObj
= dyn_cast
<XCOFFObjectFile
>(Obj
);
185 return readobj_error::unsupported_obj_file_format
;
187 Result
.reset(new XCOFFDumper(*XObj
, Writer
));
188 return readobj_error::success
;