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