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),
186 ECase(XMC_GL), ECase(XMC_XO), ECase(XMC_SV),
187 ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI),
188 ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
189 ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),
190 ECase(XMC_UA), ECase(XMC_BS), ECase(XMC_UC),
191 ECase(XMC_TL), ECase(XMC_TE)
192 #undef ECase
193 };
194
195 static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
196 #define ECase(X) \
197 { #X, XCOFF::X }
198 ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
199 #undef ECase
200 };
201
printCsectAuxEnt32(const XCOFFCsectAuxEnt32 * AuxEntPtr)202 void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
203 assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
204
205 DictScope SymDs(W, "CSECT Auxiliary Entry");
206 W.printNumber("Index",
207 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
208 if (AuxEntPtr->isLabel())
209 W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength);
210 else
211 W.printNumber("SectionLen", AuxEntPtr->SectionOrLength);
212 W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
213 W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
214 // Print out symbol alignment and type.
215 W.printNumber("SymbolAlignmentLog2", AuxEntPtr->getAlignmentLog2());
216 W.printEnum("SymbolType", AuxEntPtr->getSymbolType(),
217 makeArrayRef(CsectSymbolTypeClass));
218 W.printEnum("StorageMappingClass",
219 static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
220 makeArrayRef(CsectStorageMappingClass));
221 W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
222 W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
223 }
224
printSectAuxEntForStat(const XCOFFSectAuxEntForStat * AuxEntPtr)225 void XCOFFDumper::printSectAuxEntForStat(
226 const XCOFFSectAuxEntForStat *AuxEntPtr) {
227 assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
228
229 DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
230 W.printNumber("Index",
231 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
232 W.printNumber("SectionLength", AuxEntPtr->SectionLength);
233
234 // Unlike the corresponding fields in the section header, NumberOfRelocEnt
235 // and NumberOfLineNum do not handle values greater than 65535.
236 W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
237 W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
238 }
239
240 static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
241 #define ECase(X) \
242 { #X, XCOFF::X }
243 ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
244 ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
245 ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
246 ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
247 ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
248 ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
249 ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
250 ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
251 ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
252 ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
253 ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
254 ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
255 ECase(C_STTLS), ECase(C_EFCN)
256 #undef ECase
257 };
258
GetSymbolValueName(XCOFF::StorageClass SC)259 static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
260 switch (SC) {
261 case XCOFF::C_EXT:
262 case XCOFF::C_WEAKEXT:
263 case XCOFF::C_HIDEXT:
264 case XCOFF::C_STAT:
265 return "Value (RelocatableAddress)";
266 case XCOFF::C_FILE:
267 return "Value (SymbolTableIndex)";
268 case XCOFF::C_FCN:
269 case XCOFF::C_BLOCK:
270 case XCOFF::C_FUN:
271 case XCOFF::C_STSYM:
272 case XCOFF::C_BINCL:
273 case XCOFF::C_EINCL:
274 case XCOFF::C_INFO:
275 case XCOFF::C_BSTAT:
276 case XCOFF::C_LSYM:
277 case XCOFF::C_PSYM:
278 case XCOFF::C_RPSYM:
279 case XCOFF::C_RSYM:
280 case XCOFF::C_ECOML:
281 case XCOFF::C_DWARF:
282 assert(false && "This StorageClass for the symbol is not yet implemented.");
283 return "";
284 default:
285 return "Value";
286 }
287 }
288
289 static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
290 #define ECase(X) \
291 { #X, XCOFF::X }
292 ECase(TB_C), ECase(TB_CPLUSPLUS)
293 #undef ECase
294 };
295
296 static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
297 #define ECase(X) \
298 { #X, XCOFF::X }
299 ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
300 #undef ECase
301 };
302
printSymbol(const SymbolRef & S)303 void XCOFFDumper::printSymbol(const SymbolRef &S) {
304 if (Obj.is64Bit())
305 report_fatal_error("64-bit support is unimplemented.");
306
307 DataRefImpl SymbolDRI = S.getRawDataRefImpl();
308 const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
309
310 XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
311 uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
312
313 DictScope SymDs(W, "Symbol");
314
315 StringRef SymbolName =
316 unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
317
318 W.printNumber("Index",
319 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
320 W.printString("Name", SymbolName);
321 W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
322 SymbolEntPtr->Value);
323
324 StringRef SectionName =
325 unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
326
327 W.printString("Section", SectionName);
328 if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
329 W.printEnum("Source Language ID",
330 SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
331 makeArrayRef(CFileLangIdClass));
332 W.printEnum("CPU Version ID",
333 SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
334 makeArrayRef(CFileCpuIdClass));
335 } else
336 W.printHex("Type", SymbolEntPtr->SymbolType);
337
338 W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
339 makeArrayRef(SymStorageClass));
340 W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
341
342 if (NumberOfAuxEntries == 0)
343 return;
344
345 switch (XCOFFSymRef.getStorageClass()) {
346 case XCOFF::C_FILE:
347 // If the symbol is C_FILE and has auxiliary entries...
348 for (int i = 1; i <= NumberOfAuxEntries; i++) {
349 const XCOFFFileAuxEnt *FileAuxEntPtr =
350 reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
351 #ifndef NDEBUG
352 Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
353 #endif
354 printFileAuxEnt(FileAuxEntPtr);
355 }
356 break;
357 case XCOFF::C_EXT:
358 case XCOFF::C_WEAKEXT:
359 case XCOFF::C_HIDEXT:
360 // If the symbol is for a function, and it has more than 1 auxiliary entry,
361 // then one of them must be function auxiliary entry which we do not
362 // support yet.
363 if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
364 report_fatal_error("Function auxiliary entry printing is unimplemented.");
365
366 // If there is more than 1 auxiliary entry, instead of printing out
367 // error information, print out the raw Auxiliary entry from 1st till
368 // the last - 1. The last one must be a CSECT Auxiliary Entry.
369 for (int i = 1; i < NumberOfAuxEntries; i++) {
370 W.startLine() << "!Unexpected raw auxiliary entry data:\n";
371 W.startLine() << format_bytes(
372 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
373 XCOFF::SymbolTableEntrySize));
374 }
375
376 // The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
377 printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
378 break;
379 case XCOFF::C_STAT:
380 if (NumberOfAuxEntries > 1)
381 report_fatal_error(
382 "C_STAT symbol should not have more than 1 auxiliary entry.");
383
384 const XCOFFSectAuxEntForStat *StatAuxEntPtr;
385 StatAuxEntPtr =
386 reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
387 #ifndef NDEBUG
388 Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
389 #endif
390 printSectAuxEntForStat(StatAuxEntPtr);
391 break;
392 case XCOFF::C_DWARF:
393 case XCOFF::C_BLOCK:
394 case XCOFF::C_FCN:
395 report_fatal_error("Symbol table entry printing for this storage class "
396 "type is unimplemented.");
397 break;
398 default:
399 for (int i = 1; i <= NumberOfAuxEntries; i++) {
400 W.startLine() << "!Unexpected raw auxiliary entry data:\n";
401 W.startLine() << format_bytes(
402 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
403 XCOFF::SymbolTableEntrySize));
404 }
405 break;
406 }
407 }
408
printSymbols()409 void XCOFFDumper::printSymbols() {
410 ListScope Group(W, "Symbols");
411 for (const SymbolRef &S : Obj.symbols())
412 printSymbol(S);
413 }
414
printDynamicSymbols()415 void XCOFFDumper::printDynamicSymbols() {
416 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
417 }
418
printUnwindInfo()419 void XCOFFDumper::printUnwindInfo() {
420 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
421 }
422
printStackMap() const423 void XCOFFDumper::printStackMap() const {
424 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
425 }
426
printNeededLibraries()427 void XCOFFDumper::printNeededLibraries() {
428 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
429 }
430
431 static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
432 #define ECase(X) \
433 { #X, XCOFF::X }
434 ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT),
435 ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT),
436 ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS),
437 ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
438 ECase(STYP_OVRFLO)
439 #undef ECase
440 };
441
442 template <typename T>
printOverflowSectionHeader(T & Sec) const443 void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
444 if (Obj.is64Bit()) {
445 reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
446 "contain an overflow section header.",
447 object_error::parse_failed),
448 Obj.getFileName());
449 }
450
451 W.printString("Name", Sec.getName());
452 W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
453 W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
454 W.printHex("Size", Sec.SectionSize);
455 W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
456 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
457 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
458 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
459 W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
460 }
461
462 template <typename T>
printGenericSectionHeader(T & Sec) const463 void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
464 W.printString("Name", Sec.getName());
465 W.printHex("PhysicalAddress", Sec.PhysicalAddress);
466 W.printHex("VirtualAddress", Sec.VirtualAddress);
467 W.printHex("Size", Sec.SectionSize);
468 W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
469 W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
470 W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
471 W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
472 W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
473 }
474
475 template <typename T>
printSectionHeaders(ArrayRef<T> Sections)476 void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
477 ListScope Group(W, "Sections");
478
479 uint16_t Index = 1;
480 for (const T &Sec : Sections) {
481 DictScope SecDS(W, "Section");
482
483 W.printNumber("Index", Index++);
484 uint16_t SectionType = Sec.getSectionType();
485 switch (SectionType) {
486 case XCOFF::STYP_OVRFLO:
487 printOverflowSectionHeader(Sec);
488 break;
489 case XCOFF::STYP_LOADER:
490 case XCOFF::STYP_EXCEPT:
491 case XCOFF::STYP_TYPCHK:
492 // TODO The interpretation of loader, exception and type check section
493 // headers are different from that of generic section headers. We will
494 // implement them later. We interpret them as generic section headers for
495 // now.
496 default:
497 printGenericSectionHeader(Sec);
498 break;
499 }
500 if (Sec.isReservedSectionType())
501 W.printHex("Flags", "Reserved", SectionType);
502 else
503 W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames));
504 }
505
506 if (opts::SectionRelocations)
507 report_fatal_error("Dumping section relocations is unimplemented");
508
509 if (opts::SectionSymbols)
510 report_fatal_error("Dumping symbols is unimplemented");
511
512 if (opts::SectionData)
513 report_fatal_error("Dumping section data is unimplemented");
514 }
515
516 namespace llvm {
517 std::unique_ptr<ObjDumper>
createXCOFFDumper(const object::XCOFFObjectFile & XObj,ScopedPrinter & Writer)518 createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
519 return std::make_unique<XCOFFDumper>(XObj, Writer);
520 }
521 } // namespace llvm
522