XCOFFDumper.cpp revision 353358
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
19using namespace llvm;
20using namespace object;
21
22namespace {
23
24class XCOFFDumper : public ObjDumper {
25public:
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
38private:
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
48void 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
95void XCOFFDumper::printSectionHeaders() {
96  if (Obj.is64Bit())
97    printSectionHeaders(Obj.sections64());
98  else
99    printSectionHeaders(Obj.sections32());
100}
101
102void XCOFFDumper::printRelocations() {
103  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
104}
105
106void XCOFFDumper::printSymbols() {
107  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
108}
109
110void XCOFFDumper::printDynamicSymbols() {
111  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
112}
113
114void XCOFFDumper::printUnwindInfo() {
115  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
116}
117
118void XCOFFDumper::printStackMap() const {
119  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
120}
121
122void XCOFFDumper::printNeededLibraries() {
123  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
124}
125
126static 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
137template <typename T>
138void 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
179namespace llvm {
180std::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