123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218 |
- //===-- 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 "ObjDumper.h"
- #include "llvm-readobj.h"
- #include "llvm/Object/XCOFFObjectFile.h"
- #include "llvm/Support/FormattedStream.h"
- #include "llvm/Support/ScopedPrinter.h"
- #include <ctime>
- using namespace llvm;
- using namespace object;
- namespace {
- class XCOFFDumper : public ObjDumper {
- public:
- XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
- : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}
- void printFileHeaders() override;
- void printAuxiliaryHeader() override;
- void printSectionHeaders() override;
- void printRelocations() override;
- void printSymbols() override;
- void printDynamicSymbols() override;
- void printUnwindInfo() override;
- void printStackMap() const override;
- void printNeededLibraries() override;
- void printStringTable() override;
- void printExceptionSection() override;
- void printLoaderSection(bool PrintHeader, bool PrintSymbols,
- bool PrintRelocations) override;
- ScopedPrinter &getScopedPrinter() const { return W; }
- private:
- template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
- template <typename T> void printGenericSectionHeader(T &Sec) const;
- template <typename T> void printOverflowSectionHeader(T &Sec) const;
- template <typename T>
- void printExceptionSectionEntry(const T &ExceptionSectEnt) const;
- template <typename T> void printExceptionSectionEntries() const;
- template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);
- void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
- void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
- void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
- void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr);
- void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr);
- void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr);
- void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr);
- void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr);
- template <typename T> void printSectAuxEntForDWARF(const T *AuxEntPtr);
- void printSymbol(const SymbolRef &);
- template <typename RelTy> void printRelocation(RelTy Reloc);
- template <typename Shdr, typename RelTy>
- void printRelocations(ArrayRef<Shdr> Sections);
- void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
- void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
- void printLoaderSectionHeader(uintptr_t LoaderSectAddr);
- void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);
- template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
- void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);
- template <typename LoadSectionRelocTy>
- void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,
- StringRef SymbolName);
- void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);
- template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
- typename LoaderSectionRelocationEntry>
- void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);
- const XCOFFObjectFile &Obj;
- const static int32_t FirstSymIdxOfLoaderSec = 3;
- };
- } // 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::printAuxiliaryHeader() {
- DictScope DS(W, "AuxiliaryHeader");
- if (Obj.is64Bit())
- printAuxiliaryHeader(Obj.auxiliaryHeader64());
- else
- printAuxiliaryHeader(Obj.auxiliaryHeader32());
- }
- void XCOFFDumper::printSectionHeaders() {
- if (Obj.is64Bit())
- printSectionHeaders(Obj.sections64());
- else
- printSectionHeaders(Obj.sections32());
- }
- void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,
- bool PrintRelocations) {
- DictScope DS(W, "Loader Section");
- Expected<uintptr_t> LoaderSectionAddrOrError =
- Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
- if (!LoaderSectionAddrOrError) {
- reportUniqueWarning(LoaderSectionAddrOrError.takeError());
- return;
- }
- uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
- if (LoaderSectionAddr == 0)
- return;
- W.indent();
- if (PrintHeader)
- printLoaderSectionHeader(LoaderSectionAddr);
- if (PrintSymbols)
- printLoaderSectionSymbols(LoaderSectionAddr);
- if (PrintRelocations)
- printLoaderSectionRelocationEntries(LoaderSectionAddr);
- W.unindent();
- }
- void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) {
- DictScope DS(W, "Loader Section Header");
- auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {
- W.printNumber("Version", LDHeader->Version);
- W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt);
- W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt);
- W.printNumber("LengthOfImportFileIDStringTable",
- LDHeader->LengthOfImpidStrTbl);
- W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid);
- W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid);
- W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl);
- W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl);
- };
- if (Obj.is64Bit()) {
- const LoaderSectionHeader64 *LoaderSec64 =
- reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);
- PrintLoadSecHeaderCommon(LoaderSec64);
- W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);
- W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);
- } else {
- const LoaderSectionHeader32 *LoaderSec32 =
- reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);
- PrintLoadSecHeaderCommon(LoaderSec32);
- }
- }
- const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
- ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
- ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
- ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
- ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
- ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
- ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
- ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
- ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
- ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
- ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
- ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
- ECase(C_STTLS), ECase(C_EFCN)
- #undef ECase
- };
- template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
- void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) {
- const LoaderSectionHeader *LoadSecHeader =
- reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
- const LoaderSectionSymbolEntry *LoadSecSymEntPtr =
- reinterpret_cast<LoaderSectionSymbolEntry *>(
- LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()));
- for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt;
- ++i, ++LoadSecSymEntPtr) {
- if (Error E = Binary::checkOffset(
- Obj.getMemoryBufferRef(),
- LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()) +
- (i * sizeof(LoaderSectionSymbolEntry)),
- sizeof(LoaderSectionSymbolEntry))) {
- reportUniqueWarning(std::move(E));
- return;
- }
- Expected<StringRef> SymbolNameOrErr =
- LoadSecSymEntPtr->getSymbolName(LoadSecHeader);
- if (!SymbolNameOrErr) {
- reportUniqueWarning(SymbolNameOrErr.takeError());
- return;
- }
- DictScope DS(W, "Symbol");
- W.printString("Name", SymbolNameOrErr.get());
- W.printHex("Virtual Address", LoadSecSymEntPtr->Value);
- W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber);
- W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType);
- W.printEnum("StorageClass",
- static_cast<uint8_t>(LoadSecSymEntPtr->StorageClass),
- ArrayRef(SymStorageClass));
- W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID);
- W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck);
- }
- }
- void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {
- DictScope DS(W, "Loader Section Symbols");
- if (Obj.is64Bit())
- printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64,
- LoaderSectionHeader64>(LoaderSectionAddr);
- else
- printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32,
- LoaderSectionHeader32>(LoaderSectionAddr);
- }
- const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
- ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
- ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
- ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
- ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
- ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
- #undef ECase
- };
- // From the XCOFF specification: there are five implicit external symbols, one
- // each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols
- // are referenced from the relocation table entries using symbol table index
- // values 0, 1, 2, -1, and -2, respectively.
- static const char *getImplicitLoaderSectionSymName(int SymIndx) {
- switch (SymIndx) {
- default:
- return "Unkown Symbol Name";
- case -2:
- return ".tbss";
- case -1:
- return ".tdata";
- case 0:
- return ".text";
- case 1:
- return ".data";
- case 2:
- return ".bss";
- }
- }
- template <typename LoadSectionRelocTy>
- void XCOFFDumper::printLoaderSectionRelocationEntry(
- LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {
- uint16_t Type = LoaderSecRelEntPtr->Type;
- if (opts::ExpandRelocs) {
- DictScope DS(W, "Relocation");
- auto IsRelocationSigned = [](uint8_t Info) {
- return Info & XCOFF::XR_SIGN_INDICATOR_MASK;
- };
- auto IsFixupIndicated = [](uint8_t Info) {
- return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;
- };
- auto GetRelocatedLength = [](uint8_t Info) {
- // The relocation encodes the bit length being relocated minus 1. Add
- // back
- // the 1 to get the actual length being relocated.
- return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;
- };
- uint8_t Info = Type >> 8;
- W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);
- W.printNumber("Symbol", SymbolName, LoaderSecRelEntPtr->SymbolIndex);
- W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");
- W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);
- W.printNumber("Length", GetRelocatedLength(Info));
- W.printEnum("Type", static_cast<uint8_t>(Type),
- ArrayRef(RelocationTypeNameclass));
- W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);
- } else {
- W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,
- Obj.is64Bit() ? 18 : 10)
- << " " << format_hex(Type, 6) << " ("
- << XCOFF::getRelocationTypeString(
- static_cast<XCOFF::RelocationType>(Type))
- << ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)
- << " " << SymbolName << " ("
- << LoaderSecRelEntPtr->SymbolIndex << ")\n";
- }
- }
- template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
- typename LoaderSectionRelocationEntry>
- void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(
- uintptr_t LoaderSectionAddr) {
- const LoaderSectionHeader *LoaderSec =
- reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
- const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =
- reinterpret_cast<const LoaderSectionRelocationEntry *>(
- LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));
- if (!opts::ExpandRelocs)
- W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)
- << center_justify("Type", 15) << right_justify("SecNum", 8)
- << center_justify("SymbolName (Index) ", 24) << "\n";
- for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;
- ++i, ++LoaderSecRelEntPtr) {
- StringRef SymbolName;
- if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {
- // Because there are implicit symbol index values (-2, -1, 0, 1, 2),
- // LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the
- // real symbol from the symbol table.
- const uint64_t SymOffset =
- (LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *
- sizeof(LoaderSectionSymbolEntry);
- const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =
- reinterpret_cast<LoaderSectionSymbolEntry *>(
- LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +
- SymOffset);
- Expected<StringRef> SymbolNameOrErr =
- LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);
- if (!SymbolNameOrErr) {
- reportUniqueWarning(SymbolNameOrErr.takeError());
- return;
- }
- SymbolName = SymbolNameOrErr.get();
- } else
- SymbolName =
- getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);
- printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);
- }
- }
- void XCOFFDumper::printLoaderSectionRelocationEntries(
- uintptr_t LoaderSectionAddr) {
- DictScope DS(W, "Loader Section Relocations");
- if (Obj.is64Bit())
- printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,
- LoaderSectionSymbolEntry64,
- LoaderSectionRelocationEntry64>(
- LoaderSectionAddr);
- else
- printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,
- LoaderSectionSymbolEntry32,
- LoaderSectionRelocationEntry32>(
- LoaderSectionAddr);
- }
- template <typename T>
- void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {
- if (ExceptionSectEnt.getReason())
- W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());
- else {
- uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();
- Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);
- if (Error E = ErrOrSymbolName.takeError()) {
- reportUniqueWarning(std::move(E));
- return;
- }
- StringRef SymName = *ErrOrSymbolName;
- W.printNumber("Symbol", SymName, SymIdx);
- }
- W.printNumber("LangID", ExceptionSectEnt.getLangID());
- W.printNumber("Reason", ExceptionSectEnt.getReason());
- }
- template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {
- Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();
- if (Error E = ExceptSectEntsOrErr.takeError()) {
- reportUniqueWarning(std::move(E));
- return;
- }
- ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;
- DictScope DS(W, "Exception section");
- if (ExceptSectEnts.empty())
- return;
- for (auto &Ent : ExceptSectEnts)
- printExceptionSectionEntry(Ent);
- }
- void XCOFFDumper::printExceptionSection() {
- if (Obj.is64Bit())
- printExceptionSectionEntries<ExceptionSectionEntry64>();
- else
- printExceptionSectionEntries<ExceptionSectionEntry32>();
- }
- void XCOFFDumper::printRelocations() {
- if (Obj.is64Bit())
- printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
- else
- printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
- }
- template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {
- Expected<StringRef> ErrOrSymbolName =
- Obj.getSymbolNameByIndex(Reloc.SymbolIndex);
- if (Error E = ErrOrSymbolName.takeError()) {
- reportUniqueWarning(std::move(E));
- return;
- }
- StringRef SymbolName = *ErrOrSymbolName;
- StringRef RelocName = XCOFF::getRelocationTypeString(Reloc.Type);
- if (opts::ExpandRelocs) {
- DictScope Group(W, "Relocation");
- W.printHex("Virtual Address", Reloc.VirtualAddress);
- W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
- W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
- W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
- W.printNumber("Length", Reloc.getRelocatedLength());
- W.printEnum("Type", (uint8_t)Reloc.Type, ArrayRef(RelocationTypeNameclass));
- } else {
- raw_ostream &OS = W.startLine();
- OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " " << SymbolName
- << "(" << Reloc.SymbolIndex << ") " << W.hex(Reloc.Info) << "\n";
- }
- }
- template <typename Shdr, typename RelTy>
- void XCOFFDumper::printRelocations(ArrayRef<Shdr> Sections) {
- ListScope LS(W, "Relocations");
- uint16_t Index = 0;
- for (const Shdr &Sec : Sections) {
- ++Index;
- // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
- if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
- Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
- continue;
- Expected<ArrayRef<RelTy>> ErrOrRelocations = Obj.relocations<Shdr, RelTy>(Sec);
- if (Error E = ErrOrRelocations.takeError()) {
- reportUniqueWarning(std::move(E));
- continue;
- }
- const ArrayRef<RelTy> Relocations = *ErrOrRelocations;
- if (Relocations.empty())
- continue;
- W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
- << " {\n";
- W.indent();
- for (const RelTy Reloc : Relocations)
- printRelocation(Reloc);
- W.unindent();
- W.startLine() << "}\n";
- }
- }
- const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
- #undef ECase
- };
- const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),
- ECase(AUX_CSECT), ECase(AUX_SECT)
- #undef ECase
- };
- void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
- assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&
- "Mismatched auxiliary type!");
- StringRef FileName =
- unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
- DictScope SymDs(W, "File Auxiliary Entry");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printString("Name", FileName);
- W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
- ArrayRef(FileStringType));
- if (Obj.is64Bit()) {
- W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
- ArrayRef(SymAuxType));
- }
- }
- static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
- {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), ECase(XMC_GL),
- ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),
- ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
- ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), ECase(XMC_UA),
- ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL), ECase(XMC_UL),
- ECase(XMC_TE)
- #undef ECase
- };
- const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
- #undef ECase
- };
- void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {
- assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&
- "Mismatched auxiliary type!");
- DictScope SymDs(W, "CSECT Auxiliary Entry");
- W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));
- W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"
- : "SectionLen",
- AuxEntRef.getSectionOrLength());
- W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());
- W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());
- // Print out symbol alignment and type.
- W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
- W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
- ArrayRef(CsectSymbolTypeClass));
- W.printEnum("StorageMappingClass",
- static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
- ArrayRef(CsectStorageMappingClass));
- if (Obj.is64Bit()) {
- W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
- ArrayRef(SymAuxType));
- } else {
- W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
- W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
- }
- }
- void XCOFFDumper::printSectAuxEntForStat(
- const XCOFFSectAuxEntForStat *AuxEntPtr) {
- assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
- DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printNumber("SectionLength", AuxEntPtr->SectionLength);
- // Unlike the corresponding fields in the section header, NumberOfRelocEnt
- // and NumberOfLineNum do not handle values greater than 65535.
- W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
- W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
- }
- void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) {
- assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
- DictScope SymDs(W, "Exception Auxiliary Entry");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
- W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
- W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
- W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
- ArrayRef(SymAuxType));
- }
- void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {
- assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
- DictScope SymDs(W, "Function Auxiliary Entry");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
- W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
- W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
- W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
- }
- void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) {
- assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
- DictScope SymDs(W, "Function Auxiliary Entry");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
- W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
- W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
- W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
- ArrayRef(SymAuxType));
- }
- void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {
- assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
- DictScope SymDs(W, "Block Auxiliary Entry");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi);
- W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo);
- }
- void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) {
- assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
- DictScope SymDs(W, "Block Auxiliary Entry");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printHex("LineNumber", AuxEntPtr->LineNum);
- W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
- ArrayRef(SymAuxType));
- }
- template <typename T>
- void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) {
- DictScope SymDs(W, "Sect Auxiliary Entry For DWARF");
- W.printNumber("Index",
- Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
- W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion);
- W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);
- if (Obj.is64Bit())
- W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),
- ArrayRef(SymAuxType));
- }
- static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
- switch (SC) {
- case XCOFF::C_EXT:
- case XCOFF::C_WEAKEXT:
- case XCOFF::C_HIDEXT:
- case XCOFF::C_STAT:
- case XCOFF::C_FCN:
- case XCOFF::C_BLOCK:
- return "Value (RelocatableAddress)";
- case XCOFF::C_FILE:
- return "Value (SymbolTableIndex)";
- case XCOFF::C_DWARF:
- return "Value (OffsetInDWARF)";
- case XCOFF::C_FUN:
- case XCOFF::C_STSYM:
- case XCOFF::C_BINCL:
- case XCOFF::C_EINCL:
- case XCOFF::C_INFO:
- case XCOFF::C_BSTAT:
- case XCOFF::C_LSYM:
- case XCOFF::C_PSYM:
- case XCOFF::C_RPSYM:
- case XCOFF::C_RSYM:
- case XCOFF::C_ECOML:
- assert(false && "This StorageClass for the symbol is not yet implemented.");
- return "";
- default:
- return "Value";
- }
- }
- const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(TB_C), ECase(TB_CPLUSPLUS)
- #undef ECase
- };
- const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
- #define ECase(X) \
- { #X, XCOFF::X }
- ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
- #undef ECase
- };
- template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) {
- const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress);
- Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr));
- return AuxEntPtr;
- }
- static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) {
- W.startLine() << "!Unexpected raw auxiliary entry data:\n";
- W.startLine() << format_bytes(
- ArrayRef<uint8_t>(
- reinterpret_cast<const uint8_t *>(AuxAddress),
- XCOFF::SymbolTableEntrySize),
- std::nullopt, XCOFF::SymbolTableEntrySize)
- << "\n";
- }
- void XCOFFDumper::printSymbol(const SymbolRef &S) {
- DataRefImpl SymbolDRI = S.getRawDataRefImpl();
- XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
- uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
- DictScope SymDs(W, "Symbol");
- StringRef SymbolName =
- unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());
- uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
- XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass();
- W.printNumber("Index", SymbolIdx);
- W.printString("Name", SymbolName);
- W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue());
- StringRef SectionName =
- unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));
- W.printString("Section", SectionName);
- if (SymbolClass == XCOFF::C_FILE) {
- W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
- ArrayRef(CFileLangIdClass));
- W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
- ArrayRef(CFileCpuIdClass));
- } else
- W.printHex("Type", SymbolEntRef.getSymbolType());
- W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),
- ArrayRef(SymStorageClass));
- W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
- if (NumberOfAuxEntries == 0)
- return;
- auto checkNumOfAux = [=] {
- if (NumberOfAuxEntries > 1)
- reportUniqueWarning("the " +
- enumToString(static_cast<uint8_t>(SymbolClass),
- ArrayRef(SymStorageClass)) +
- " symbol at index " + Twine(SymbolIdx) +
- " should not have more than 1 "
- "auxiliary entry");
- };
- switch (SymbolClass) {
- case XCOFF::C_FILE:
- // If the symbol is C_FILE and has auxiliary entries...
- for (int I = 1; I <= NumberOfAuxEntries; I++) {
- uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
- SymbolEntRef.getEntryAddress(), I);
- if (Obj.is64Bit() &&
- *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {
- printUnexpectedRawAuxEnt(W, AuxAddress);
- continue;
- }
- const XCOFFFileAuxEnt *FileAuxEntPtr =
- getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);
- printFileAuxEnt(FileAuxEntPtr);
- }
- break;
- case XCOFF::C_EXT:
- case XCOFF::C_WEAKEXT:
- case XCOFF::C_HIDEXT: {
- // For 32-bit objects, print the function auxiliary symbol table entry. The
- // last one must be a CSECT auxiliary entry.
- // For 64-bit objects, both a function auxiliary entry and an exception
- // auxiliary entry may appear, print them in the loop and skip printing the
- // CSECT auxiliary entry, which will be printed outside the loop.
- for (int I = 1; I <= NumberOfAuxEntries; I++) {
- if (I == NumberOfAuxEntries && !Obj.is64Bit())
- break;
- uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
- SymbolEntRef.getEntryAddress(), I);
- if (Obj.is64Bit()) {
- XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);
- if (Type == XCOFF::SymbolAuxType::AUX_CSECT)
- continue;
- if (Type == XCOFF::SymbolAuxType::AUX_FCN) {
- const XCOFFFunctionAuxEnt64 *AuxEntPtr =
- getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);
- printFunctionAuxEnt(AuxEntPtr);
- } else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) {
- const XCOFFExceptionAuxEnt *AuxEntPtr =
- getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);
- printExceptionAuxEnt(AuxEntPtr);
- } else {
- printUnexpectedRawAuxEnt(W, AuxAddress);
- }
- } else {
- const XCOFFFunctionAuxEnt32 *AuxEntPtr =
- getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);
- printFunctionAuxEnt(AuxEntPtr);
- }
- }
- // Print the CSECT auxiliary entry.
- auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
- if (!ErrOrCsectAuxRef)
- reportUniqueWarning(ErrOrCsectAuxRef.takeError());
- else
- printCsectAuxEnt(*ErrOrCsectAuxRef);
- break;
- }
- case XCOFF::C_STAT: {
- checkNumOfAux();
- const XCOFFSectAuxEntForStat *StatAuxEntPtr =
- getAuxEntPtr<XCOFFSectAuxEntForStat>(
- XCOFFObjectFile::getAdvancedSymbolEntryAddress(
- SymbolEntRef.getEntryAddress(), 1));
- printSectAuxEntForStat(StatAuxEntPtr);
- break;
- }
- case XCOFF::C_DWARF: {
- checkNumOfAux();
- uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
- SymbolEntRef.getEntryAddress(), 1);
- if (Obj.is64Bit()) {
- const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =
- getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);
- printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr);
- } else {
- const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =
- getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);
- printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr);
- }
- break;
- }
- case XCOFF::C_BLOCK:
- case XCOFF::C_FCN: {
- checkNumOfAux();
- uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
- SymbolEntRef.getEntryAddress(), 1);
- if (Obj.is64Bit()) {
- const XCOFFBlockAuxEnt64 *AuxEntPtr =
- getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);
- printBlockAuxEnt(AuxEntPtr);
- } else {
- const XCOFFBlockAuxEnt32 *AuxEntPtr =
- getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);
- printBlockAuxEnt(AuxEntPtr);
- }
- break;
- }
- default:
- for (int i = 1; i <= NumberOfAuxEntries; i++) {
- printUnexpectedRawAuxEnt(W,
- XCOFFObjectFile::getAdvancedSymbolEntryAddress(
- SymbolEntRef.getEntryAddress(), i));
- }
- break;
- }
- }
- void XCOFFDumper::printSymbols() {
- ListScope Group(W, "Symbols");
- for (const SymbolRef &S : Obj.symbols())
- printSymbol(S);
- }
- void XCOFFDumper::printStringTable() {
- DictScope DS(W, "StringTable");
- StringRef StrTable = Obj.getStringTable();
- uint32_t StrTabSize = StrTable.size();
- W.printNumber("Length", StrTabSize);
- // Print strings from the fifth byte, since the first four bytes contain the
- // length (in bytes) of the string table (including the length field).
- if (StrTabSize > 4)
- printAsStringList(StrTable, 4);
- }
- 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() {
- ListScope D(W, "NeededLibraries");
- auto ImportFilesOrError = Obj.getImportFileTable();
- if (!ImportFilesOrError) {
- reportUniqueWarning(ImportFilesOrError.takeError());
- return;
- }
- StringRef ImportFileTable = ImportFilesOrError.get();
- const char *CurrentStr = ImportFileTable.data();
- const char *TableEnd = ImportFileTable.end();
- // Default column width for names is 13 even if no names are that long.
- size_t BaseWidth = 13;
- // Get the max width of BASE columns.
- for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) {
- size_t CurrentLen = strlen(CurrentStr);
- CurrentStr += strlen(CurrentStr) + 1;
- if (StrIndex % 3 == 1)
- BaseWidth = std::max(BaseWidth, CurrentLen);
- }
- auto &OS = static_cast<formatted_raw_ostream &>(W.startLine());
- // Each entry consists of 3 strings: the path_name, base_name and
- // archive_member_name. The first entry is a default LIBPATH value and other
- // entries have no path_name. We just dump the base_name and
- // archive_member_name here.
- OS << left_justify("BASE", BaseWidth) << " MEMBER\n";
- CurrentStr = ImportFileTable.data();
- for (size_t StrIndex = 0; CurrentStr < TableEnd;
- ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) {
- if (StrIndex >= 3 && StrIndex % 3 != 0) {
- if (StrIndex % 3 == 1)
- OS << " " << left_justify(CurrentStr, BaseWidth) << " ";
- else
- OS << CurrentStr << "\n";
- }
- }
- }
- 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::printOverflowSectionHeader(T &Sec) const {
- if (Obj.is64Bit()) {
- reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
- "contain an overflow section header.",
- object_error::parse_failed),
- Obj.getFileName());
- }
- W.printString("Name", Sec.getName());
- W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
- W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
- W.printHex("Size", Sec.SectionSize);
- W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
- W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
- W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
- W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
- W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
- }
- template <typename T>
- void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
- 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);
- W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
- W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
- }
- enum PrintStyle { Hex, Number };
- template <typename T, typename V>
- static void printAuxMemberHelper(PrintStyle Style, const char *MemberName,
- const T &Member, const V *AuxHeader,
- uint16_t AuxSize, uint16_t &PartialFieldOffset,
- const char *&PartialFieldName,
- ScopedPrinter &W) {
- ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -
- reinterpret_cast<const char *>(AuxHeader);
- if (Offset + sizeof(Member) <= AuxSize)
- Style == Hex ? W.printHex(MemberName, Member)
- : W.printNumber(MemberName, Member);
- else if (Offset < AuxSize) {
- PartialFieldOffset = Offset;
- PartialFieldName = MemberName;
- }
- }
- template <class T>
- void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,
- uint16_t PartialFieldOffset,
- uint16_t AuxSize, T &AuxHeader,
- XCOFFDumper *Dumper) {
- if (PartialFieldOffset < AuxSize) {
- Dumper->reportUniqueWarning(Twine("only partial field for ") +
- PartialFieldName + " at offset (" +
- Twine(PartialFieldOffset) + ")");
- Dumper->getScopedPrinter().printBinary(
- "Raw data", "",
- ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
- PartialFieldOffset,
- AuxSize - PartialFieldOffset));
- } else if (sizeof(AuxHeader) < AuxSize)
- Dumper->getScopedPrinter().printBinary(
- "Extra raw data", "",
- ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
- sizeof(AuxHeader),
- AuxSize - sizeof(AuxHeader)));
- }
- void XCOFFDumper::printAuxiliaryHeader(
- const XCOFFAuxiliaryHeader32 *AuxHeader) {
- if (AuxHeader == nullptr)
- return;
- uint16_t AuxSize = Obj.getOptionalHeaderSize();
- uint16_t PartialFieldOffset = AuxSize;
- const char *PartialFieldName = nullptr;
- auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
- auto &Member) {
- printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
- PartialFieldOffset, PartialFieldName, W);
- };
- PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
- PrintAuxMember(Hex, "Version", AuxHeader->Version);
- PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
- PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
- PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
- PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
- PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
- PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
- PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
- PrintAuxMember(Number, "Section number of entryPoint",
- AuxHeader->SecNumOfEntryPoint);
- PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
- PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
- PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
- PrintAuxMember(Number, "Section number of loader data",
- AuxHeader->SecNumOfLoader);
- PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
- PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
- PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
- PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
- PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
- PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
- PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
- PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
- PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
- PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
- PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
- PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
- if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +
- sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=
- AuxSize) {
- W.printHex("Flag", AuxHeader->getFlag());
- W.printHex("Alignment of thread-local storage",
- AuxHeader->getTDataAlignment());
- }
- PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
- PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
- checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
- AuxSize, *AuxHeader, this);
- }
- void XCOFFDumper::printAuxiliaryHeader(
- const XCOFFAuxiliaryHeader64 *AuxHeader) {
- if (AuxHeader == nullptr)
- return;
- uint16_t AuxSize = Obj.getOptionalHeaderSize();
- uint16_t PartialFieldOffset = AuxSize;
- const char *PartialFieldName = nullptr;
- auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
- auto &Member) {
- printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
- PartialFieldOffset, PartialFieldName, W);
- };
- PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
- PrintAuxMember(Hex, "Version", AuxHeader->Version);
- PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
- PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
- PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
- PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
- PrintAuxMember(Number, "Section number of entryPoint",
- AuxHeader->SecNumOfEntryPoint);
- PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
- PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
- PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
- PrintAuxMember(Number, "Section number of loader data",
- AuxHeader->SecNumOfLoader);
- PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
- PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
- PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
- PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
- PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
- PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
- PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
- PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
- PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
- if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +
- sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=
- AuxSize) {
- W.printHex("Flag", AuxHeader->getFlag());
- W.printHex("Alignment of thread-local storage",
- AuxHeader->getTDataAlignment());
- }
- PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
- PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
- PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
- PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
- PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
- PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
- PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
- PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
- PrintAuxMember(Hex, "Additional flags 64-bit XCOFF", AuxHeader->XCOFF64Flag);
- checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
- AuxSize, *AuxHeader, this);
- }
- 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++);
- uint16_t SectionType = Sec.getSectionType();
- switch (SectionType) {
- case XCOFF::STYP_OVRFLO:
- printOverflowSectionHeader(Sec);
- break;
- case XCOFF::STYP_LOADER:
- case XCOFF::STYP_EXCEPT:
- case XCOFF::STYP_TYPCHK:
- // TODO The interpretation of loader, exception and type check section
- // headers are different from that of generic section headers. We will
- // implement them later. We interpret them as generic section headers for
- // now.
- default:
- printGenericSectionHeader(Sec);
- break;
- }
- if (Sec.isReservedSectionType())
- W.printHex("Flags", "Reserved", SectionType);
- else
- W.printEnum("Type", SectionType, ArrayRef(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::unique_ptr<ObjDumper>
- createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
- return std::make_unique<XCOFFDumper>(XObj, Writer);
- }
- } // namespace llvm
|