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