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