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