xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements an XCOFF specific dumper for llvm-readobj.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "ObjDumper.h"
140b57cec5SDimitry Andric #include "llvm-readobj.h"
15*0fca6ea1SDimitry Andric #include "llvm/Demangle/Demangle.h"
160b57cec5SDimitry Andric #include "llvm/Object/XCOFFObjectFile.h"
17349cc55cSDimitry Andric #include "llvm/Support/FormattedStream.h"
180b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
190b57cec5SDimitry Andric 
2004eeddc0SDimitry Andric #include <ctime>
21349cc55cSDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric using namespace object;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric class XCOFFDumper : public ObjDumper {
288bcb0991SDimitry Andric 
290b57cec5SDimitry Andric public:
XCOFFDumper(const XCOFFObjectFile & Obj,ScopedPrinter & Writer)300b57cec5SDimitry Andric   XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
31e8d8bef9SDimitry Andric       : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   void printFileHeaders() override;
34349cc55cSDimitry Andric   void printAuxiliaryHeader() override;
350b57cec5SDimitry Andric   void printSectionHeaders() override;
360b57cec5SDimitry Andric   void printRelocations() override;
375f757f3fSDimitry Andric   void printSymbols(bool ExtraSymInfo) override;
380b57cec5SDimitry Andric   void printDynamicSymbols() override;
390b57cec5SDimitry Andric   void printUnwindInfo() override;
400b57cec5SDimitry Andric   void printStackMap() const override;
410b57cec5SDimitry Andric   void printNeededLibraries() override;
42fe6060f1SDimitry Andric   void printStringTable() override;
43bdd1243dSDimitry Andric   void printExceptionSection() override;
44bdd1243dSDimitry Andric   void printLoaderSection(bool PrintHeader, bool PrintSymbols,
45bdd1243dSDimitry Andric                           bool PrintRelocations) override;
460b57cec5SDimitry Andric 
getScopedPrinter() const4781ad6265SDimitry Andric   ScopedPrinter &getScopedPrinter() const { return W; }
4881ad6265SDimitry Andric 
490b57cec5SDimitry Andric private:
500b57cec5SDimitry Andric   template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
518bcb0991SDimitry Andric   template <typename T> void printGenericSectionHeader(T &Sec) const;
528bcb0991SDimitry Andric   template <typename T> void printOverflowSectionHeader(T &Sec) const;
53bdd1243dSDimitry Andric   template <typename T>
54bdd1243dSDimitry Andric   void printExceptionSectionEntry(const T &ExceptionSectEnt) const;
55bdd1243dSDimitry Andric   template <typename T> void printExceptionSectionEntries() const;
5604eeddc0SDimitry Andric   template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);
578bcb0991SDimitry Andric   void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
58fe6060f1SDimitry Andric   void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
598bcb0991SDimitry Andric   void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
6004eeddc0SDimitry Andric   void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr);
6104eeddc0SDimitry Andric   void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr);
6204eeddc0SDimitry Andric   void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr);
6304eeddc0SDimitry Andric   void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr);
6404eeddc0SDimitry Andric   void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr);
6504eeddc0SDimitry Andric   template <typename T> void printSectAuxEntForDWARF(const T *AuxEntPtr);
668bcb0991SDimitry Andric   void printSymbol(const SymbolRef &);
67349cc55cSDimitry Andric   template <typename RelTy> void printRelocation(RelTy Reloc);
68349cc55cSDimitry Andric   template <typename Shdr, typename RelTy>
69349cc55cSDimitry Andric   void printRelocations(ArrayRef<Shdr> Sections);
70349cc55cSDimitry Andric   void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
71349cc55cSDimitry Andric   void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
72bdd1243dSDimitry Andric   void printLoaderSectionHeader(uintptr_t LoaderSectAddr);
73bdd1243dSDimitry Andric   void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);
74bdd1243dSDimitry Andric   template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
75bdd1243dSDimitry Andric   void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);
76bdd1243dSDimitry Andric   template <typename LoadSectionRelocTy>
77bdd1243dSDimitry Andric   void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,
78bdd1243dSDimitry Andric                                          StringRef SymbolName);
79bdd1243dSDimitry Andric   void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);
80bdd1243dSDimitry Andric   template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
81bdd1243dSDimitry Andric             typename LoaderSectionRelocationEntry>
82bdd1243dSDimitry Andric   void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);
83bdd1243dSDimitry Andric 
848bcb0991SDimitry Andric   const XCOFFObjectFile &Obj;
85bdd1243dSDimitry Andric   const static int32_t FirstSymIdxOfLoaderSec = 3;
860b57cec5SDimitry Andric };
870b57cec5SDimitry Andric } // anonymous namespace
880b57cec5SDimitry Andric 
printFileHeaders()890b57cec5SDimitry Andric void XCOFFDumper::printFileHeaders() {
900b57cec5SDimitry Andric   DictScope DS(W, "FileHeader");
910b57cec5SDimitry Andric   W.printHex("Magic", Obj.getMagic());
920b57cec5SDimitry Andric   W.printNumber("NumberOfSections", Obj.getNumberOfSections());
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   // Negative timestamp values are reserved for future use.
950b57cec5SDimitry Andric   int32_t TimeStamp = Obj.getTimeStamp();
960b57cec5SDimitry Andric   if (TimeStamp > 0) {
970b57cec5SDimitry Andric     // This handling of the time stamp assumes that the host system's time_t is
980b57cec5SDimitry Andric     // compatible with AIX time_t. If a platform is not compatible, the lit
990b57cec5SDimitry Andric     // tests will let us know.
1000b57cec5SDimitry Andric     time_t TimeDate = TimeStamp;
1010b57cec5SDimitry Andric 
10206c3fb27SDimitry Andric     char FormattedTime[80] = {};
10306c3fb27SDimitry Andric 
10406c3fb27SDimitry Andric     size_t BytesFormatted =
10506c3fb27SDimitry Andric       strftime(FormattedTime, sizeof(FormattedTime), "%F %T", gmtime(&TimeDate));
10606c3fb27SDimitry Andric     if (BytesFormatted)
1070b57cec5SDimitry Andric       W.printHex("TimeStamp", FormattedTime, TimeStamp);
1080b57cec5SDimitry Andric     else
1090b57cec5SDimitry Andric       W.printHex("Timestamp", TimeStamp);
1100b57cec5SDimitry Andric   } else {
1110b57cec5SDimitry Andric     W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
1120b57cec5SDimitry Andric                TimeStamp);
1130b57cec5SDimitry Andric   }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // The number of symbol table entries is an unsigned value in 64-bit objects
1160b57cec5SDimitry Andric   // and a signed value (with negative values being 'reserved') in 32-bit
1170b57cec5SDimitry Andric   // objects.
1180b57cec5SDimitry Andric   if (Obj.is64Bit()) {
1190b57cec5SDimitry Andric     W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
1200b57cec5SDimitry Andric     W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
1210b57cec5SDimitry Andric   } else {
1220b57cec5SDimitry Andric     W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
1230b57cec5SDimitry Andric     int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
1240b57cec5SDimitry Andric     if (SymTabEntries >= 0)
1250b57cec5SDimitry Andric       W.printNumber("SymbolTableEntries", SymTabEntries);
1260b57cec5SDimitry Andric     else
1270b57cec5SDimitry Andric       W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
1310b57cec5SDimitry Andric   W.printHex("Flags", Obj.getFlags());
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   // TODO FIXME Add support for the auxiliary header (if any) once
1340b57cec5SDimitry Andric   // XCOFFObjectFile has the necessary support.
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
printAuxiliaryHeader()137349cc55cSDimitry Andric void XCOFFDumper::printAuxiliaryHeader() {
13881ad6265SDimitry Andric   DictScope DS(W, "AuxiliaryHeader");
13981ad6265SDimitry Andric 
140349cc55cSDimitry Andric   if (Obj.is64Bit())
141349cc55cSDimitry Andric     printAuxiliaryHeader(Obj.auxiliaryHeader64());
142349cc55cSDimitry Andric   else
143349cc55cSDimitry Andric     printAuxiliaryHeader(Obj.auxiliaryHeader32());
144349cc55cSDimitry Andric }
145349cc55cSDimitry Andric 
printSectionHeaders()1460b57cec5SDimitry Andric void XCOFFDumper::printSectionHeaders() {
1470b57cec5SDimitry Andric   if (Obj.is64Bit())
1480b57cec5SDimitry Andric     printSectionHeaders(Obj.sections64());
1490b57cec5SDimitry Andric   else
1500b57cec5SDimitry Andric     printSectionHeaders(Obj.sections32());
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
printLoaderSection(bool PrintHeader,bool PrintSymbols,bool PrintRelocations)153bdd1243dSDimitry Andric void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,
154bdd1243dSDimitry Andric                                      bool PrintRelocations) {
155bdd1243dSDimitry Andric   DictScope DS(W, "Loader Section");
156bdd1243dSDimitry Andric   Expected<uintptr_t> LoaderSectionAddrOrError =
157bdd1243dSDimitry Andric       Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
158bdd1243dSDimitry Andric   if (!LoaderSectionAddrOrError) {
159bdd1243dSDimitry Andric     reportUniqueWarning(LoaderSectionAddrOrError.takeError());
160bdd1243dSDimitry Andric     return;
161bdd1243dSDimitry Andric   }
162bdd1243dSDimitry Andric   uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
163bdd1243dSDimitry Andric 
164bdd1243dSDimitry Andric   if (LoaderSectionAddr == 0)
165bdd1243dSDimitry Andric     return;
166bdd1243dSDimitry Andric 
167bdd1243dSDimitry Andric   W.indent();
168bdd1243dSDimitry Andric   if (PrintHeader)
169bdd1243dSDimitry Andric     printLoaderSectionHeader(LoaderSectionAddr);
170bdd1243dSDimitry Andric 
171bdd1243dSDimitry Andric   if (PrintSymbols)
172bdd1243dSDimitry Andric     printLoaderSectionSymbols(LoaderSectionAddr);
173bdd1243dSDimitry Andric 
174bdd1243dSDimitry Andric   if (PrintRelocations)
175bdd1243dSDimitry Andric     printLoaderSectionRelocationEntries(LoaderSectionAddr);
176bdd1243dSDimitry Andric 
177bdd1243dSDimitry Andric   W.unindent();
178bdd1243dSDimitry Andric }
179bdd1243dSDimitry Andric 
printLoaderSectionHeader(uintptr_t LoaderSectionAddr)180bdd1243dSDimitry Andric void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) {
181bdd1243dSDimitry Andric   DictScope DS(W, "Loader Section Header");
182bdd1243dSDimitry Andric 
183bdd1243dSDimitry Andric   auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {
184bdd1243dSDimitry Andric     W.printNumber("Version", LDHeader->Version);
185bdd1243dSDimitry Andric     W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt);
186bdd1243dSDimitry Andric     W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt);
187bdd1243dSDimitry Andric     W.printNumber("LengthOfImportFileIDStringTable",
188bdd1243dSDimitry Andric                   LDHeader->LengthOfImpidStrTbl);
189bdd1243dSDimitry Andric     W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid);
190bdd1243dSDimitry Andric     W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid);
191bdd1243dSDimitry Andric     W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl);
192bdd1243dSDimitry Andric     W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl);
193bdd1243dSDimitry Andric   };
194bdd1243dSDimitry Andric 
195bdd1243dSDimitry Andric   if (Obj.is64Bit()) {
196bdd1243dSDimitry Andric     const LoaderSectionHeader64 *LoaderSec64 =
197bdd1243dSDimitry Andric         reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);
198bdd1243dSDimitry Andric     PrintLoadSecHeaderCommon(LoaderSec64);
199bdd1243dSDimitry Andric     W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);
200bdd1243dSDimitry Andric     W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);
201bdd1243dSDimitry Andric   } else {
202bdd1243dSDimitry Andric     const LoaderSectionHeader32 *LoaderSec32 =
203bdd1243dSDimitry Andric         reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);
204bdd1243dSDimitry Andric     PrintLoadSecHeaderCommon(LoaderSec32);
205bdd1243dSDimitry Andric   }
206bdd1243dSDimitry Andric }
207bdd1243dSDimitry Andric 
208bdd1243dSDimitry Andric const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
209bdd1243dSDimitry Andric #define ECase(X)                                                               \
210bdd1243dSDimitry Andric   { #X, XCOFF::X }
211bdd1243dSDimitry Andric     ECase(C_NULL),  ECase(C_AUTO),    ECase(C_EXT),     ECase(C_STAT),
212bdd1243dSDimitry Andric     ECase(C_REG),   ECase(C_EXTDEF),  ECase(C_LABEL),   ECase(C_ULABEL),
213bdd1243dSDimitry Andric     ECase(C_MOS),   ECase(C_ARG),     ECase(C_STRTAG),  ECase(C_MOU),
214bdd1243dSDimitry Andric     ECase(C_UNTAG), ECase(C_TPDEF),   ECase(C_USTATIC), ECase(C_ENTAG),
215bdd1243dSDimitry Andric     ECase(C_MOE),   ECase(C_REGPARM), ECase(C_FIELD),   ECase(C_BLOCK),
216bdd1243dSDimitry Andric     ECase(C_FCN),   ECase(C_EOS),     ECase(C_FILE),    ECase(C_LINE),
217bdd1243dSDimitry Andric     ECase(C_ALIAS), ECase(C_HIDDEN),  ECase(C_HIDEXT),  ECase(C_BINCL),
218bdd1243dSDimitry Andric     ECase(C_EINCL), ECase(C_INFO),    ECase(C_WEAKEXT), ECase(C_DWARF),
219bdd1243dSDimitry Andric     ECase(C_GSYM),  ECase(C_LSYM),    ECase(C_PSYM),    ECase(C_RSYM),
220bdd1243dSDimitry Andric     ECase(C_RPSYM), ECase(C_STSYM),   ECase(C_TCSYM),   ECase(C_BCOMM),
221bdd1243dSDimitry Andric     ECase(C_ECOML), ECase(C_ECOMM),   ECase(C_DECL),    ECase(C_ENTRY),
222bdd1243dSDimitry Andric     ECase(C_FUN),   ECase(C_BSTAT),   ECase(C_ESTAT),   ECase(C_GTLS),
223bdd1243dSDimitry Andric     ECase(C_STTLS), ECase(C_EFCN)
224bdd1243dSDimitry Andric #undef ECase
225bdd1243dSDimitry Andric };
226bdd1243dSDimitry Andric 
227bdd1243dSDimitry Andric template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr)228bdd1243dSDimitry Andric void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) {
229bdd1243dSDimitry Andric   const LoaderSectionHeader *LoadSecHeader =
230bdd1243dSDimitry Andric       reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
231bdd1243dSDimitry Andric   const LoaderSectionSymbolEntry *LoadSecSymEntPtr =
232bdd1243dSDimitry Andric       reinterpret_cast<LoaderSectionSymbolEntry *>(
233bdd1243dSDimitry Andric           LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()));
234bdd1243dSDimitry Andric 
235bdd1243dSDimitry Andric   for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt;
236bdd1243dSDimitry Andric        ++i, ++LoadSecSymEntPtr) {
237bdd1243dSDimitry Andric     if (Error E = Binary::checkOffset(
238bdd1243dSDimitry Andric             Obj.getMemoryBufferRef(),
239bdd1243dSDimitry Andric             LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()) +
240bdd1243dSDimitry Andric                 (i * sizeof(LoaderSectionSymbolEntry)),
241bdd1243dSDimitry Andric             sizeof(LoaderSectionSymbolEntry))) {
242bdd1243dSDimitry Andric       reportUniqueWarning(std::move(E));
243bdd1243dSDimitry Andric       return;
244bdd1243dSDimitry Andric     }
245bdd1243dSDimitry Andric 
246bdd1243dSDimitry Andric     Expected<StringRef> SymbolNameOrErr =
247bdd1243dSDimitry Andric         LoadSecSymEntPtr->getSymbolName(LoadSecHeader);
248bdd1243dSDimitry Andric     if (!SymbolNameOrErr) {
249bdd1243dSDimitry Andric       reportUniqueWarning(SymbolNameOrErr.takeError());
250bdd1243dSDimitry Andric       return;
251bdd1243dSDimitry Andric     }
252bdd1243dSDimitry Andric 
253bdd1243dSDimitry Andric     DictScope DS(W, "Symbol");
254*0fca6ea1SDimitry Andric     StringRef SymbolName = SymbolNameOrErr.get();
255*0fca6ea1SDimitry Andric     W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);
256bdd1243dSDimitry Andric     W.printHex("Virtual Address", LoadSecSymEntPtr->Value);
257bdd1243dSDimitry Andric     W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber);
258bdd1243dSDimitry Andric     W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType);
259bdd1243dSDimitry Andric     W.printEnum("StorageClass",
260bdd1243dSDimitry Andric                 static_cast<uint8_t>(LoadSecSymEntPtr->StorageClass),
261bdd1243dSDimitry Andric                 ArrayRef(SymStorageClass));
262bdd1243dSDimitry Andric     W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID);
263bdd1243dSDimitry Andric     W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck);
264bdd1243dSDimitry Andric   }
265bdd1243dSDimitry Andric }
266bdd1243dSDimitry Andric 
printLoaderSectionSymbols(uintptr_t LoaderSectionAddr)267bdd1243dSDimitry Andric void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {
268bdd1243dSDimitry Andric   DictScope DS(W, "Loader Section Symbols");
2698bcb0991SDimitry Andric   if (Obj.is64Bit())
270bdd1243dSDimitry Andric     printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64,
271bdd1243dSDimitry Andric                                     LoaderSectionHeader64>(LoaderSectionAddr);
2728bcb0991SDimitry Andric   else
273bdd1243dSDimitry Andric     printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32,
274bdd1243dSDimitry Andric                                     LoaderSectionHeader32>(LoaderSectionAddr);
2758bcb0991SDimitry Andric }
2768bcb0991SDimitry Andric 
277349cc55cSDimitry Andric const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
2788bcb0991SDimitry Andric #define ECase(X)                                                               \
2798bcb0991SDimitry Andric   { #X, XCOFF::X }
2808bcb0991SDimitry Andric     ECase(R_POS),    ECase(R_RL),     ECase(R_RLA),    ECase(R_NEG),
2818bcb0991SDimitry Andric     ECase(R_REL),    ECase(R_TOC),    ECase(R_TRL),    ECase(R_TRLA),
2828bcb0991SDimitry Andric     ECase(R_GL),     ECase(R_TCL),    ECase(R_REF),    ECase(R_BA),
2838bcb0991SDimitry Andric     ECase(R_BR),     ECase(R_RBA),    ECase(R_RBR),    ECase(R_TLS),
2848bcb0991SDimitry Andric     ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
2858bcb0991SDimitry Andric     ECase(R_TLSML),  ECase(R_TOCU),   ECase(R_TOCL)
2868bcb0991SDimitry Andric #undef ECase
2878bcb0991SDimitry Andric };
2888bcb0991SDimitry Andric 
289bdd1243dSDimitry Andric // From the XCOFF specification: there are five implicit external symbols, one
290bdd1243dSDimitry Andric // each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols
291bdd1243dSDimitry Andric // are referenced from the relocation table entries using symbol table index
292bdd1243dSDimitry Andric // values 0, 1, 2, -1, and -2, respectively.
getImplicitLoaderSectionSymName(int SymIndx)293bdd1243dSDimitry Andric static const char *getImplicitLoaderSectionSymName(int SymIndx) {
294bdd1243dSDimitry Andric   switch (SymIndx) {
295bdd1243dSDimitry Andric   default:
296bdd1243dSDimitry Andric     return "Unkown Symbol Name";
297bdd1243dSDimitry Andric   case -2:
298bdd1243dSDimitry Andric     return ".tbss";
299bdd1243dSDimitry Andric   case -1:
300bdd1243dSDimitry Andric     return ".tdata";
301bdd1243dSDimitry Andric   case 0:
302bdd1243dSDimitry Andric     return ".text";
303bdd1243dSDimitry Andric   case 1:
304bdd1243dSDimitry Andric     return ".data";
305bdd1243dSDimitry Andric   case 2:
306bdd1243dSDimitry Andric     return ".bss";
307bdd1243dSDimitry Andric   }
308bdd1243dSDimitry Andric }
309bdd1243dSDimitry Andric 
310bdd1243dSDimitry Andric template <typename LoadSectionRelocTy>
printLoaderSectionRelocationEntry(LoadSectionRelocTy * LoaderSecRelEntPtr,StringRef SymbolName)311bdd1243dSDimitry Andric void XCOFFDumper::printLoaderSectionRelocationEntry(
312bdd1243dSDimitry Andric     LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {
313bdd1243dSDimitry Andric   uint16_t Type = LoaderSecRelEntPtr->Type;
314bdd1243dSDimitry Andric   if (opts::ExpandRelocs) {
315bdd1243dSDimitry Andric     DictScope DS(W, "Relocation");
316bdd1243dSDimitry Andric     auto IsRelocationSigned = [](uint8_t Info) {
317bdd1243dSDimitry Andric       return Info & XCOFF::XR_SIGN_INDICATOR_MASK;
318bdd1243dSDimitry Andric     };
319bdd1243dSDimitry Andric     auto IsFixupIndicated = [](uint8_t Info) {
320bdd1243dSDimitry Andric       return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;
321bdd1243dSDimitry Andric     };
322bdd1243dSDimitry Andric     auto GetRelocatedLength = [](uint8_t Info) {
323bdd1243dSDimitry Andric       // The relocation encodes the bit length being relocated minus 1. Add
324bdd1243dSDimitry Andric       // back
325bdd1243dSDimitry Andric       //   the 1 to get the actual length being relocated.
326bdd1243dSDimitry Andric       return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;
327bdd1243dSDimitry Andric     };
328bdd1243dSDimitry Andric 
329bdd1243dSDimitry Andric     uint8_t Info = Type >> 8;
330bdd1243dSDimitry Andric     W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);
331*0fca6ea1SDimitry Andric     W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,
332*0fca6ea1SDimitry Andric                   LoaderSecRelEntPtr->SymbolIndex);
333bdd1243dSDimitry Andric     W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");
334bdd1243dSDimitry Andric     W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);
335bdd1243dSDimitry Andric     W.printNumber("Length", GetRelocatedLength(Info));
336bdd1243dSDimitry Andric     W.printEnum("Type", static_cast<uint8_t>(Type),
337bdd1243dSDimitry Andric                 ArrayRef(RelocationTypeNameclass));
338bdd1243dSDimitry Andric     W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);
339bdd1243dSDimitry Andric   } else {
340bdd1243dSDimitry Andric     W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,
341bdd1243dSDimitry Andric                                 Obj.is64Bit() ? 18 : 10)
342bdd1243dSDimitry Andric                   << " " << format_hex(Type, 6) << " ("
343bdd1243dSDimitry Andric                   << XCOFF::getRelocationTypeString(
344bdd1243dSDimitry Andric                          static_cast<XCOFF::RelocationType>(Type))
345bdd1243dSDimitry Andric                   << ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)
346*0fca6ea1SDimitry Andric                   << "    "
347*0fca6ea1SDimitry Andric                   << (opts::Demangle ? demangle(SymbolName) : SymbolName)
348*0fca6ea1SDimitry Andric                   << " (" << LoaderSecRelEntPtr->SymbolIndex << ")\n";
349bdd1243dSDimitry Andric   }
350bdd1243dSDimitry Andric }
351bdd1243dSDimitry Andric 
352bdd1243dSDimitry Andric template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
353bdd1243dSDimitry Andric           typename LoaderSectionRelocationEntry>
printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectionAddr)354bdd1243dSDimitry Andric void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(
355bdd1243dSDimitry Andric     uintptr_t LoaderSectionAddr) {
356bdd1243dSDimitry Andric   const LoaderSectionHeader *LoaderSec =
357bdd1243dSDimitry Andric       reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
358bdd1243dSDimitry Andric   const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =
359bdd1243dSDimitry Andric       reinterpret_cast<const LoaderSectionRelocationEntry *>(
360bdd1243dSDimitry Andric           LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));
361bdd1243dSDimitry Andric 
362bdd1243dSDimitry Andric   if (!opts::ExpandRelocs)
363bdd1243dSDimitry Andric     W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)
364bdd1243dSDimitry Andric                   << center_justify("Type", 15) << right_justify("SecNum", 8)
365bdd1243dSDimitry Andric                   << center_justify("SymbolName (Index) ", 24) << "\n";
366bdd1243dSDimitry Andric 
367bdd1243dSDimitry Andric   for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;
368bdd1243dSDimitry Andric        ++i, ++LoaderSecRelEntPtr) {
369bdd1243dSDimitry Andric     StringRef SymbolName;
370bdd1243dSDimitry Andric     if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {
371bdd1243dSDimitry Andric       // Because there are implicit symbol index values (-2, -1, 0, 1, 2),
372bdd1243dSDimitry Andric       // LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the
373bdd1243dSDimitry Andric       // real symbol from the symbol table.
374bdd1243dSDimitry Andric       const uint64_t SymOffset =
375bdd1243dSDimitry Andric           (LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *
376bdd1243dSDimitry Andric           sizeof(LoaderSectionSymbolEntry);
377bdd1243dSDimitry Andric       const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =
378bdd1243dSDimitry Andric           reinterpret_cast<LoaderSectionSymbolEntry *>(
379bdd1243dSDimitry Andric               LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +
380bdd1243dSDimitry Andric               SymOffset);
381bdd1243dSDimitry Andric 
382bdd1243dSDimitry Andric       Expected<StringRef> SymbolNameOrErr =
383bdd1243dSDimitry Andric           LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);
384bdd1243dSDimitry Andric       if (!SymbolNameOrErr) {
385bdd1243dSDimitry Andric         reportUniqueWarning(SymbolNameOrErr.takeError());
386bdd1243dSDimitry Andric         return;
387bdd1243dSDimitry Andric       }
388bdd1243dSDimitry Andric       SymbolName = SymbolNameOrErr.get();
389bdd1243dSDimitry Andric     } else
390bdd1243dSDimitry Andric       SymbolName =
391bdd1243dSDimitry Andric           getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);
392bdd1243dSDimitry Andric 
393bdd1243dSDimitry Andric     printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);
394bdd1243dSDimitry Andric   }
395bdd1243dSDimitry Andric }
396bdd1243dSDimitry Andric 
printLoaderSectionRelocationEntries(uintptr_t LoaderSectionAddr)397bdd1243dSDimitry Andric void XCOFFDumper::printLoaderSectionRelocationEntries(
398bdd1243dSDimitry Andric     uintptr_t LoaderSectionAddr) {
399bdd1243dSDimitry Andric   DictScope DS(W, "Loader Section Relocations");
400bdd1243dSDimitry Andric 
401bdd1243dSDimitry Andric   if (Obj.is64Bit())
402bdd1243dSDimitry Andric     printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,
403bdd1243dSDimitry Andric                                               LoaderSectionSymbolEntry64,
404bdd1243dSDimitry Andric                                               LoaderSectionRelocationEntry64>(
405bdd1243dSDimitry Andric         LoaderSectionAddr);
406bdd1243dSDimitry Andric   else
407bdd1243dSDimitry Andric     printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,
408bdd1243dSDimitry Andric                                               LoaderSectionSymbolEntry32,
409bdd1243dSDimitry Andric                                               LoaderSectionRelocationEntry32>(
410bdd1243dSDimitry Andric         LoaderSectionAddr);
411bdd1243dSDimitry Andric }
412bdd1243dSDimitry Andric 
413bdd1243dSDimitry Andric template <typename T>
printExceptionSectionEntry(const T & ExceptionSectEnt) const414bdd1243dSDimitry Andric void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {
415bdd1243dSDimitry Andric   if (ExceptionSectEnt.getReason())
416bdd1243dSDimitry Andric     W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());
417bdd1243dSDimitry Andric   else {
418bdd1243dSDimitry Andric     uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();
419bdd1243dSDimitry Andric     Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);
420bdd1243dSDimitry Andric     if (Error E = ErrOrSymbolName.takeError()) {
421bdd1243dSDimitry Andric       reportUniqueWarning(std::move(E));
422bdd1243dSDimitry Andric       return;
423bdd1243dSDimitry Andric     }
424bdd1243dSDimitry Andric     StringRef SymName = *ErrOrSymbolName;
425bdd1243dSDimitry Andric 
426bdd1243dSDimitry Andric     W.printNumber("Symbol", SymName, SymIdx);
427bdd1243dSDimitry Andric   }
428bdd1243dSDimitry Andric   W.printNumber("LangID", ExceptionSectEnt.getLangID());
429bdd1243dSDimitry Andric   W.printNumber("Reason", ExceptionSectEnt.getReason());
430bdd1243dSDimitry Andric }
431bdd1243dSDimitry Andric 
printExceptionSectionEntries() const432bdd1243dSDimitry Andric template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {
433bdd1243dSDimitry Andric   Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();
434bdd1243dSDimitry Andric   if (Error E = ExceptSectEntsOrErr.takeError()) {
435bdd1243dSDimitry Andric     reportUniqueWarning(std::move(E));
436bdd1243dSDimitry Andric     return;
437bdd1243dSDimitry Andric   }
438bdd1243dSDimitry Andric   ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;
439bdd1243dSDimitry Andric 
440bdd1243dSDimitry Andric   DictScope DS(W, "Exception section");
441bdd1243dSDimitry Andric   if (ExceptSectEnts.empty())
442bdd1243dSDimitry Andric     return;
443bdd1243dSDimitry Andric   for (auto &Ent : ExceptSectEnts)
444bdd1243dSDimitry Andric     printExceptionSectionEntry(Ent);
445bdd1243dSDimitry Andric }
446bdd1243dSDimitry Andric 
printExceptionSection()447bdd1243dSDimitry Andric void XCOFFDumper::printExceptionSection() {
448bdd1243dSDimitry Andric   if (Obj.is64Bit())
449bdd1243dSDimitry Andric     printExceptionSectionEntries<ExceptionSectionEntry64>();
450bdd1243dSDimitry Andric   else
451bdd1243dSDimitry Andric     printExceptionSectionEntries<ExceptionSectionEntry32>();
452bdd1243dSDimitry Andric }
453bdd1243dSDimitry Andric 
printRelocations()454bdd1243dSDimitry Andric void XCOFFDumper::printRelocations() {
455bdd1243dSDimitry Andric   if (Obj.is64Bit())
456bdd1243dSDimitry Andric     printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
457bdd1243dSDimitry Andric   else
458bdd1243dSDimitry Andric     printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
459bdd1243dSDimitry Andric }
460bdd1243dSDimitry Andric 
printRelocation(RelTy Reloc)461349cc55cSDimitry Andric template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {
462349cc55cSDimitry Andric   Expected<StringRef> ErrOrSymbolName =
463349cc55cSDimitry Andric       Obj.getSymbolNameByIndex(Reloc.SymbolIndex);
464349cc55cSDimitry Andric   if (Error E = ErrOrSymbolName.takeError()) {
465349cc55cSDimitry Andric     reportUniqueWarning(std::move(E));
466349cc55cSDimitry Andric     return;
467349cc55cSDimitry Andric   }
468349cc55cSDimitry Andric   StringRef SymbolName = *ErrOrSymbolName;
469349cc55cSDimitry Andric   StringRef RelocName = XCOFF::getRelocationTypeString(Reloc.Type);
470349cc55cSDimitry Andric   if (opts::ExpandRelocs) {
471349cc55cSDimitry Andric     DictScope Group(W, "Relocation");
4728bcb0991SDimitry Andric     W.printHex("Virtual Address", Reloc.VirtualAddress);
473*0fca6ea1SDimitry Andric     W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,
474*0fca6ea1SDimitry Andric                   Reloc.SymbolIndex);
4758bcb0991SDimitry Andric     W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
4768bcb0991SDimitry Andric     W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
4778bcb0991SDimitry Andric     W.printNumber("Length", Reloc.getRelocatedLength());
478bdd1243dSDimitry Andric     W.printEnum("Type", (uint8_t)Reloc.Type, ArrayRef(RelocationTypeNameclass));
479349cc55cSDimitry Andric   } else {
480349cc55cSDimitry Andric     raw_ostream &OS = W.startLine();
481*0fca6ea1SDimitry Andric     OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " "
482*0fca6ea1SDimitry Andric        << (opts::Demangle ? demangle(SymbolName) : SymbolName) << "("
483*0fca6ea1SDimitry Andric        << Reloc.SymbolIndex << ") " << W.hex(Reloc.Info) << "\n";
4848bcb0991SDimitry Andric   }
485349cc55cSDimitry Andric }
486349cc55cSDimitry Andric 
487349cc55cSDimitry Andric template <typename Shdr, typename RelTy>
printRelocations(ArrayRef<Shdr> Sections)488349cc55cSDimitry Andric void XCOFFDumper::printRelocations(ArrayRef<Shdr> Sections) {
489349cc55cSDimitry Andric   ListScope LS(W, "Relocations");
490349cc55cSDimitry Andric   uint16_t Index = 0;
491349cc55cSDimitry Andric   for (const Shdr &Sec : Sections) {
492349cc55cSDimitry Andric     ++Index;
493349cc55cSDimitry Andric     // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
494349cc55cSDimitry Andric     if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
495349cc55cSDimitry Andric         Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
496349cc55cSDimitry Andric       continue;
497349cc55cSDimitry Andric     Expected<ArrayRef<RelTy>> ErrOrRelocations = Obj.relocations<Shdr, RelTy>(Sec);
498349cc55cSDimitry Andric     if (Error E = ErrOrRelocations.takeError()) {
499349cc55cSDimitry Andric       reportUniqueWarning(std::move(E));
500349cc55cSDimitry Andric       continue;
501349cc55cSDimitry Andric     }
502349cc55cSDimitry Andric 
503349cc55cSDimitry Andric     const ArrayRef<RelTy> Relocations = *ErrOrRelocations;
504349cc55cSDimitry Andric     if (Relocations.empty())
505349cc55cSDimitry Andric       continue;
506349cc55cSDimitry Andric 
507349cc55cSDimitry Andric     W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
508349cc55cSDimitry Andric                   << " {\n";
509349cc55cSDimitry Andric     W.indent();
510349cc55cSDimitry Andric 
511349cc55cSDimitry Andric     for (const RelTy Reloc : Relocations)
512349cc55cSDimitry Andric       printRelocation(Reloc);
513349cc55cSDimitry Andric 
5148bcb0991SDimitry Andric     W.unindent();
5158bcb0991SDimitry Andric     W.startLine() << "}\n";
5168bcb0991SDimitry Andric   }
5178bcb0991SDimitry Andric }
5188bcb0991SDimitry Andric 
519349cc55cSDimitry Andric const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
5208bcb0991SDimitry Andric #define ECase(X)                                                               \
5218bcb0991SDimitry Andric   { #X, XCOFF::X }
5228bcb0991SDimitry Andric     ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
5238bcb0991SDimitry Andric #undef ECase
5248bcb0991SDimitry Andric };
5258bcb0991SDimitry Andric 
526349cc55cSDimitry Andric const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {
527fe6060f1SDimitry Andric #define ECase(X)                                                               \
528fe6060f1SDimitry Andric   { #X, XCOFF::X }
529fe6060f1SDimitry Andric     ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),
530fe6060f1SDimitry Andric     ECase(AUX_CSECT),  ECase(AUX_SECT)
531fe6060f1SDimitry Andric #undef ECase
532fe6060f1SDimitry Andric };
533fe6060f1SDimitry Andric 
printFileAuxEnt(const XCOFFFileAuxEnt * AuxEntPtr)5348bcb0991SDimitry Andric void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
535fe6060f1SDimitry Andric   assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&
536fe6060f1SDimitry Andric          "Mismatched auxiliary type!");
5378bcb0991SDimitry Andric   StringRef FileName =
5388bcb0991SDimitry Andric       unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
5398bcb0991SDimitry Andric   DictScope SymDs(W, "File Auxiliary Entry");
5408bcb0991SDimitry Andric   W.printNumber("Index",
5418bcb0991SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
5428bcb0991SDimitry Andric   W.printString("Name", FileName);
5438bcb0991SDimitry Andric   W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
544bdd1243dSDimitry Andric               ArrayRef(FileStringType));
545fe6060f1SDimitry Andric   if (Obj.is64Bit()) {
546fe6060f1SDimitry Andric     W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
547bdd1243dSDimitry Andric                 ArrayRef(SymAuxType));
548fe6060f1SDimitry Andric   }
5498bcb0991SDimitry Andric }
5508bcb0991SDimitry Andric 
5518bcb0991SDimitry Andric static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
5528bcb0991SDimitry Andric     {
5538bcb0991SDimitry Andric #define ECase(X)                                                               \
5548bcb0991SDimitry Andric   { #X, XCOFF::X }
555fe6060f1SDimitry Andric         ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB),   ECase(XMC_GL),
556fe6060f1SDimitry Andric         ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),
557fe6060f1SDimitry Andric         ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW),   ECase(XMC_TC0),
558fe6060f1SDimitry Andric         ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),   ECase(XMC_UA),
559fe6060f1SDimitry Andric         ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL),   ECase(XMC_UL),
560fe6060f1SDimitry Andric         ECase(XMC_TE)
5618bcb0991SDimitry Andric #undef ECase
5628bcb0991SDimitry Andric };
5638bcb0991SDimitry Andric 
564349cc55cSDimitry Andric const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
5658bcb0991SDimitry Andric #define ECase(X)                                                               \
5668bcb0991SDimitry Andric   { #X, XCOFF::X }
5678bcb0991SDimitry Andric     ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
5688bcb0991SDimitry Andric #undef ECase
5698bcb0991SDimitry Andric };
5708bcb0991SDimitry Andric 
printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef)571fe6060f1SDimitry Andric void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {
572fe6060f1SDimitry Andric   assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&
573fe6060f1SDimitry Andric          "Mismatched auxiliary type!");
5748bcb0991SDimitry Andric 
5758bcb0991SDimitry Andric   DictScope SymDs(W, "CSECT Auxiliary Entry");
576fe6060f1SDimitry Andric   W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));
577fe6060f1SDimitry Andric   W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"
578fe6060f1SDimitry Andric                                     : "SectionLen",
579fe6060f1SDimitry Andric                 AuxEntRef.getSectionOrLength());
580fe6060f1SDimitry Andric   W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());
581fe6060f1SDimitry Andric   W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());
5828bcb0991SDimitry Andric   // Print out symbol alignment and type.
583fe6060f1SDimitry Andric   W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
584fe6060f1SDimitry Andric   W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
585bdd1243dSDimitry Andric               ArrayRef(CsectSymbolTypeClass));
5868bcb0991SDimitry Andric   W.printEnum("StorageMappingClass",
587fe6060f1SDimitry Andric               static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
588bdd1243dSDimitry Andric               ArrayRef(CsectStorageMappingClass));
589fe6060f1SDimitry Andric 
590fe6060f1SDimitry Andric   if (Obj.is64Bit()) {
591fe6060f1SDimitry Andric     W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
592bdd1243dSDimitry Andric                 ArrayRef(SymAuxType));
593fe6060f1SDimitry Andric   } else {
594fe6060f1SDimitry Andric     W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
595fe6060f1SDimitry Andric     W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
596fe6060f1SDimitry Andric   }
5978bcb0991SDimitry Andric }
5988bcb0991SDimitry Andric 
printSectAuxEntForStat(const XCOFFSectAuxEntForStat * AuxEntPtr)5998bcb0991SDimitry Andric void XCOFFDumper::printSectAuxEntForStat(
6008bcb0991SDimitry Andric     const XCOFFSectAuxEntForStat *AuxEntPtr) {
6018bcb0991SDimitry Andric   assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
6028bcb0991SDimitry Andric 
6038bcb0991SDimitry Andric   DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
6048bcb0991SDimitry Andric   W.printNumber("Index",
6058bcb0991SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
6068bcb0991SDimitry Andric   W.printNumber("SectionLength", AuxEntPtr->SectionLength);
6078bcb0991SDimitry Andric 
6088bcb0991SDimitry Andric   // Unlike the corresponding fields in the section header, NumberOfRelocEnt
6098bcb0991SDimitry Andric   // and NumberOfLineNum do not handle values greater than 65535.
6108bcb0991SDimitry Andric   W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
6118bcb0991SDimitry Andric   W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
6128bcb0991SDimitry Andric }
6138bcb0991SDimitry Andric 
printExceptionAuxEnt(const XCOFFExceptionAuxEnt * AuxEntPtr)61404eeddc0SDimitry Andric void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) {
61504eeddc0SDimitry Andric   assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
61604eeddc0SDimitry Andric 
61704eeddc0SDimitry Andric   DictScope SymDs(W, "Exception Auxiliary Entry");
61804eeddc0SDimitry Andric   W.printNumber("Index",
61904eeddc0SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
62004eeddc0SDimitry Andric   W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
62104eeddc0SDimitry Andric   W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
62204eeddc0SDimitry Andric   W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
62304eeddc0SDimitry Andric   W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
624bdd1243dSDimitry Andric               ArrayRef(SymAuxType));
62504eeddc0SDimitry Andric }
62604eeddc0SDimitry Andric 
printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 * AuxEntPtr)62704eeddc0SDimitry Andric void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {
62804eeddc0SDimitry Andric   assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
62904eeddc0SDimitry Andric 
63004eeddc0SDimitry Andric   DictScope SymDs(W, "Function Auxiliary Entry");
63104eeddc0SDimitry Andric   W.printNumber("Index",
63204eeddc0SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
63304eeddc0SDimitry Andric   W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
63404eeddc0SDimitry Andric   W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
63504eeddc0SDimitry Andric   W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
63604eeddc0SDimitry Andric   W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
63704eeddc0SDimitry Andric }
63804eeddc0SDimitry Andric 
printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 * AuxEntPtr)63904eeddc0SDimitry Andric void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) {
64004eeddc0SDimitry Andric   assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
64104eeddc0SDimitry Andric 
64204eeddc0SDimitry Andric   DictScope SymDs(W, "Function Auxiliary Entry");
64304eeddc0SDimitry Andric   W.printNumber("Index",
64404eeddc0SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
64504eeddc0SDimitry Andric   W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
64604eeddc0SDimitry Andric   W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
64704eeddc0SDimitry Andric   W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
64804eeddc0SDimitry Andric   W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
649bdd1243dSDimitry Andric               ArrayRef(SymAuxType));
65004eeddc0SDimitry Andric }
65104eeddc0SDimitry Andric 
printBlockAuxEnt(const XCOFFBlockAuxEnt32 * AuxEntPtr)65204eeddc0SDimitry Andric void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {
65304eeddc0SDimitry Andric   assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
65404eeddc0SDimitry Andric 
65504eeddc0SDimitry Andric   DictScope SymDs(W, "Block Auxiliary Entry");
65604eeddc0SDimitry Andric   W.printNumber("Index",
65704eeddc0SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
65804eeddc0SDimitry Andric   W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi);
65904eeddc0SDimitry Andric   W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo);
66004eeddc0SDimitry Andric }
66104eeddc0SDimitry Andric 
printBlockAuxEnt(const XCOFFBlockAuxEnt64 * AuxEntPtr)66204eeddc0SDimitry Andric void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) {
66304eeddc0SDimitry Andric   assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
66404eeddc0SDimitry Andric 
66504eeddc0SDimitry Andric   DictScope SymDs(W, "Block Auxiliary Entry");
66604eeddc0SDimitry Andric   W.printNumber("Index",
66704eeddc0SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
66804eeddc0SDimitry Andric   W.printHex("LineNumber", AuxEntPtr->LineNum);
66904eeddc0SDimitry Andric   W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
670bdd1243dSDimitry Andric               ArrayRef(SymAuxType));
67104eeddc0SDimitry Andric }
67204eeddc0SDimitry Andric 
67304eeddc0SDimitry Andric template <typename T>
printSectAuxEntForDWARF(const T * AuxEntPtr)67404eeddc0SDimitry Andric void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) {
67504eeddc0SDimitry Andric   DictScope SymDs(W, "Sect Auxiliary Entry For DWARF");
67604eeddc0SDimitry Andric   W.printNumber("Index",
67704eeddc0SDimitry Andric                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
67804eeddc0SDimitry Andric   W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion);
67904eeddc0SDimitry Andric   W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);
68004eeddc0SDimitry Andric   if (Obj.is64Bit())
68104eeddc0SDimitry Andric     W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),
682bdd1243dSDimitry Andric                 ArrayRef(SymAuxType));
68304eeddc0SDimitry Andric }
68404eeddc0SDimitry Andric 
GetSymbolValueName(XCOFF::StorageClass SC)6858bcb0991SDimitry Andric static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
6868bcb0991SDimitry Andric   switch (SC) {
6878bcb0991SDimitry Andric   case XCOFF::C_EXT:
6888bcb0991SDimitry Andric   case XCOFF::C_WEAKEXT:
6898bcb0991SDimitry Andric   case XCOFF::C_HIDEXT:
6908bcb0991SDimitry Andric   case XCOFF::C_STAT:
69104eeddc0SDimitry Andric   case XCOFF::C_FCN:
69204eeddc0SDimitry Andric   case XCOFF::C_BLOCK:
6938bcb0991SDimitry Andric     return "Value (RelocatableAddress)";
6948bcb0991SDimitry Andric   case XCOFF::C_FILE:
6958bcb0991SDimitry Andric     return "Value (SymbolTableIndex)";
69604eeddc0SDimitry Andric   case XCOFF::C_DWARF:
69704eeddc0SDimitry Andric     return "Value (OffsetInDWARF)";
6988bcb0991SDimitry Andric   case XCOFF::C_FUN:
6998bcb0991SDimitry Andric   case XCOFF::C_STSYM:
7008bcb0991SDimitry Andric   case XCOFF::C_BINCL:
7018bcb0991SDimitry Andric   case XCOFF::C_EINCL:
7028bcb0991SDimitry Andric   case XCOFF::C_INFO:
7038bcb0991SDimitry Andric   case XCOFF::C_BSTAT:
7048bcb0991SDimitry Andric   case XCOFF::C_LSYM:
7058bcb0991SDimitry Andric   case XCOFF::C_PSYM:
7068bcb0991SDimitry Andric   case XCOFF::C_RPSYM:
7078bcb0991SDimitry Andric   case XCOFF::C_RSYM:
7088bcb0991SDimitry Andric   case XCOFF::C_ECOML:
7098bcb0991SDimitry Andric     assert(false && "This StorageClass for the symbol is not yet implemented.");
7108bcb0991SDimitry Andric     return "";
7118bcb0991SDimitry Andric   default:
7128bcb0991SDimitry Andric     return "Value";
7138bcb0991SDimitry Andric   }
7148bcb0991SDimitry Andric }
7158bcb0991SDimitry Andric 
716349cc55cSDimitry Andric const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
7178bcb0991SDimitry Andric #define ECase(X)                                                               \
7188bcb0991SDimitry Andric   { #X, XCOFF::X }
71906c3fb27SDimitry Andric     ECase(TB_C), ECase(TB_Fortran), ECase(TB_CPLUSPLUS)
7208bcb0991SDimitry Andric #undef ECase
7218bcb0991SDimitry Andric };
7228bcb0991SDimitry Andric 
723349cc55cSDimitry Andric const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
7248bcb0991SDimitry Andric #define ECase(X)                                                               \
7258bcb0991SDimitry Andric   { #X, XCOFF::X }
7268bcb0991SDimitry Andric     ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
7278bcb0991SDimitry Andric #undef ECase
7288bcb0991SDimitry Andric };
7298bcb0991SDimitry Andric 
getAuxEntPtr(uintptr_t AuxAddress)73004eeddc0SDimitry Andric template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) {
73104eeddc0SDimitry Andric   const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress);
73204eeddc0SDimitry Andric   Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr));
73304eeddc0SDimitry Andric   return AuxEntPtr;
73404eeddc0SDimitry Andric }
73504eeddc0SDimitry Andric 
printUnexpectedRawAuxEnt(ScopedPrinter & W,uintptr_t AuxAddress)73604eeddc0SDimitry Andric static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) {
73704eeddc0SDimitry Andric   W.startLine() << "!Unexpected raw auxiliary entry data:\n";
73804eeddc0SDimitry Andric   W.startLine() << format_bytes(
73904eeddc0SDimitry Andric                        ArrayRef<uint8_t>(
74004eeddc0SDimitry Andric                            reinterpret_cast<const uint8_t *>(AuxAddress),
74104eeddc0SDimitry Andric                            XCOFF::SymbolTableEntrySize),
742bdd1243dSDimitry Andric                        std::nullopt, XCOFF::SymbolTableEntrySize)
74304eeddc0SDimitry Andric                 << "\n";
74404eeddc0SDimitry Andric }
74504eeddc0SDimitry Andric 
printSymbol(const SymbolRef & S)7468bcb0991SDimitry Andric void XCOFFDumper::printSymbol(const SymbolRef &S) {
7478bcb0991SDimitry Andric   DataRefImpl SymbolDRI = S.getRawDataRefImpl();
748fe6060f1SDimitry Andric   XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
7498bcb0991SDimitry Andric 
750fe6060f1SDimitry Andric   uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
7518bcb0991SDimitry Andric 
7528bcb0991SDimitry Andric   DictScope SymDs(W, "Symbol");
7538bcb0991SDimitry Andric 
7548bcb0991SDimitry Andric   StringRef SymbolName =
755fe6060f1SDimitry Andric       unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());
7568bcb0991SDimitry Andric 
75704eeddc0SDimitry Andric   uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
75804eeddc0SDimitry Andric   XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass();
75904eeddc0SDimitry Andric 
76004eeddc0SDimitry Andric   W.printNumber("Index", SymbolIdx);
761*0fca6ea1SDimitry Andric   W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);
76204eeddc0SDimitry Andric   W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue());
7638bcb0991SDimitry Andric 
7648bcb0991SDimitry Andric   StringRef SectionName =
765fe6060f1SDimitry Andric       unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));
7668bcb0991SDimitry Andric 
7678bcb0991SDimitry Andric   W.printString("Section", SectionName);
76804eeddc0SDimitry Andric   if (SymbolClass == XCOFF::C_FILE) {
769fe6060f1SDimitry Andric     W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
770bdd1243dSDimitry Andric                 ArrayRef(CFileLangIdClass));
771fe6060f1SDimitry Andric     W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
772bdd1243dSDimitry Andric                 ArrayRef(CFileCpuIdClass));
7738bcb0991SDimitry Andric   } else
774fe6060f1SDimitry Andric     W.printHex("Type", SymbolEntRef.getSymbolType());
7758bcb0991SDimitry Andric 
77604eeddc0SDimitry Andric   W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),
777bdd1243dSDimitry Andric               ArrayRef(SymStorageClass));
778fe6060f1SDimitry Andric   W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
7798bcb0991SDimitry Andric 
7808bcb0991SDimitry Andric   if (NumberOfAuxEntries == 0)
7818bcb0991SDimitry Andric     return;
7828bcb0991SDimitry Andric 
78304eeddc0SDimitry Andric   auto checkNumOfAux = [=] {
78404eeddc0SDimitry Andric     if (NumberOfAuxEntries > 1)
78504eeddc0SDimitry Andric       reportUniqueWarning("the " +
78604eeddc0SDimitry Andric                           enumToString(static_cast<uint8_t>(SymbolClass),
787bdd1243dSDimitry Andric                                        ArrayRef(SymStorageClass)) +
78804eeddc0SDimitry Andric                           " symbol at index " + Twine(SymbolIdx) +
78904eeddc0SDimitry Andric                           " should not have more than 1 "
79004eeddc0SDimitry Andric                           "auxiliary entry");
79104eeddc0SDimitry Andric   };
79204eeddc0SDimitry Andric 
79304eeddc0SDimitry Andric   switch (SymbolClass) {
7948bcb0991SDimitry Andric   case XCOFF::C_FILE:
7958bcb0991SDimitry Andric     // If the symbol is C_FILE and has auxiliary entries...
796fe6060f1SDimitry Andric     for (int I = 1; I <= NumberOfAuxEntries; I++) {
797fe6060f1SDimitry Andric       uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
798fe6060f1SDimitry Andric           SymbolEntRef.getEntryAddress(), I);
799fe6060f1SDimitry Andric 
800fe6060f1SDimitry Andric       if (Obj.is64Bit() &&
801fe6060f1SDimitry Andric           *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {
80204eeddc0SDimitry Andric         printUnexpectedRawAuxEnt(W, AuxAddress);
803fe6060f1SDimitry Andric         continue;
804fe6060f1SDimitry Andric       }
805fe6060f1SDimitry Andric 
8068bcb0991SDimitry Andric       const XCOFFFileAuxEnt *FileAuxEntPtr =
80704eeddc0SDimitry Andric           getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);
8088bcb0991SDimitry Andric       printFileAuxEnt(FileAuxEntPtr);
8098bcb0991SDimitry Andric     }
8108bcb0991SDimitry Andric     break;
8118bcb0991SDimitry Andric   case XCOFF::C_EXT:
8128bcb0991SDimitry Andric   case XCOFF::C_WEAKEXT:
813fe6060f1SDimitry Andric   case XCOFF::C_HIDEXT: {
81404eeddc0SDimitry Andric     // For 32-bit objects, print the function auxiliary symbol table entry. The
81504eeddc0SDimitry Andric     // last one must be a CSECT auxiliary entry.
81604eeddc0SDimitry Andric     // For 64-bit objects, both a function auxiliary entry and an exception
81704eeddc0SDimitry Andric     // auxiliary entry may appear, print them in the loop and skip printing the
81804eeddc0SDimitry Andric     // CSECT auxiliary entry, which will be printed outside the loop.
819fe6060f1SDimitry Andric     for (int I = 1; I <= NumberOfAuxEntries; I++) {
820bdd1243dSDimitry Andric       if (I == NumberOfAuxEntries && !Obj.is64Bit())
821fe6060f1SDimitry Andric         break;
822fe6060f1SDimitry Andric 
823fe6060f1SDimitry Andric       uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
824fe6060f1SDimitry Andric           SymbolEntRef.getEntryAddress(), I);
825fe6060f1SDimitry Andric 
82604eeddc0SDimitry Andric       if (Obj.is64Bit()) {
82704eeddc0SDimitry Andric         XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);
82804eeddc0SDimitry Andric         if (Type == XCOFF::SymbolAuxType::AUX_CSECT)
82904eeddc0SDimitry Andric           continue;
83004eeddc0SDimitry Andric         if (Type == XCOFF::SymbolAuxType::AUX_FCN) {
83104eeddc0SDimitry Andric           const XCOFFFunctionAuxEnt64 *AuxEntPtr =
83204eeddc0SDimitry Andric               getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);
83304eeddc0SDimitry Andric           printFunctionAuxEnt(AuxEntPtr);
83404eeddc0SDimitry Andric         } else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) {
83504eeddc0SDimitry Andric           const XCOFFExceptionAuxEnt *AuxEntPtr =
83604eeddc0SDimitry Andric               getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);
83704eeddc0SDimitry Andric           printExceptionAuxEnt(AuxEntPtr);
83804eeddc0SDimitry Andric         } else {
83904eeddc0SDimitry Andric           printUnexpectedRawAuxEnt(W, AuxAddress);
84004eeddc0SDimitry Andric         }
84104eeddc0SDimitry Andric       } else {
84204eeddc0SDimitry Andric         const XCOFFFunctionAuxEnt32 *AuxEntPtr =
84304eeddc0SDimitry Andric             getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);
84404eeddc0SDimitry Andric         printFunctionAuxEnt(AuxEntPtr);
84504eeddc0SDimitry Andric       }
8468bcb0991SDimitry Andric     }
8478bcb0991SDimitry Andric 
84804eeddc0SDimitry Andric     // Print the CSECT auxiliary entry.
849fe6060f1SDimitry Andric     auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
850fe6060f1SDimitry Andric     if (!ErrOrCsectAuxRef)
851fe6060f1SDimitry Andric       reportUniqueWarning(ErrOrCsectAuxRef.takeError());
852fe6060f1SDimitry Andric     else
853fe6060f1SDimitry Andric       printCsectAuxEnt(*ErrOrCsectAuxRef);
854fe6060f1SDimitry Andric 
8558bcb0991SDimitry Andric     break;
856fe6060f1SDimitry Andric   }
85704eeddc0SDimitry Andric   case XCOFF::C_STAT: {
85804eeddc0SDimitry Andric     checkNumOfAux();
8598bcb0991SDimitry Andric 
86004eeddc0SDimitry Andric     const XCOFFSectAuxEntForStat *StatAuxEntPtr =
86104eeddc0SDimitry Andric         getAuxEntPtr<XCOFFSectAuxEntForStat>(
862fe6060f1SDimitry Andric             XCOFFObjectFile::getAdvancedSymbolEntryAddress(
863fe6060f1SDimitry Andric                 SymbolEntRef.getEntryAddress(), 1));
8648bcb0991SDimitry Andric     printSectAuxEntForStat(StatAuxEntPtr);
8658bcb0991SDimitry Andric     break;
86604eeddc0SDimitry Andric   }
86704eeddc0SDimitry Andric   case XCOFF::C_DWARF: {
86804eeddc0SDimitry Andric     checkNumOfAux();
86904eeddc0SDimitry Andric 
87004eeddc0SDimitry Andric     uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
87104eeddc0SDimitry Andric         SymbolEntRef.getEntryAddress(), 1);
87204eeddc0SDimitry Andric 
87304eeddc0SDimitry Andric     if (Obj.is64Bit()) {
87404eeddc0SDimitry Andric       const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =
87504eeddc0SDimitry Andric           getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);
87604eeddc0SDimitry Andric       printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr);
87704eeddc0SDimitry Andric     } else {
87804eeddc0SDimitry Andric       const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =
87904eeddc0SDimitry Andric           getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);
88004eeddc0SDimitry Andric       printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr);
88104eeddc0SDimitry Andric     }
8828bcb0991SDimitry Andric     break;
88304eeddc0SDimitry Andric   }
88404eeddc0SDimitry Andric   case XCOFF::C_BLOCK:
88504eeddc0SDimitry Andric   case XCOFF::C_FCN: {
88604eeddc0SDimitry Andric     checkNumOfAux();
88704eeddc0SDimitry Andric 
88804eeddc0SDimitry Andric     uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
88904eeddc0SDimitry Andric         SymbolEntRef.getEntryAddress(), 1);
89004eeddc0SDimitry Andric 
89104eeddc0SDimitry Andric     if (Obj.is64Bit()) {
89204eeddc0SDimitry Andric       const XCOFFBlockAuxEnt64 *AuxEntPtr =
89304eeddc0SDimitry Andric           getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);
89404eeddc0SDimitry Andric       printBlockAuxEnt(AuxEntPtr);
89504eeddc0SDimitry Andric     } else {
89604eeddc0SDimitry Andric       const XCOFFBlockAuxEnt32 *AuxEntPtr =
89704eeddc0SDimitry Andric           getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);
89804eeddc0SDimitry Andric       printBlockAuxEnt(AuxEntPtr);
89904eeddc0SDimitry Andric     }
90004eeddc0SDimitry Andric     break;
90104eeddc0SDimitry Andric   }
9028bcb0991SDimitry Andric   default:
9038bcb0991SDimitry Andric     for (int i = 1; i <= NumberOfAuxEntries; i++) {
90404eeddc0SDimitry Andric       printUnexpectedRawAuxEnt(W,
905fe6060f1SDimitry Andric                                XCOFFObjectFile::getAdvancedSymbolEntryAddress(
90604eeddc0SDimitry Andric                                    SymbolEntRef.getEntryAddress(), i));
9078bcb0991SDimitry Andric     }
9088bcb0991SDimitry Andric     break;
9098bcb0991SDimitry Andric   }
9100b57cec5SDimitry Andric }
9110b57cec5SDimitry Andric 
printSymbols(bool)9125f757f3fSDimitry Andric void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) {
9138bcb0991SDimitry Andric   ListScope Group(W, "Symbols");
9148bcb0991SDimitry Andric   for (const SymbolRef &S : Obj.symbols())
9158bcb0991SDimitry Andric     printSymbol(S);
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric 
printStringTable()918fe6060f1SDimitry Andric void XCOFFDumper::printStringTable() {
919fe6060f1SDimitry Andric   DictScope DS(W, "StringTable");
920fe6060f1SDimitry Andric   StringRef StrTable = Obj.getStringTable();
921349cc55cSDimitry Andric   uint32_t StrTabSize = StrTable.size();
922349cc55cSDimitry Andric   W.printNumber("Length", StrTabSize);
923349cc55cSDimitry Andric   // Print strings from the fifth byte, since the first four bytes contain the
924349cc55cSDimitry Andric   // length (in bytes) of the string table (including the length field).
925349cc55cSDimitry Andric   if (StrTabSize > 4)
926349cc55cSDimitry Andric     printAsStringList(StrTable, 4);
927fe6060f1SDimitry Andric }
928fe6060f1SDimitry Andric 
printDynamicSymbols()9290b57cec5SDimitry Andric void XCOFFDumper::printDynamicSymbols() {
9300b57cec5SDimitry Andric   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
9310b57cec5SDimitry Andric }
9320b57cec5SDimitry Andric 
printUnwindInfo()9330b57cec5SDimitry Andric void XCOFFDumper::printUnwindInfo() {
9340b57cec5SDimitry Andric   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric 
printStackMap() const9370b57cec5SDimitry Andric void XCOFFDumper::printStackMap() const {
9380b57cec5SDimitry Andric   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
9390b57cec5SDimitry Andric }
9400b57cec5SDimitry Andric 
printNeededLibraries()9410b57cec5SDimitry Andric void XCOFFDumper::printNeededLibraries() {
942349cc55cSDimitry Andric   ListScope D(W, "NeededLibraries");
943349cc55cSDimitry Andric   auto ImportFilesOrError = Obj.getImportFileTable();
944349cc55cSDimitry Andric   if (!ImportFilesOrError) {
945349cc55cSDimitry Andric     reportUniqueWarning(ImportFilesOrError.takeError());
946349cc55cSDimitry Andric     return;
9470b57cec5SDimitry Andric   }
9480b57cec5SDimitry Andric 
949349cc55cSDimitry Andric   StringRef ImportFileTable = ImportFilesOrError.get();
950349cc55cSDimitry Andric   const char *CurrentStr = ImportFileTable.data();
951349cc55cSDimitry Andric   const char *TableEnd = ImportFileTable.end();
952349cc55cSDimitry Andric   // Default column width for names is 13 even if no names are that long.
953349cc55cSDimitry Andric   size_t BaseWidth = 13;
954349cc55cSDimitry Andric 
955349cc55cSDimitry Andric   // Get the max width of BASE columns.
956349cc55cSDimitry Andric   for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) {
957349cc55cSDimitry Andric     size_t CurrentLen = strlen(CurrentStr);
958349cc55cSDimitry Andric     CurrentStr += strlen(CurrentStr) + 1;
959349cc55cSDimitry Andric     if (StrIndex % 3 == 1)
960349cc55cSDimitry Andric       BaseWidth = std::max(BaseWidth, CurrentLen);
961349cc55cSDimitry Andric   }
962349cc55cSDimitry Andric 
963349cc55cSDimitry Andric   auto &OS = static_cast<formatted_raw_ostream &>(W.startLine());
964349cc55cSDimitry Andric   // Each entry consists of 3 strings: the path_name, base_name and
965349cc55cSDimitry Andric   // archive_member_name. The first entry is a default LIBPATH value and other
966349cc55cSDimitry Andric   // entries have no path_name. We just dump the base_name and
967349cc55cSDimitry Andric   // archive_member_name here.
968349cc55cSDimitry Andric   OS << left_justify("BASE", BaseWidth)  << " MEMBER\n";
969349cc55cSDimitry Andric   CurrentStr = ImportFileTable.data();
970349cc55cSDimitry Andric   for (size_t StrIndex = 0; CurrentStr < TableEnd;
971349cc55cSDimitry Andric        ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) {
972349cc55cSDimitry Andric     if (StrIndex >= 3 && StrIndex % 3 != 0) {
973349cc55cSDimitry Andric       if (StrIndex % 3 == 1)
974349cc55cSDimitry Andric         OS << "  " << left_justify(CurrentStr, BaseWidth) << " ";
975349cc55cSDimitry Andric       else
976349cc55cSDimitry Andric         OS << CurrentStr << "\n";
977349cc55cSDimitry Andric     }
978349cc55cSDimitry Andric   }
979349cc55cSDimitry Andric }
980349cc55cSDimitry Andric 
981349cc55cSDimitry Andric const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
9820b57cec5SDimitry Andric #define ECase(X)                                                               \
9830b57cec5SDimitry Andric   { #X, XCOFF::X }
9840b57cec5SDimitry Andric     ECase(STYP_PAD),    ECase(STYP_DWARF), ECase(STYP_TEXT),
9850b57cec5SDimitry Andric     ECase(STYP_DATA),   ECase(STYP_BSS),   ECase(STYP_EXCEPT),
9860b57cec5SDimitry Andric     ECase(STYP_INFO),   ECase(STYP_TDATA), ECase(STYP_TBSS),
9870b57cec5SDimitry Andric     ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
9880b57cec5SDimitry Andric     ECase(STYP_OVRFLO)
9890b57cec5SDimitry Andric #undef ECase
9900b57cec5SDimitry Andric };
9910b57cec5SDimitry Andric 
992*0fca6ea1SDimitry Andric const EnumEntry<XCOFF::DwarfSectionSubtypeFlags>
993*0fca6ea1SDimitry Andric     DWARFSectionSubtypeFlagsNames[] = {
994*0fca6ea1SDimitry Andric #define ECase(X)                                                               \
995*0fca6ea1SDimitry Andric   { #X, XCOFF::X }
996*0fca6ea1SDimitry Andric         ECase(SSUBTYP_DWINFO),  ECase(SSUBTYP_DWLINE),  ECase(SSUBTYP_DWPBNMS),
997*0fca6ea1SDimitry Andric         ECase(SSUBTYP_DWPBTYP), ECase(SSUBTYP_DWARNGE), ECase(SSUBTYP_DWABREV),
998*0fca6ea1SDimitry Andric         ECase(SSUBTYP_DWSTR),   ECase(SSUBTYP_DWRNGES), ECase(SSUBTYP_DWLOC),
999*0fca6ea1SDimitry Andric         ECase(SSUBTYP_DWFRAME), ECase(SSUBTYP_DWMAC)
1000*0fca6ea1SDimitry Andric #undef ECase
1001*0fca6ea1SDimitry Andric };
1002*0fca6ea1SDimitry Andric 
10030b57cec5SDimitry Andric template <typename T>
printOverflowSectionHeader(T & Sec) const10048bcb0991SDimitry Andric void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
10058bcb0991SDimitry Andric   if (Obj.is64Bit()) {
10068bcb0991SDimitry Andric     reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
10078bcb0991SDimitry Andric                                           "contain an overflow section header.",
10088bcb0991SDimitry Andric                                           object_error::parse_failed),
10098bcb0991SDimitry Andric                   Obj.getFileName());
10108bcb0991SDimitry Andric   }
10118bcb0991SDimitry Andric 
10128bcb0991SDimitry Andric   W.printString("Name", Sec.getName());
10138bcb0991SDimitry Andric   W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
10148bcb0991SDimitry Andric   W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
10158bcb0991SDimitry Andric   W.printHex("Size", Sec.SectionSize);
10168bcb0991SDimitry Andric   W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
10178bcb0991SDimitry Andric   W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
10188bcb0991SDimitry Andric   W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
10198bcb0991SDimitry Andric   W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
10208bcb0991SDimitry Andric   W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
10218bcb0991SDimitry Andric }
10228bcb0991SDimitry Andric 
10238bcb0991SDimitry Andric template <typename T>
printGenericSectionHeader(T & Sec) const10248bcb0991SDimitry Andric void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
10258bcb0991SDimitry Andric   W.printString("Name", Sec.getName());
10268bcb0991SDimitry Andric   W.printHex("PhysicalAddress", Sec.PhysicalAddress);
10278bcb0991SDimitry Andric   W.printHex("VirtualAddress", Sec.VirtualAddress);
10288bcb0991SDimitry Andric   W.printHex("Size", Sec.SectionSize);
10298bcb0991SDimitry Andric   W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
10308bcb0991SDimitry Andric   W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
10318bcb0991SDimitry Andric   W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
10328bcb0991SDimitry Andric   W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
10338bcb0991SDimitry Andric   W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
10348bcb0991SDimitry Andric }
10358bcb0991SDimitry Andric 
103681ad6265SDimitry Andric enum PrintStyle { Hex, Number };
103781ad6265SDimitry Andric template <typename T, typename V>
printAuxMemberHelper(PrintStyle Style,const char * MemberName,const T & Member,const V * AuxHeader,uint16_t AuxSize,uint16_t & PartialFieldOffset,const char * & PartialFieldName,ScopedPrinter & W)103881ad6265SDimitry Andric static void printAuxMemberHelper(PrintStyle Style, const char *MemberName,
103981ad6265SDimitry Andric                                  const T &Member, const V *AuxHeader,
104081ad6265SDimitry Andric                                  uint16_t AuxSize, uint16_t &PartialFieldOffset,
104181ad6265SDimitry Andric                                  const char *&PartialFieldName,
104281ad6265SDimitry Andric                                  ScopedPrinter &W) {
104381ad6265SDimitry Andric   ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -
104481ad6265SDimitry Andric                      reinterpret_cast<const char *>(AuxHeader);
104581ad6265SDimitry Andric   if (Offset + sizeof(Member) <= AuxSize)
104681ad6265SDimitry Andric     Style == Hex ? W.printHex(MemberName, Member)
104781ad6265SDimitry Andric                  : W.printNumber(MemberName, Member);
104881ad6265SDimitry Andric   else if (Offset < AuxSize) {
104981ad6265SDimitry Andric     PartialFieldOffset = Offset;
105081ad6265SDimitry Andric     PartialFieldName = MemberName;
105181ad6265SDimitry Andric   }
105281ad6265SDimitry Andric }
105381ad6265SDimitry Andric 
105481ad6265SDimitry Andric template <class T>
checkAndPrintAuxHeaderParseError(const char * PartialFieldName,uint16_t PartialFieldOffset,uint16_t AuxSize,T & AuxHeader,XCOFFDumper * Dumper)105581ad6265SDimitry Andric void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,
105681ad6265SDimitry Andric                                       uint16_t PartialFieldOffset,
105781ad6265SDimitry Andric                                       uint16_t AuxSize, T &AuxHeader,
105881ad6265SDimitry Andric                                       XCOFFDumper *Dumper) {
105981ad6265SDimitry Andric   if (PartialFieldOffset < AuxSize) {
106081ad6265SDimitry Andric     Dumper->reportUniqueWarning(Twine("only partial field for ") +
106181ad6265SDimitry Andric                                 PartialFieldName + " at offset (" +
106281ad6265SDimitry Andric                                 Twine(PartialFieldOffset) + ")");
106381ad6265SDimitry Andric     Dumper->getScopedPrinter().printBinary(
106481ad6265SDimitry Andric         "Raw data", "",
106581ad6265SDimitry Andric         ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
106681ad6265SDimitry Andric                               PartialFieldOffset,
106781ad6265SDimitry Andric                           AuxSize - PartialFieldOffset));
106881ad6265SDimitry Andric   } else if (sizeof(AuxHeader) < AuxSize)
106981ad6265SDimitry Andric     Dumper->getScopedPrinter().printBinary(
107081ad6265SDimitry Andric         "Extra raw data", "",
107181ad6265SDimitry Andric         ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
107281ad6265SDimitry Andric                               sizeof(AuxHeader),
107381ad6265SDimitry Andric                           AuxSize - sizeof(AuxHeader)));
107481ad6265SDimitry Andric }
107581ad6265SDimitry Andric 
printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 * AuxHeader)1076349cc55cSDimitry Andric void XCOFFDumper::printAuxiliaryHeader(
1077349cc55cSDimitry Andric     const XCOFFAuxiliaryHeader32 *AuxHeader) {
1078349cc55cSDimitry Andric   if (AuxHeader == nullptr)
1079349cc55cSDimitry Andric     return;
1080349cc55cSDimitry Andric   uint16_t AuxSize = Obj.getOptionalHeaderSize();
1081349cc55cSDimitry Andric   uint16_t PartialFieldOffset = AuxSize;
1082349cc55cSDimitry Andric   const char *PartialFieldName = nullptr;
1083349cc55cSDimitry Andric 
108481ad6265SDimitry Andric   auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
108581ad6265SDimitry Andric                             auto &Member) {
108681ad6265SDimitry Andric     printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
108781ad6265SDimitry Andric                          PartialFieldOffset, PartialFieldName, W);
108881ad6265SDimitry Andric   };
1089349cc55cSDimitry Andric 
109081ad6265SDimitry Andric   PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
109181ad6265SDimitry Andric   PrintAuxMember(Hex, "Version", AuxHeader->Version);
109281ad6265SDimitry Andric   PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
109381ad6265SDimitry Andric   PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
109481ad6265SDimitry Andric   PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
109581ad6265SDimitry Andric   PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
109681ad6265SDimitry Andric   PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
109781ad6265SDimitry Andric   PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
109881ad6265SDimitry Andric   PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
109981ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of entryPoint",
110081ad6265SDimitry Andric                  AuxHeader->SecNumOfEntryPoint);
110181ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
110281ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
110381ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
110481ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of loader data",
110581ad6265SDimitry Andric                  AuxHeader->SecNumOfLoader);
110681ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
110781ad6265SDimitry Andric   PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
110881ad6265SDimitry Andric   PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
110981ad6265SDimitry Andric   PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
111081ad6265SDimitry Andric   PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
111181ad6265SDimitry Andric   PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
111281ad6265SDimitry Andric   PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
111381ad6265SDimitry Andric   PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
111481ad6265SDimitry Andric   PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
111581ad6265SDimitry Andric   PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
111681ad6265SDimitry Andric   PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
111781ad6265SDimitry Andric   PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
1118349cc55cSDimitry Andric   if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +
1119349cc55cSDimitry Andric           sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=
1120349cc55cSDimitry Andric       AuxSize) {
1121349cc55cSDimitry Andric     W.printHex("Flag", AuxHeader->getFlag());
1122349cc55cSDimitry Andric     W.printHex("Alignment of thread-local storage",
1123349cc55cSDimitry Andric                AuxHeader->getTDataAlignment());
1124349cc55cSDimitry Andric   }
1125349cc55cSDimitry Andric 
112681ad6265SDimitry Andric   PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
112781ad6265SDimitry Andric   PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
1128349cc55cSDimitry Andric 
112981ad6265SDimitry Andric   checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
113081ad6265SDimitry Andric                                    AuxSize, *AuxHeader, this);
1131349cc55cSDimitry Andric }
1132349cc55cSDimitry Andric 
printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 * AuxHeader)1133349cc55cSDimitry Andric void XCOFFDumper::printAuxiliaryHeader(
1134349cc55cSDimitry Andric     const XCOFFAuxiliaryHeader64 *AuxHeader) {
1135349cc55cSDimitry Andric   if (AuxHeader == nullptr)
1136349cc55cSDimitry Andric     return;
1137349cc55cSDimitry Andric   uint16_t AuxSize = Obj.getOptionalHeaderSize();
1138349cc55cSDimitry Andric   uint16_t PartialFieldOffset = AuxSize;
1139349cc55cSDimitry Andric   const char *PartialFieldName = nullptr;
1140349cc55cSDimitry Andric 
114181ad6265SDimitry Andric   auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
114281ad6265SDimitry Andric                             auto &Member) {
114381ad6265SDimitry Andric     printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
114481ad6265SDimitry Andric                          PartialFieldOffset, PartialFieldName, W);
114581ad6265SDimitry Andric   };
1146349cc55cSDimitry Andric 
114781ad6265SDimitry Andric   PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
114881ad6265SDimitry Andric   PrintAuxMember(Hex, "Version", AuxHeader->Version);
114981ad6265SDimitry Andric   PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
115081ad6265SDimitry Andric   PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
115181ad6265SDimitry Andric   PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
115281ad6265SDimitry Andric   PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
115381ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of entryPoint",
115481ad6265SDimitry Andric                  AuxHeader->SecNumOfEntryPoint);
115581ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
115681ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
115781ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
115881ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of loader data",
115981ad6265SDimitry Andric                  AuxHeader->SecNumOfLoader);
116081ad6265SDimitry Andric   PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
116181ad6265SDimitry Andric   PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
116281ad6265SDimitry Andric   PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
116381ad6265SDimitry Andric   PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
116481ad6265SDimitry Andric   PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
116581ad6265SDimitry Andric   PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
116681ad6265SDimitry Andric   PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
116781ad6265SDimitry Andric   PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
116881ad6265SDimitry Andric   PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
1169349cc55cSDimitry Andric   if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +
1170349cc55cSDimitry Andric           sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=
1171349cc55cSDimitry Andric       AuxSize) {
1172349cc55cSDimitry Andric     W.printHex("Flag", AuxHeader->getFlag());
1173349cc55cSDimitry Andric     W.printHex("Alignment of thread-local storage",
1174349cc55cSDimitry Andric                AuxHeader->getTDataAlignment());
1175349cc55cSDimitry Andric   }
117681ad6265SDimitry Andric   PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
117781ad6265SDimitry Andric   PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
117881ad6265SDimitry Andric   PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
117981ad6265SDimitry Andric   PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
118081ad6265SDimitry Andric   PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
118181ad6265SDimitry Andric   PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
118281ad6265SDimitry Andric   PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
118381ad6265SDimitry Andric   PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
118481ad6265SDimitry Andric   PrintAuxMember(Hex, "Additional flags 64-bit XCOFF", AuxHeader->XCOFF64Flag);
1185349cc55cSDimitry Andric 
118681ad6265SDimitry Andric   checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
118781ad6265SDimitry Andric                                    AuxSize, *AuxHeader, this);
1188349cc55cSDimitry Andric }
1189349cc55cSDimitry Andric 
11908bcb0991SDimitry Andric template <typename T>
printSectionHeaders(ArrayRef<T> Sections)11910b57cec5SDimitry Andric void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
11920b57cec5SDimitry Andric   ListScope Group(W, "Sections");
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric   uint16_t Index = 1;
11950b57cec5SDimitry Andric   for (const T &Sec : Sections) {
11960b57cec5SDimitry Andric     DictScope SecDS(W, "Section");
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric     W.printNumber("Index", Index++);
1199480093f4SDimitry Andric     uint16_t SectionType = Sec.getSectionType();
1200*0fca6ea1SDimitry Andric     int32_t SectionSubtype = Sec.getSectionSubtype();
12018bcb0991SDimitry Andric     switch (SectionType) {
12028bcb0991SDimitry Andric     case XCOFF::STYP_OVRFLO:
12038bcb0991SDimitry Andric       printOverflowSectionHeader(Sec);
12048bcb0991SDimitry Andric       break;
12058bcb0991SDimitry Andric     case XCOFF::STYP_LOADER:
12068bcb0991SDimitry Andric     case XCOFF::STYP_EXCEPT:
12078bcb0991SDimitry Andric     case XCOFF::STYP_TYPCHK:
12088bcb0991SDimitry Andric       // TODO The interpretation of loader, exception and type check section
12098bcb0991SDimitry Andric       // headers are different from that of generic section headers. We will
12108bcb0991SDimitry Andric       // implement them later. We interpret them as generic section headers for
12118bcb0991SDimitry Andric       // now.
12128bcb0991SDimitry Andric     default:
12138bcb0991SDimitry Andric       printGenericSectionHeader(Sec);
12148bcb0991SDimitry Andric       break;
12158bcb0991SDimitry Andric     }
1216480093f4SDimitry Andric     if (Sec.isReservedSectionType())
12178bcb0991SDimitry Andric       W.printHex("Flags", "Reserved", SectionType);
1218*0fca6ea1SDimitry Andric     else {
1219bdd1243dSDimitry Andric       W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames));
1220*0fca6ea1SDimitry Andric       if (SectionType == XCOFF::STYP_DWARF) {
1221*0fca6ea1SDimitry Andric         W.printEnum("DWARFSubType", SectionSubtype,
1222*0fca6ea1SDimitry Andric                     ArrayRef(DWARFSectionSubtypeFlagsNames));
1223*0fca6ea1SDimitry Andric       }
1224*0fca6ea1SDimitry Andric     }
12250b57cec5SDimitry Andric   }
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric   if (opts::SectionRelocations)
12280b57cec5SDimitry Andric     report_fatal_error("Dumping section relocations is unimplemented");
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric   if (opts::SectionSymbols)
12310b57cec5SDimitry Andric     report_fatal_error("Dumping symbols is unimplemented");
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   if (opts::SectionData)
12340b57cec5SDimitry Andric     report_fatal_error("Dumping section data is unimplemented");
12350b57cec5SDimitry Andric }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric namespace llvm {
1238e8d8bef9SDimitry Andric std::unique_ptr<ObjDumper>
createXCOFFDumper(const object::XCOFFObjectFile & XObj,ScopedPrinter & Writer)1239e8d8bef9SDimitry Andric createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
1240e8d8bef9SDimitry Andric   return std::make_unique<XCOFFDumper>(XObj, Writer);
12410b57cec5SDimitry Andric }
12420b57cec5SDimitry Andric } // namespace llvm
1243