xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1 //===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements an XCOFF specific dumper for llvm-readobj.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Error.h"
14 #include "ObjDumper.h"
15 #include "llvm-readobj.h"
16 #include "llvm/Object/XCOFFObjectFile.h"
17 #include "llvm/Support/ScopedPrinter.h"
18 
19 using namespace llvm;
20 using namespace object;
21 
22 namespace {
23 
24 class XCOFFDumper : public ObjDumper {
25 public:
26   XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
27       : ObjDumper(Writer), Obj(Obj) {}
28 
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;
37 
38 private:
39   template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
40 
41   const XCOFFObjectFile &Obj;
42 
43   // Least significant 3 bits are reserved.
44   static constexpr unsigned SectionFlagsReservedMask = 0x7;
45 };
46 } // anonymous namespace
47 
48 void XCOFFDumper::printFileHeaders() {
49   DictScope DS(W, "FileHeader");
50   W.printHex("Magic", Obj.getMagic());
51   W.printNumber("NumberOfSections", Obj.getNumberOfSections());
52 
53   // Negative timestamp values are reserved for future use.
54   int32_t TimeStamp = Obj.getTimeStamp();
55   if (TimeStamp > 0) {
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;
60 
61     char FormattedTime[21] = {};
62     size_t BytesWritten =
63         strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
64     if (BytesWritten)
65       W.printHex("TimeStamp", FormattedTime, TimeStamp);
66     else
67       W.printHex("Timestamp", TimeStamp);
68   } else {
69     W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
70                TimeStamp);
71   }
72 
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
75   // objects.
76   if (Obj.is64Bit()) {
77     W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
78     W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
79   } else {
80     W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
81     int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
82     if (SymTabEntries >= 0)
83       W.printNumber("SymbolTableEntries", SymTabEntries);
84     else
85       W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
86   }
87 
88   W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
89   W.printHex("Flags", Obj.getFlags());
90 
91   // TODO FIXME Add support for the auxiliary header (if any) once
92   // XCOFFObjectFile has the necessary support.
93 }
94 
95 void XCOFFDumper::printSectionHeaders() {
96   if (Obj.is64Bit())
97     printSectionHeaders(Obj.sections64());
98   else
99     printSectionHeaders(Obj.sections32());
100 }
101 
102 void XCOFFDumper::printRelocations() {
103   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
104 }
105 
106 void XCOFFDumper::printSymbols() {
107   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
108 }
109 
110 void XCOFFDumper::printDynamicSymbols() {
111   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
112 }
113 
114 void XCOFFDumper::printUnwindInfo() {
115   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
116 }
117 
118 void XCOFFDumper::printStackMap() const {
119   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
120 }
121 
122 void XCOFFDumper::printNeededLibraries() {
123   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
124 }
125 
126 static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
127 #define ECase(X)                                                               \
128   { #X, XCOFF::X }
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),
133     ECase(STYP_OVRFLO)
134 #undef ECase
135 };
136 
137 template <typename T>
138 void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
139   ListScope Group(W, "Sections");
140 
141   uint16_t Index = 1;
142   for (const T &Sec : Sections) {
143     DictScope SecDS(W, "Section");
144 
145     W.printNumber("Index", Index++);
146     W.printString("Name", Sec.getName());
147 
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);
154 
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);
159 
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);
165     else
166       W.printEnum("Type", Flags, makeArrayRef(SectionTypeFlagsNames));
167   }
168 
169   if (opts::SectionRelocations)
170     report_fatal_error("Dumping section relocations is unimplemented");
171 
172   if (opts::SectionSymbols)
173     report_fatal_error("Dumping symbols is unimplemented");
174 
175   if (opts::SectionData)
176     report_fatal_error("Dumping section data is unimplemented");
177 }
178 
179 namespace llvm {
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);
184   if (!XObj)
185     return readobj_error::unsupported_obj_file_format;
186 
187   Result.reset(new XCOFFDumper(*XObj, Writer));
188   return readobj_error::success;
189 }
190 } // namespace llvm
191