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