xref: /netbsd-src/external/apache2/llvm/dist/llvm/tools/llvm-readobj/XCOFFDumper.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 //===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements an XCOFF specific dumper for llvm-readobj.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "ObjDumper.h"
14 #include "llvm-readobj.h"
15 #include "llvm/Object/XCOFFObjectFile.h"
16 #include "llvm/Support/ScopedPrinter.h"
17 
18 using namespace llvm;
19 using namespace object;
20 
21 namespace {
22 
23 class XCOFFDumper : public ObjDumper {
24 
25 public:
XCOFFDumper(const XCOFFObjectFile & Obj,ScopedPrinter & Writer)26   XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
27       : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}
28 
29   void printFileHeaders() override;
30   void printSectionHeaders() override;
31   void printRelocations() override;
32   void printSymbols() override;
33   void printDynamicSymbols() override;
34   void printUnwindInfo() override;
35   void printStackMap() const override;
36   void printNeededLibraries() override;
37 
38 private:
39   template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
40   template <typename T> void printGenericSectionHeader(T &Sec) const;
41   template <typename T> void printOverflowSectionHeader(T &Sec) const;
42   void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
43   void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr);
44   void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
45   void printSymbol(const SymbolRef &);
46   void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections);
47   const XCOFFObjectFile &Obj;
48 };
49 } // anonymous namespace
50 
printFileHeaders()51 void XCOFFDumper::printFileHeaders() {
52   DictScope DS(W, "FileHeader");
53   W.printHex("Magic", Obj.getMagic());
54   W.printNumber("NumberOfSections", Obj.getNumberOfSections());
55 
56   // Negative timestamp values are reserved for future use.
57   int32_t TimeStamp = Obj.getTimeStamp();
58   if (TimeStamp > 0) {
59     // This handling of the time stamp assumes that the host system's time_t is
60     // compatible with AIX time_t. If a platform is not compatible, the lit
61     // tests will let us know.
62     time_t TimeDate = TimeStamp;
63 
64     char FormattedTime[21] = {};
65     size_t BytesWritten =
66         strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
67     if (BytesWritten)
68       W.printHex("TimeStamp", FormattedTime, TimeStamp);
69     else
70       W.printHex("Timestamp", TimeStamp);
71   } else {
72     W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
73                TimeStamp);
74   }
75 
76   // The number of symbol table entries is an unsigned value in 64-bit objects
77   // and a signed value (with negative values being 'reserved') in 32-bit
78   // objects.
79   if (Obj.is64Bit()) {
80     W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
81     W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
82   } else {
83     W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
84     int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
85     if (SymTabEntries >= 0)
86       W.printNumber("SymbolTableEntries", SymTabEntries);
87     else
88       W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
89   }
90 
91   W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
92   W.printHex("Flags", Obj.getFlags());
93 
94   // TODO FIXME Add support for the auxiliary header (if any) once
95   // XCOFFObjectFile has the necessary support.
96 }
97 
printSectionHeaders()98 void XCOFFDumper::printSectionHeaders() {
99   if (Obj.is64Bit())
100     printSectionHeaders(Obj.sections64());
101   else
102     printSectionHeaders(Obj.sections32());
103 }
104 
printRelocations()105 void XCOFFDumper::printRelocations() {
106   if (Obj.is64Bit())
107     llvm_unreachable("64-bit relocation output not implemented!");
108   else
109     printRelocations(Obj.sections32());
110 }
111 
112 static const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
113 #define ECase(X)                                                               \
114   { #X, XCOFF::X }
115     ECase(R_POS),    ECase(R_RL),     ECase(R_RLA),    ECase(R_NEG),
116     ECase(R_REL),    ECase(R_TOC),    ECase(R_TRL),    ECase(R_TRLA),
117     ECase(R_GL),     ECase(R_TCL),    ECase(R_REF),    ECase(R_BA),
118     ECase(R_BR),     ECase(R_RBA),    ECase(R_RBR),    ECase(R_TLS),
119     ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
120     ECase(R_TLSML),  ECase(R_TOCU),   ECase(R_TOCL)
121 #undef ECase
122 };
123 
printRelocations(ArrayRef<XCOFFSectionHeader32> Sections)124 void XCOFFDumper::printRelocations(ArrayRef<XCOFFSectionHeader32> Sections) {
125   if (!opts::ExpandRelocs)
126     report_fatal_error("Unexpanded relocation output not implemented.");
127 
128   ListScope LS(W, "Relocations");
129   uint16_t Index = 0;
130   for (const auto &Sec : Sections) {
131     ++Index;
132     // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
133     if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
134         Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
135       continue;
136     auto Relocations = unwrapOrError(Obj.getFileName(), Obj.relocations(Sec));
137     if (Relocations.empty())
138       continue;
139 
140     W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
141                   << " {\n";
142     for (auto Reloc : Relocations) {
143       StringRef SymbolName = unwrapOrError(
144           Obj.getFileName(), Obj.getSymbolNameByIndex(Reloc.SymbolIndex));
145 
146       DictScope RelocScope(W, "Relocation");
147       W.printHex("Virtual Address", Reloc.VirtualAddress);
148       W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
149       W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
150       W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
151       W.printNumber("Length", Reloc.getRelocatedLength());
152       W.printEnum("Type", (uint8_t)Reloc.Type,
153                   makeArrayRef(RelocationTypeNameclass));
154     }
155     W.unindent();
156     W.startLine() << "}\n";
157   }
158 }
159 
160 static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
161 #define ECase(X)                                                               \
162   { #X, XCOFF::X }
163     ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
164 #undef ECase
165 };
166 
printFileAuxEnt(const XCOFFFileAuxEnt * AuxEntPtr)167 void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
168   if (Obj.is64Bit())
169     report_fatal_error(
170         "Printing for File Auxiliary Entry in 64-bit is unimplemented.");
171   StringRef FileName =
172       unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
173   DictScope SymDs(W, "File Auxiliary Entry");
174   W.printNumber("Index",
175                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
176   W.printString("Name", FileName);
177   W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
178               makeArrayRef(FileStringType));
179 }
180 
181 static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
182     {
183 #define ECase(X)                                                               \
184   { #X, XCOFF::X }
185         ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB),   ECase(XMC_GL),
186         ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),
187         ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW),   ECase(XMC_TC0),
188         ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),   ECase(XMC_UA),
189         ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL),   ECase(XMC_UL),
190         ECase(XMC_TE)
191 #undef ECase
192 };
193 
194 static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
195 #define ECase(X)                                                               \
196   { #X, XCOFF::X }
197     ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
198 #undef ECase
199 };
200 
printCsectAuxEnt32(const XCOFFCsectAuxEnt32 * AuxEntPtr)201 void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
202   assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
203 
204   DictScope SymDs(W, "CSECT Auxiliary Entry");
205   W.printNumber("Index",
206                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
207   if (AuxEntPtr->isLabel())
208     W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength);
209   else
210     W.printNumber("SectionLen", AuxEntPtr->SectionOrLength);
211   W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
212   W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
213   // Print out symbol alignment and type.
214   W.printNumber("SymbolAlignmentLog2", AuxEntPtr->getAlignmentLog2());
215   W.printEnum("SymbolType", AuxEntPtr->getSymbolType(),
216               makeArrayRef(CsectSymbolTypeClass));
217   W.printEnum("StorageMappingClass",
218               static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
219               makeArrayRef(CsectStorageMappingClass));
220   W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
221   W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
222 }
223 
printSectAuxEntForStat(const XCOFFSectAuxEntForStat * AuxEntPtr)224 void XCOFFDumper::printSectAuxEntForStat(
225     const XCOFFSectAuxEntForStat *AuxEntPtr) {
226   assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
227 
228   DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
229   W.printNumber("Index",
230                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
231   W.printNumber("SectionLength", AuxEntPtr->SectionLength);
232 
233   // Unlike the corresponding fields in the section header, NumberOfRelocEnt
234   // and NumberOfLineNum do not handle values greater than 65535.
235   W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
236   W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
237 }
238 
239 static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
240 #define ECase(X)                                                               \
241   { #X, XCOFF::X }
242     ECase(C_NULL),  ECase(C_AUTO),    ECase(C_EXT),     ECase(C_STAT),
243     ECase(C_REG),   ECase(C_EXTDEF),  ECase(C_LABEL),   ECase(C_ULABEL),
244     ECase(C_MOS),   ECase(C_ARG),     ECase(C_STRTAG),  ECase(C_MOU),
245     ECase(C_UNTAG), ECase(C_TPDEF),   ECase(C_USTATIC), ECase(C_ENTAG),
246     ECase(C_MOE),   ECase(C_REGPARM), ECase(C_FIELD),   ECase(C_BLOCK),
247     ECase(C_FCN),   ECase(C_EOS),     ECase(C_FILE),    ECase(C_LINE),
248     ECase(C_ALIAS), ECase(C_HIDDEN),  ECase(C_HIDEXT),  ECase(C_BINCL),
249     ECase(C_EINCL), ECase(C_INFO),    ECase(C_WEAKEXT), ECase(C_DWARF),
250     ECase(C_GSYM),  ECase(C_LSYM),    ECase(C_PSYM),    ECase(C_RSYM),
251     ECase(C_RPSYM), ECase(C_STSYM),   ECase(C_TCSYM),   ECase(C_BCOMM),
252     ECase(C_ECOML), ECase(C_ECOMM),   ECase(C_DECL),    ECase(C_ENTRY),
253     ECase(C_FUN),   ECase(C_BSTAT),   ECase(C_ESTAT),   ECase(C_GTLS),
254     ECase(C_STTLS), ECase(C_EFCN)
255 #undef ECase
256 };
257 
GetSymbolValueName(XCOFF::StorageClass SC)258 static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
259   switch (SC) {
260   case XCOFF::C_EXT:
261   case XCOFF::C_WEAKEXT:
262   case XCOFF::C_HIDEXT:
263   case XCOFF::C_STAT:
264     return "Value (RelocatableAddress)";
265   case XCOFF::C_FILE:
266     return "Value (SymbolTableIndex)";
267   case XCOFF::C_FCN:
268   case XCOFF::C_BLOCK:
269   case XCOFF::C_FUN:
270   case XCOFF::C_STSYM:
271   case XCOFF::C_BINCL:
272   case XCOFF::C_EINCL:
273   case XCOFF::C_INFO:
274   case XCOFF::C_BSTAT:
275   case XCOFF::C_LSYM:
276   case XCOFF::C_PSYM:
277   case XCOFF::C_RPSYM:
278   case XCOFF::C_RSYM:
279   case XCOFF::C_ECOML:
280   case XCOFF::C_DWARF:
281     assert(false && "This StorageClass for the symbol is not yet implemented.");
282     return "";
283   default:
284     return "Value";
285   }
286 }
287 
288 static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
289 #define ECase(X)                                                               \
290   { #X, XCOFF::X }
291     ECase(TB_C), ECase(TB_CPLUSPLUS)
292 #undef ECase
293 };
294 
295 static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
296 #define ECase(X)                                                               \
297   { #X, XCOFF::X }
298     ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
299 #undef ECase
300 };
301 
printSymbol(const SymbolRef & S)302 void XCOFFDumper::printSymbol(const SymbolRef &S) {
303   if (Obj.is64Bit())
304     report_fatal_error("64-bit support is unimplemented.");
305 
306   DataRefImpl SymbolDRI = S.getRawDataRefImpl();
307   const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
308 
309   XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
310   uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
311 
312   DictScope SymDs(W, "Symbol");
313 
314   StringRef SymbolName =
315       unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
316 
317   W.printNumber("Index",
318                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
319   W.printString("Name", SymbolName);
320   W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
321              SymbolEntPtr->Value);
322 
323   StringRef SectionName =
324       unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
325 
326   W.printString("Section", SectionName);
327   if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
328     W.printEnum("Source Language ID",
329                 SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
330                 makeArrayRef(CFileLangIdClass));
331     W.printEnum("CPU Version ID",
332                 SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
333                 makeArrayRef(CFileCpuIdClass));
334   } else
335     W.printHex("Type", SymbolEntPtr->SymbolType);
336 
337   W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
338               makeArrayRef(SymStorageClass));
339   W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
340 
341   if (NumberOfAuxEntries == 0)
342     return;
343 
344   switch (XCOFFSymRef.getStorageClass()) {
345   case XCOFF::C_FILE:
346     // If the symbol is C_FILE and has auxiliary entries...
347     for (int i = 1; i <= NumberOfAuxEntries; i++) {
348       const XCOFFFileAuxEnt *FileAuxEntPtr =
349           reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
350 #ifndef NDEBUG
351       Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
352 #endif
353       printFileAuxEnt(FileAuxEntPtr);
354     }
355     break;
356   case XCOFF::C_EXT:
357   case XCOFF::C_WEAKEXT:
358   case XCOFF::C_HIDEXT:
359     // If the symbol is for a function, and it has more than 1 auxiliary entry,
360     // then one of them must be function auxiliary entry which we do not
361     // support yet.
362     if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
363       report_fatal_error("Function auxiliary entry printing is unimplemented.");
364 
365     // If there is more than 1 auxiliary entry, instead of printing out
366     // error information, print out the raw Auxiliary entry from 1st till
367     // the last - 1. The last one must be a CSECT Auxiliary Entry.
368     for (int i = 1; i < NumberOfAuxEntries; i++) {
369       W.startLine() << "!Unexpected raw auxiliary entry data:\n";
370       W.startLine() << format_bytes(
371           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
372                             XCOFF::SymbolTableEntrySize));
373     }
374 
375     // The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
376     printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
377     break;
378   case XCOFF::C_STAT:
379     if (NumberOfAuxEntries > 1)
380       report_fatal_error(
381           "C_STAT symbol should not have more than 1 auxiliary entry.");
382 
383     const XCOFFSectAuxEntForStat *StatAuxEntPtr;
384     StatAuxEntPtr =
385         reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
386 #ifndef NDEBUG
387     Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
388 #endif
389     printSectAuxEntForStat(StatAuxEntPtr);
390     break;
391   case XCOFF::C_DWARF:
392   case XCOFF::C_BLOCK:
393   case XCOFF::C_FCN:
394     report_fatal_error("Symbol table entry printing for this storage class "
395                        "type is unimplemented.");
396     break;
397   default:
398     for (int i = 1; i <= NumberOfAuxEntries; i++) {
399       W.startLine() << "!Unexpected raw auxiliary entry data:\n";
400       W.startLine() << format_bytes(
401           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
402                             XCOFF::SymbolTableEntrySize));
403     }
404     break;
405   }
406 }
407 
printSymbols()408 void XCOFFDumper::printSymbols() {
409   ListScope Group(W, "Symbols");
410   for (const SymbolRef &S : Obj.symbols())
411     printSymbol(S);
412 }
413 
printDynamicSymbols()414 void XCOFFDumper::printDynamicSymbols() {
415   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
416 }
417 
printUnwindInfo()418 void XCOFFDumper::printUnwindInfo() {
419   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
420 }
421 
printStackMap() const422 void XCOFFDumper::printStackMap() const {
423   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
424 }
425 
printNeededLibraries()426 void XCOFFDumper::printNeededLibraries() {
427   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
428 }
429 
430 static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
431 #define ECase(X)                                                               \
432   { #X, XCOFF::X }
433     ECase(STYP_PAD),    ECase(STYP_DWARF), ECase(STYP_TEXT),
434     ECase(STYP_DATA),   ECase(STYP_BSS),   ECase(STYP_EXCEPT),
435     ECase(STYP_INFO),   ECase(STYP_TDATA), ECase(STYP_TBSS),
436     ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
437     ECase(STYP_OVRFLO)
438 #undef ECase
439 };
440 
441 template <typename T>
printOverflowSectionHeader(T & Sec) const442 void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
443   if (Obj.is64Bit()) {
444     reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
445                                           "contain an overflow section header.",
446                                           object_error::parse_failed),
447                   Obj.getFileName());
448   }
449 
450   W.printString("Name", Sec.getName());
451   W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
452   W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
453   W.printHex("Size", Sec.SectionSize);
454   W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
455   W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
456   W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
457   W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
458   W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
459 }
460 
461 template <typename T>
printGenericSectionHeader(T & Sec) const462 void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
463   W.printString("Name", Sec.getName());
464   W.printHex("PhysicalAddress", Sec.PhysicalAddress);
465   W.printHex("VirtualAddress", Sec.VirtualAddress);
466   W.printHex("Size", Sec.SectionSize);
467   W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
468   W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
469   W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
470   W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
471   W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
472 }
473 
474 template <typename T>
printSectionHeaders(ArrayRef<T> Sections)475 void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
476   ListScope Group(W, "Sections");
477 
478   uint16_t Index = 1;
479   for (const T &Sec : Sections) {
480     DictScope SecDS(W, "Section");
481 
482     W.printNumber("Index", Index++);
483     uint16_t SectionType = Sec.getSectionType();
484     switch (SectionType) {
485     case XCOFF::STYP_OVRFLO:
486       printOverflowSectionHeader(Sec);
487       break;
488     case XCOFF::STYP_LOADER:
489     case XCOFF::STYP_EXCEPT:
490     case XCOFF::STYP_TYPCHK:
491       // TODO The interpretation of loader, exception and type check section
492       // headers are different from that of generic section headers. We will
493       // implement them later. We interpret them as generic section headers for
494       // now.
495     default:
496       printGenericSectionHeader(Sec);
497       break;
498     }
499     if (Sec.isReservedSectionType())
500       W.printHex("Flags", "Reserved", SectionType);
501     else
502       W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames));
503   }
504 
505   if (opts::SectionRelocations)
506     report_fatal_error("Dumping section relocations is unimplemented");
507 
508   if (opts::SectionSymbols)
509     report_fatal_error("Dumping symbols is unimplemented");
510 
511   if (opts::SectionData)
512     report_fatal_error("Dumping section data is unimplemented");
513 }
514 
515 namespace llvm {
516 std::unique_ptr<ObjDumper>
createXCOFFDumper(const object::XCOFFObjectFile & XObj,ScopedPrinter & Writer)517 createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
518   return std::make_unique<XCOFFDumper>(XObj, Writer);
519 }
520 } // namespace llvm
521