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