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