1 //===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements an XCOFF specific dumper for llvm-readobj.
11 //===----------------------------------------------------------------------===//
13 #include "ObjDumper.h"
14 #include "llvm-readobj.h"
15 #include "llvm/Object/XCOFFObjectFile.h"
16 #include "llvm/Support/FormattedStream.h"
17 #include "llvm/Support/ScopedPrinter.h"
22 using namespace object
;
26 class XCOFFDumper
: public ObjDumper
{
29 XCOFFDumper(const XCOFFObjectFile
&Obj
, ScopedPrinter
&Writer
)
30 : ObjDumper(Writer
, Obj
.getFileName()), Obj(Obj
) {}
32 void printFileHeaders() override
;
33 void printAuxiliaryHeader() override
;
34 void printSectionHeaders() override
;
35 void printRelocations() override
;
36 void printSymbols(bool ExtraSymInfo
) override
;
37 void printDynamicSymbols() override
;
38 void printUnwindInfo() override
;
39 void printStackMap() const override
;
40 void printNeededLibraries() override
;
41 void printStringTable() override
;
42 void printExceptionSection() override
;
43 void printLoaderSection(bool PrintHeader
, bool PrintSymbols
,
44 bool PrintRelocations
) override
;
46 ScopedPrinter
&getScopedPrinter() const { return W
; }
49 template <typename T
> void printSectionHeaders(ArrayRef
<T
> Sections
);
50 template <typename T
> void printGenericSectionHeader(T
&Sec
) const;
51 template <typename T
> void printOverflowSectionHeader(T
&Sec
) const;
53 void printExceptionSectionEntry(const T
&ExceptionSectEnt
) const;
54 template <typename T
> void printExceptionSectionEntries() const;
55 template <typename T
> const T
*getAuxEntPtr(uintptr_t AuxAddress
);
56 void printFileAuxEnt(const XCOFFFileAuxEnt
*AuxEntPtr
);
57 void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef
);
58 void printSectAuxEntForStat(const XCOFFSectAuxEntForStat
*AuxEntPtr
);
59 void printExceptionAuxEnt(const XCOFFExceptionAuxEnt
*AuxEntPtr
);
60 void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32
*AuxEntPtr
);
61 void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64
*AuxEntPtr
);
62 void printBlockAuxEnt(const XCOFFBlockAuxEnt32
*AuxEntPtr
);
63 void printBlockAuxEnt(const XCOFFBlockAuxEnt64
*AuxEntPtr
);
64 template <typename T
> void printSectAuxEntForDWARF(const T
*AuxEntPtr
);
65 void printSymbol(const SymbolRef
&);
66 template <typename RelTy
> void printRelocation(RelTy Reloc
);
67 template <typename Shdr
, typename RelTy
>
68 void printRelocations(ArrayRef
<Shdr
> Sections
);
69 void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32
*AuxHeader
);
70 void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64
*AuxHeader
);
71 void printLoaderSectionHeader(uintptr_t LoaderSectAddr
);
72 void printLoaderSectionSymbols(uintptr_t LoaderSectAddr
);
73 template <typename LoaderSectionSymbolEntry
, typename LoaderSectionHeader
>
74 void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr
);
75 template <typename LoadSectionRelocTy
>
76 void printLoaderSectionRelocationEntry(LoadSectionRelocTy
*LoaderSecRelEntPtr
,
77 StringRef SymbolName
);
78 void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr
);
79 template <typename LoaderSectionHeader
, typename LoaderSectionSymbolEntry
,
80 typename LoaderSectionRelocationEntry
>
81 void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr
);
83 const XCOFFObjectFile
&Obj
;
84 const static int32_t FirstSymIdxOfLoaderSec
= 3;
86 } // anonymous namespace
88 void XCOFFDumper::printFileHeaders() {
89 DictScope
DS(W
, "FileHeader");
90 W
.printHex("Magic", Obj
.getMagic());
91 W
.printNumber("NumberOfSections", Obj
.getNumberOfSections());
93 // Negative timestamp values are reserved for future use.
94 int32_t TimeStamp
= Obj
.getTimeStamp();
96 // This handling of the time stamp assumes that the host system's time_t is
97 // compatible with AIX time_t. If a platform is not compatible, the lit
98 // tests will let us know.
99 time_t TimeDate
= TimeStamp
;
101 char FormattedTime
[80] = {};
103 size_t BytesFormatted
=
104 strftime(FormattedTime
, sizeof(FormattedTime
), "%F %T", gmtime(&TimeDate
));
106 W
.printHex("TimeStamp", FormattedTime
, TimeStamp
);
108 W
.printHex("Timestamp", TimeStamp
);
110 W
.printHex("TimeStamp", TimeStamp
== 0 ? "None" : "Reserved Value",
114 // The number of symbol table entries is an unsigned value in 64-bit objects
115 // and a signed value (with negative values being 'reserved') in 32-bit
118 W
.printHex("SymbolTableOffset", Obj
.getSymbolTableOffset64());
119 W
.printNumber("SymbolTableEntries", Obj
.getNumberOfSymbolTableEntries64());
121 W
.printHex("SymbolTableOffset", Obj
.getSymbolTableOffset32());
122 int32_t SymTabEntries
= Obj
.getRawNumberOfSymbolTableEntries32();
123 if (SymTabEntries
>= 0)
124 W
.printNumber("SymbolTableEntries", SymTabEntries
);
126 W
.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries
);
129 W
.printHex("OptionalHeaderSize", Obj
.getOptionalHeaderSize());
130 W
.printHex("Flags", Obj
.getFlags());
132 // TODO FIXME Add support for the auxiliary header (if any) once
133 // XCOFFObjectFile has the necessary support.
136 void XCOFFDumper::printAuxiliaryHeader() {
137 DictScope
DS(W
, "AuxiliaryHeader");
140 printAuxiliaryHeader(Obj
.auxiliaryHeader64());
142 printAuxiliaryHeader(Obj
.auxiliaryHeader32());
145 void XCOFFDumper::printSectionHeaders() {
147 printSectionHeaders(Obj
.sections64());
149 printSectionHeaders(Obj
.sections32());
152 void XCOFFDumper::printLoaderSection(bool PrintHeader
, bool PrintSymbols
,
153 bool PrintRelocations
) {
154 DictScope
DS(W
, "Loader Section");
155 Expected
<uintptr_t> LoaderSectionAddrOrError
=
156 Obj
.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER
);
157 if (!LoaderSectionAddrOrError
) {
158 reportUniqueWarning(LoaderSectionAddrOrError
.takeError());
161 uintptr_t LoaderSectionAddr
= LoaderSectionAddrOrError
.get();
163 if (LoaderSectionAddr
== 0)
168 printLoaderSectionHeader(LoaderSectionAddr
);
171 printLoaderSectionSymbols(LoaderSectionAddr
);
173 if (PrintRelocations
)
174 printLoaderSectionRelocationEntries(LoaderSectionAddr
);
179 void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr
) {
180 DictScope
DS(W
, "Loader Section Header");
182 auto PrintLoadSecHeaderCommon
= [&](const auto *LDHeader
) {
183 W
.printNumber("Version", LDHeader
->Version
);
184 W
.printNumber("NumberOfSymbolEntries", LDHeader
->NumberOfSymTabEnt
);
185 W
.printNumber("NumberOfRelocationEntries", LDHeader
->NumberOfRelTabEnt
);
186 W
.printNumber("LengthOfImportFileIDStringTable",
187 LDHeader
->LengthOfImpidStrTbl
);
188 W
.printNumber("NumberOfImportFileIDs", LDHeader
->NumberOfImpid
);
189 W
.printHex("OffsetToImportFileIDs", LDHeader
->OffsetToImpid
);
190 W
.printNumber("LengthOfStringTable", LDHeader
->LengthOfStrTbl
);
191 W
.printHex("OffsetToStringTable", LDHeader
->OffsetToStrTbl
);
195 const LoaderSectionHeader64
*LoaderSec64
=
196 reinterpret_cast<const LoaderSectionHeader64
*>(LoaderSectionAddr
);
197 PrintLoadSecHeaderCommon(LoaderSec64
);
198 W
.printHex("OffsetToSymbolTable", LoaderSec64
->OffsetToSymTbl
);
199 W
.printHex("OffsetToRelocationEntries", LoaderSec64
->OffsetToRelEnt
);
201 const LoaderSectionHeader32
*LoaderSec32
=
202 reinterpret_cast<const LoaderSectionHeader32
*>(LoaderSectionAddr
);
203 PrintLoadSecHeaderCommon(LoaderSec32
);
207 const EnumEntry
<XCOFF::StorageClass
> SymStorageClass
[] = {
210 ECase(C_NULL
), ECase(C_AUTO
), ECase(C_EXT
), ECase(C_STAT
),
211 ECase(C_REG
), ECase(C_EXTDEF
), ECase(C_LABEL
), ECase(C_ULABEL
),
212 ECase(C_MOS
), ECase(C_ARG
), ECase(C_STRTAG
), ECase(C_MOU
),
213 ECase(C_UNTAG
), ECase(C_TPDEF
), ECase(C_USTATIC
), ECase(C_ENTAG
),
214 ECase(C_MOE
), ECase(C_REGPARM
), ECase(C_FIELD
), ECase(C_BLOCK
),
215 ECase(C_FCN
), ECase(C_EOS
), ECase(C_FILE
), ECase(C_LINE
),
216 ECase(C_ALIAS
), ECase(C_HIDDEN
), ECase(C_HIDEXT
), ECase(C_BINCL
),
217 ECase(C_EINCL
), ECase(C_INFO
), ECase(C_WEAKEXT
), ECase(C_DWARF
),
218 ECase(C_GSYM
), ECase(C_LSYM
), ECase(C_PSYM
), ECase(C_RSYM
),
219 ECase(C_RPSYM
), ECase(C_STSYM
), ECase(C_TCSYM
), ECase(C_BCOMM
),
220 ECase(C_ECOML
), ECase(C_ECOMM
), ECase(C_DECL
), ECase(C_ENTRY
),
221 ECase(C_FUN
), ECase(C_BSTAT
), ECase(C_ESTAT
), ECase(C_GTLS
),
222 ECase(C_STTLS
), ECase(C_EFCN
)
226 template <typename LoaderSectionSymbolEntry
, typename LoaderSectionHeader
>
227 void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr
) {
228 const LoaderSectionHeader
*LoadSecHeader
=
229 reinterpret_cast<const LoaderSectionHeader
*>(LoaderSectionAddr
);
230 const LoaderSectionSymbolEntry
*LoadSecSymEntPtr
=
231 reinterpret_cast<LoaderSectionSymbolEntry
*>(
232 LoaderSectionAddr
+ uintptr_t(LoadSecHeader
->getOffsetToSymTbl()));
234 for (uint32_t i
= 0; i
< LoadSecHeader
->NumberOfSymTabEnt
;
235 ++i
, ++LoadSecSymEntPtr
) {
236 if (Error E
= Binary::checkOffset(
237 Obj
.getMemoryBufferRef(),
238 LoaderSectionAddr
+ uintptr_t(LoadSecHeader
->getOffsetToSymTbl()) +
239 (i
* sizeof(LoaderSectionSymbolEntry
)),
240 sizeof(LoaderSectionSymbolEntry
))) {
241 reportUniqueWarning(std::move(E
));
245 Expected
<StringRef
> SymbolNameOrErr
=
246 LoadSecSymEntPtr
->getSymbolName(LoadSecHeader
);
247 if (!SymbolNameOrErr
) {
248 reportUniqueWarning(SymbolNameOrErr
.takeError());
252 DictScope
DS(W
, "Symbol");
253 W
.printString("Name", SymbolNameOrErr
.get());
254 W
.printHex("Virtual Address", LoadSecSymEntPtr
->Value
);
255 W
.printNumber("SectionNum", LoadSecSymEntPtr
->SectionNumber
);
256 W
.printHex("SymbolType", LoadSecSymEntPtr
->SymbolType
);
257 W
.printEnum("StorageClass",
258 static_cast<uint8_t>(LoadSecSymEntPtr
->StorageClass
),
259 ArrayRef(SymStorageClass
));
260 W
.printHex("ImportFileID", LoadSecSymEntPtr
->ImportFileID
);
261 W
.printNumber("ParameterTypeCheck", LoadSecSymEntPtr
->ParameterTypeCheck
);
265 void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr
) {
266 DictScope
DS(W
, "Loader Section Symbols");
268 printLoaderSectionSymbolsHelper
<LoaderSectionSymbolEntry64
,
269 LoaderSectionHeader64
>(LoaderSectionAddr
);
271 printLoaderSectionSymbolsHelper
<LoaderSectionSymbolEntry32
,
272 LoaderSectionHeader32
>(LoaderSectionAddr
);
275 const EnumEntry
<XCOFF::RelocationType
> RelocationTypeNameclass
[] = {
278 ECase(R_POS
), ECase(R_RL
), ECase(R_RLA
), ECase(R_NEG
),
279 ECase(R_REL
), ECase(R_TOC
), ECase(R_TRL
), ECase(R_TRLA
),
280 ECase(R_GL
), ECase(R_TCL
), ECase(R_REF
), ECase(R_BA
),
281 ECase(R_BR
), ECase(R_RBA
), ECase(R_RBR
), ECase(R_TLS
),
282 ECase(R_TLS_IE
), ECase(R_TLS_LD
), ECase(R_TLS_LE
), ECase(R_TLSM
),
283 ECase(R_TLSML
), ECase(R_TOCU
), ECase(R_TOCL
)
287 // From the XCOFF specification: there are five implicit external symbols, one
288 // each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols
289 // are referenced from the relocation table entries using symbol table index
290 // values 0, 1, 2, -1, and -2, respectively.
291 static const char *getImplicitLoaderSectionSymName(int SymIndx
) {
294 return "Unkown Symbol Name";
308 template <typename LoadSectionRelocTy
>
309 void XCOFFDumper::printLoaderSectionRelocationEntry(
310 LoadSectionRelocTy
*LoaderSecRelEntPtr
, StringRef SymbolName
) {
311 uint16_t Type
= LoaderSecRelEntPtr
->Type
;
312 if (opts::ExpandRelocs
) {
313 DictScope
DS(W
, "Relocation");
314 auto IsRelocationSigned
= [](uint8_t Info
) {
315 return Info
& XCOFF::XR_SIGN_INDICATOR_MASK
;
317 auto IsFixupIndicated
= [](uint8_t Info
) {
318 return Info
& XCOFF::XR_FIXUP_INDICATOR_MASK
;
320 auto GetRelocatedLength
= [](uint8_t Info
) {
321 // The relocation encodes the bit length being relocated minus 1. Add
323 // the 1 to get the actual length being relocated.
324 return (Info
& XCOFF::XR_BIASED_LENGTH_MASK
) + 1;
327 uint8_t Info
= Type
>> 8;
328 W
.printHex("Virtual Address", LoaderSecRelEntPtr
->VirtualAddr
);
329 W
.printNumber("Symbol", SymbolName
, LoaderSecRelEntPtr
->SymbolIndex
);
330 W
.printString("IsSigned", IsRelocationSigned(Info
) ? "Yes" : "No");
331 W
.printNumber("FixupBitValue", IsFixupIndicated(Info
) ? 1 : 0);
332 W
.printNumber("Length", GetRelocatedLength(Info
));
333 W
.printEnum("Type", static_cast<uint8_t>(Type
),
334 ArrayRef(RelocationTypeNameclass
));
335 W
.printNumber("SectionNumber", LoaderSecRelEntPtr
->SectionNum
);
337 W
.startLine() << format_hex(LoaderSecRelEntPtr
->VirtualAddr
,
338 Obj
.is64Bit() ? 18 : 10)
339 << " " << format_hex(Type
, 6) << " ("
340 << XCOFF::getRelocationTypeString(
341 static_cast<XCOFF::RelocationType
>(Type
))
342 << ")" << format_decimal(LoaderSecRelEntPtr
->SectionNum
, 8)
343 << " " << SymbolName
<< " ("
344 << LoaderSecRelEntPtr
->SymbolIndex
<< ")\n";
348 template <typename LoaderSectionHeader
, typename LoaderSectionSymbolEntry
,
349 typename LoaderSectionRelocationEntry
>
350 void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(
351 uintptr_t LoaderSectionAddr
) {
352 const LoaderSectionHeader
*LoaderSec
=
353 reinterpret_cast<const LoaderSectionHeader
*>(LoaderSectionAddr
);
354 const LoaderSectionRelocationEntry
*LoaderSecRelEntPtr
=
355 reinterpret_cast<const LoaderSectionRelocationEntry
*>(
356 LoaderSectionAddr
+ uintptr_t(LoaderSec
->getOffsetToRelEnt()));
358 if (!opts::ExpandRelocs
)
359 W
.startLine() << center_justify("Vaddr", Obj
.is64Bit() ? 18 : 10)
360 << center_justify("Type", 15) << right_justify("SecNum", 8)
361 << center_justify("SymbolName (Index) ", 24) << "\n";
363 for (uint32_t i
= 0; i
< LoaderSec
->NumberOfRelTabEnt
;
364 ++i
, ++LoaderSecRelEntPtr
) {
365 StringRef SymbolName
;
366 if (LoaderSecRelEntPtr
->SymbolIndex
>= FirstSymIdxOfLoaderSec
) {
367 // Because there are implicit symbol index values (-2, -1, 0, 1, 2),
368 // LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the
369 // real symbol from the symbol table.
370 const uint64_t SymOffset
=
371 (LoaderSecRelEntPtr
->SymbolIndex
- FirstSymIdxOfLoaderSec
) *
372 sizeof(LoaderSectionSymbolEntry
);
373 const LoaderSectionSymbolEntry
*LoaderSecRelSymEntPtr
=
374 reinterpret_cast<LoaderSectionSymbolEntry
*>(
375 LoaderSectionAddr
+ uintptr_t(LoaderSec
->getOffsetToSymTbl()) +
378 Expected
<StringRef
> SymbolNameOrErr
=
379 LoaderSecRelSymEntPtr
->getSymbolName(LoaderSec
);
380 if (!SymbolNameOrErr
) {
381 reportUniqueWarning(SymbolNameOrErr
.takeError());
384 SymbolName
= SymbolNameOrErr
.get();
387 getImplicitLoaderSectionSymName(LoaderSecRelEntPtr
->SymbolIndex
);
389 printLoaderSectionRelocationEntry(LoaderSecRelEntPtr
, SymbolName
);
393 void XCOFFDumper::printLoaderSectionRelocationEntries(
394 uintptr_t LoaderSectionAddr
) {
395 DictScope
DS(W
, "Loader Section Relocations");
398 printLoaderSectionRelocationEntriesHelper
<LoaderSectionHeader64
,
399 LoaderSectionSymbolEntry64
,
400 LoaderSectionRelocationEntry64
>(
403 printLoaderSectionRelocationEntriesHelper
<LoaderSectionHeader32
,
404 LoaderSectionSymbolEntry32
,
405 LoaderSectionRelocationEntry32
>(
409 template <typename T
>
410 void XCOFFDumper::printExceptionSectionEntry(const T
&ExceptionSectEnt
) const {
411 if (ExceptionSectEnt
.getReason())
412 W
.printHex("Trap Instr Addr", ExceptionSectEnt
.getTrapInstAddr());
414 uint32_t SymIdx
= ExceptionSectEnt
.getSymbolIndex();
415 Expected
<StringRef
> ErrOrSymbolName
= Obj
.getSymbolNameByIndex(SymIdx
);
416 if (Error E
= ErrOrSymbolName
.takeError()) {
417 reportUniqueWarning(std::move(E
));
420 StringRef SymName
= *ErrOrSymbolName
;
422 W
.printNumber("Symbol", SymName
, SymIdx
);
424 W
.printNumber("LangID", ExceptionSectEnt
.getLangID());
425 W
.printNumber("Reason", ExceptionSectEnt
.getReason());
428 template <typename T
> void XCOFFDumper::printExceptionSectionEntries() const {
429 Expected
<ArrayRef
<T
>> ExceptSectEntsOrErr
= Obj
.getExceptionEntries
<T
>();
430 if (Error E
= ExceptSectEntsOrErr
.takeError()) {
431 reportUniqueWarning(std::move(E
));
434 ArrayRef
<T
> ExceptSectEnts
= *ExceptSectEntsOrErr
;
436 DictScope
DS(W
, "Exception section");
437 if (ExceptSectEnts
.empty())
439 for (auto &Ent
: ExceptSectEnts
)
440 printExceptionSectionEntry(Ent
);
443 void XCOFFDumper::printExceptionSection() {
445 printExceptionSectionEntries
<ExceptionSectionEntry64
>();
447 printExceptionSectionEntries
<ExceptionSectionEntry32
>();
450 void XCOFFDumper::printRelocations() {
452 printRelocations
<XCOFFSectionHeader64
, XCOFFRelocation64
>(Obj
.sections64());
454 printRelocations
<XCOFFSectionHeader32
, XCOFFRelocation32
>(Obj
.sections32());
457 template <typename RelTy
> void XCOFFDumper::printRelocation(RelTy Reloc
) {
458 Expected
<StringRef
> ErrOrSymbolName
=
459 Obj
.getSymbolNameByIndex(Reloc
.SymbolIndex
);
460 if (Error E
= ErrOrSymbolName
.takeError()) {
461 reportUniqueWarning(std::move(E
));
464 StringRef SymbolName
= *ErrOrSymbolName
;
465 StringRef RelocName
= XCOFF::getRelocationTypeString(Reloc
.Type
);
466 if (opts::ExpandRelocs
) {
467 DictScope
Group(W
, "Relocation");
468 W
.printHex("Virtual Address", Reloc
.VirtualAddress
);
469 W
.printNumber("Symbol", SymbolName
, Reloc
.SymbolIndex
);
470 W
.printString("IsSigned", Reloc
.isRelocationSigned() ? "Yes" : "No");
471 W
.printNumber("FixupBitValue", Reloc
.isFixupIndicated() ? 1 : 0);
472 W
.printNumber("Length", Reloc
.getRelocatedLength());
473 W
.printEnum("Type", (uint8_t)Reloc
.Type
, ArrayRef(RelocationTypeNameclass
));
475 raw_ostream
&OS
= W
.startLine();
476 OS
<< W
.hex(Reloc
.VirtualAddress
) << " " << RelocName
<< " " << SymbolName
477 << "(" << Reloc
.SymbolIndex
<< ") " << W
.hex(Reloc
.Info
) << "\n";
481 template <typename Shdr
, typename RelTy
>
482 void XCOFFDumper::printRelocations(ArrayRef
<Shdr
> Sections
) {
483 ListScope
LS(W
, "Relocations");
485 for (const Shdr
&Sec
: Sections
) {
487 // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
488 if (Sec
.Flags
!= XCOFF::STYP_TEXT
&& Sec
.Flags
!= XCOFF::STYP_DATA
&&
489 Sec
.Flags
!= XCOFF::STYP_TDATA
&& Sec
.Flags
!= XCOFF::STYP_DWARF
)
491 Expected
<ArrayRef
<RelTy
>> ErrOrRelocations
= Obj
.relocations
<Shdr
, RelTy
>(Sec
);
492 if (Error E
= ErrOrRelocations
.takeError()) {
493 reportUniqueWarning(std::move(E
));
497 const ArrayRef
<RelTy
> Relocations
= *ErrOrRelocations
;
498 if (Relocations
.empty())
501 W
.startLine() << "Section (index: " << Index
<< ") " << Sec
.getName()
505 for (const RelTy Reloc
: Relocations
)
506 printRelocation(Reloc
);
509 W
.startLine() << "}\n";
513 const EnumEntry
<XCOFF::CFileStringType
> FileStringType
[] = {
516 ECase(XFT_FN
), ECase(XFT_CT
), ECase(XFT_CV
), ECase(XFT_CD
)
520 const EnumEntry
<XCOFF::SymbolAuxType
> SymAuxType
[] = {
523 ECase(AUX_EXCEPT
), ECase(AUX_FCN
), ECase(AUX_SYM
), ECase(AUX_FILE
),
524 ECase(AUX_CSECT
), ECase(AUX_SECT
)
528 void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt
*AuxEntPtr
) {
529 assert((!Obj
.is64Bit() || AuxEntPtr
->AuxType
== XCOFF::AUX_FILE
) &&
530 "Mismatched auxiliary type!");
532 unwrapOrError(Obj
.getFileName(), Obj
.getCFileName(AuxEntPtr
));
533 DictScope
SymDs(W
, "File Auxiliary Entry");
534 W
.printNumber("Index",
535 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
536 W
.printString("Name", FileName
);
537 W
.printEnum("Type", static_cast<uint8_t>(AuxEntPtr
->Type
),
538 ArrayRef(FileStringType
));
540 W
.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr
->AuxType
),
541 ArrayRef(SymAuxType
));
545 static const EnumEntry
<XCOFF::StorageMappingClass
> CsectStorageMappingClass
[] =
549 ECase(XMC_PR
), ECase(XMC_RO
), ECase(XMC_DB
), ECase(XMC_GL
),
550 ECase(XMC_XO
), ECase(XMC_SV
), ECase(XMC_SV64
), ECase(XMC_SV3264
),
551 ECase(XMC_TI
), ECase(XMC_TB
), ECase(XMC_RW
), ECase(XMC_TC0
),
552 ECase(XMC_TC
), ECase(XMC_TD
), ECase(XMC_DS
), ECase(XMC_UA
),
553 ECase(XMC_BS
), ECase(XMC_UC
), ECase(XMC_TL
), ECase(XMC_UL
),
558 const EnumEntry
<XCOFF::SymbolType
> CsectSymbolTypeClass
[] = {
561 ECase(XTY_ER
), ECase(XTY_SD
), ECase(XTY_LD
), ECase(XTY_CM
)
565 void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef
) {
566 assert((!Obj
.is64Bit() || AuxEntRef
.getAuxType64() == XCOFF::AUX_CSECT
) &&
567 "Mismatched auxiliary type!");
569 DictScope
SymDs(W
, "CSECT Auxiliary Entry");
570 W
.printNumber("Index", Obj
.getSymbolIndex(AuxEntRef
.getEntryAddress()));
571 W
.printNumber(AuxEntRef
.isLabel() ? "ContainingCsectSymbolIndex"
573 AuxEntRef
.getSectionOrLength());
574 W
.printHex("ParameterHashIndex", AuxEntRef
.getParameterHashIndex());
575 W
.printHex("TypeChkSectNum", AuxEntRef
.getTypeChkSectNum());
576 // Print out symbol alignment and type.
577 W
.printNumber("SymbolAlignmentLog2", AuxEntRef
.getAlignmentLog2());
578 W
.printEnum("SymbolType", AuxEntRef
.getSymbolType(),
579 ArrayRef(CsectSymbolTypeClass
));
580 W
.printEnum("StorageMappingClass",
581 static_cast<uint8_t>(AuxEntRef
.getStorageMappingClass()),
582 ArrayRef(CsectStorageMappingClass
));
585 W
.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT
),
586 ArrayRef(SymAuxType
));
588 W
.printHex("StabInfoIndex", AuxEntRef
.getStabInfoIndex32());
589 W
.printHex("StabSectNum", AuxEntRef
.getStabSectNum32());
593 void XCOFFDumper::printSectAuxEntForStat(
594 const XCOFFSectAuxEntForStat
*AuxEntPtr
) {
595 assert(!Obj
.is64Bit() && "32-bit interface called on 64-bit object file.");
597 DictScope
SymDs(W
, "Sect Auxiliary Entry For Stat");
598 W
.printNumber("Index",
599 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
600 W
.printNumber("SectionLength", AuxEntPtr
->SectionLength
);
602 // Unlike the corresponding fields in the section header, NumberOfRelocEnt
603 // and NumberOfLineNum do not handle values greater than 65535.
604 W
.printNumber("NumberOfRelocEnt", AuxEntPtr
->NumberOfRelocEnt
);
605 W
.printNumber("NumberOfLineNum", AuxEntPtr
->NumberOfLineNum
);
608 void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt
*AuxEntPtr
) {
609 assert(Obj
.is64Bit() && "64-bit interface called on 32-bit object file.");
611 DictScope
SymDs(W
, "Exception Auxiliary Entry");
612 W
.printNumber("Index",
613 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
614 W
.printHex("OffsetToExceptionTable", AuxEntPtr
->OffsetToExceptionTbl
);
615 W
.printHex("SizeOfFunction", AuxEntPtr
->SizeOfFunction
);
616 W
.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr
->SymIdxOfNextBeyond
);
617 W
.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr
->AuxType
),
618 ArrayRef(SymAuxType
));
621 void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32
*AuxEntPtr
) {
622 assert(!Obj
.is64Bit() && "32-bit interface called on 64-bit object file.");
624 DictScope
SymDs(W
, "Function Auxiliary Entry");
625 W
.printNumber("Index",
626 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
627 W
.printHex("OffsetToExceptionTable", AuxEntPtr
->OffsetToExceptionTbl
);
628 W
.printHex("SizeOfFunction", AuxEntPtr
->SizeOfFunction
);
629 W
.printHex("PointerToLineNum", AuxEntPtr
->PtrToLineNum
);
630 W
.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr
->SymIdxOfNextBeyond
);
633 void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64
*AuxEntPtr
) {
634 assert(Obj
.is64Bit() && "64-bit interface called on 32-bit object file.");
636 DictScope
SymDs(W
, "Function Auxiliary Entry");
637 W
.printNumber("Index",
638 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
639 W
.printHex("SizeOfFunction", AuxEntPtr
->SizeOfFunction
);
640 W
.printHex("PointerToLineNum", AuxEntPtr
->PtrToLineNum
);
641 W
.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr
->SymIdxOfNextBeyond
);
642 W
.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr
->AuxType
),
643 ArrayRef(SymAuxType
));
646 void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32
*AuxEntPtr
) {
647 assert(!Obj
.is64Bit() && "32-bit interface called on 64-bit object file.");
649 DictScope
SymDs(W
, "Block Auxiliary Entry");
650 W
.printNumber("Index",
651 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
652 W
.printHex("LineNumber (High 2 Bytes)", AuxEntPtr
->LineNumHi
);
653 W
.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr
->LineNumLo
);
656 void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64
*AuxEntPtr
) {
657 assert(Obj
.is64Bit() && "64-bit interface called on 32-bit object file.");
659 DictScope
SymDs(W
, "Block Auxiliary Entry");
660 W
.printNumber("Index",
661 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
662 W
.printHex("LineNumber", AuxEntPtr
->LineNum
);
663 W
.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr
->AuxType
),
664 ArrayRef(SymAuxType
));
667 template <typename T
>
668 void XCOFFDumper::printSectAuxEntForDWARF(const T
*AuxEntPtr
) {
669 DictScope
SymDs(W
, "Sect Auxiliary Entry For DWARF");
670 W
.printNumber("Index",
671 Obj
.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr
)));
672 W
.printHex("LengthOfSectionPortion", AuxEntPtr
->LengthOfSectionPortion
);
673 W
.printNumber("NumberOfRelocEntries", AuxEntPtr
->NumberOfRelocEnt
);
675 W
.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT
),
676 ArrayRef(SymAuxType
));
679 static StringRef
GetSymbolValueName(XCOFF::StorageClass SC
) {
682 case XCOFF::C_WEAKEXT
:
683 case XCOFF::C_HIDEXT
:
687 return "Value (RelocatableAddress)";
689 return "Value (SymbolTableIndex)";
691 return "Value (OffsetInDWARF)";
703 assert(false && "This StorageClass for the symbol is not yet implemented.");
710 const EnumEntry
<XCOFF::CFileLangId
> CFileLangIdClass
[] = {
713 ECase(TB_C
), ECase(TB_Fortran
), ECase(TB_CPLUSPLUS
)
717 const EnumEntry
<XCOFF::CFileCpuId
> CFileCpuIdClass
[] = {
720 ECase(TCPU_PPC64
), ECase(TCPU_COM
), ECase(TCPU_970
)
724 template <typename T
> const T
*XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress
) {
725 const T
*AuxEntPtr
= reinterpret_cast<const T
*>(AuxAddress
);
726 Obj
.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr
));
730 static void printUnexpectedRawAuxEnt(ScopedPrinter
&W
, uintptr_t AuxAddress
) {
731 W
.startLine() << "!Unexpected raw auxiliary entry data:\n";
732 W
.startLine() << format_bytes(
734 reinterpret_cast<const uint8_t *>(AuxAddress
),
735 XCOFF::SymbolTableEntrySize
),
736 std::nullopt
, XCOFF::SymbolTableEntrySize
)
740 void XCOFFDumper::printSymbol(const SymbolRef
&S
) {
741 DataRefImpl SymbolDRI
= S
.getRawDataRefImpl();
742 XCOFFSymbolRef SymbolEntRef
= Obj
.toSymbolRef(SymbolDRI
);
744 uint8_t NumberOfAuxEntries
= SymbolEntRef
.getNumberOfAuxEntries();
746 DictScope
SymDs(W
, "Symbol");
748 StringRef SymbolName
=
749 unwrapOrError(Obj
.getFileName(), SymbolEntRef
.getName());
751 uint32_t SymbolIdx
= Obj
.getSymbolIndex(SymbolEntRef
.getEntryAddress());
752 XCOFF::StorageClass SymbolClass
= SymbolEntRef
.getStorageClass();
754 W
.printNumber("Index", SymbolIdx
);
755 W
.printString("Name", SymbolName
);
756 W
.printHex(GetSymbolValueName(SymbolClass
), SymbolEntRef
.getValue());
758 StringRef SectionName
=
759 unwrapOrError(Obj
.getFileName(), Obj
.getSymbolSectionName(SymbolEntRef
));
761 W
.printString("Section", SectionName
);
762 if (SymbolClass
== XCOFF::C_FILE
) {
763 W
.printEnum("Source Language ID", SymbolEntRef
.getLanguageIdForCFile(),
764 ArrayRef(CFileLangIdClass
));
765 W
.printEnum("CPU Version ID", SymbolEntRef
.getCPUTypeIddForCFile(),
766 ArrayRef(CFileCpuIdClass
));
768 W
.printHex("Type", SymbolEntRef
.getSymbolType());
770 W
.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass
),
771 ArrayRef(SymStorageClass
));
772 W
.printNumber("NumberOfAuxEntries", NumberOfAuxEntries
);
774 if (NumberOfAuxEntries
== 0)
777 auto checkNumOfAux
= [=] {
778 if (NumberOfAuxEntries
> 1)
779 reportUniqueWarning("the " +
780 enumToString(static_cast<uint8_t>(SymbolClass
),
781 ArrayRef(SymStorageClass
)) +
782 " symbol at index " + Twine(SymbolIdx
) +
783 " should not have more than 1 "
787 switch (SymbolClass
) {
789 // If the symbol is C_FILE and has auxiliary entries...
790 for (int I
= 1; I
<= NumberOfAuxEntries
; I
++) {
791 uintptr_t AuxAddress
= XCOFFObjectFile::getAdvancedSymbolEntryAddress(
792 SymbolEntRef
.getEntryAddress(), I
);
795 *Obj
.getSymbolAuxType(AuxAddress
) != XCOFF::SymbolAuxType::AUX_FILE
) {
796 printUnexpectedRawAuxEnt(W
, AuxAddress
);
800 const XCOFFFileAuxEnt
*FileAuxEntPtr
=
801 getAuxEntPtr
<XCOFFFileAuxEnt
>(AuxAddress
);
802 printFileAuxEnt(FileAuxEntPtr
);
806 case XCOFF::C_WEAKEXT
:
807 case XCOFF::C_HIDEXT
: {
808 // For 32-bit objects, print the function auxiliary symbol table entry. The
809 // last one must be a CSECT auxiliary entry.
810 // For 64-bit objects, both a function auxiliary entry and an exception
811 // auxiliary entry may appear, print them in the loop and skip printing the
812 // CSECT auxiliary entry, which will be printed outside the loop.
813 for (int I
= 1; I
<= NumberOfAuxEntries
; I
++) {
814 if (I
== NumberOfAuxEntries
&& !Obj
.is64Bit())
817 uintptr_t AuxAddress
= XCOFFObjectFile::getAdvancedSymbolEntryAddress(
818 SymbolEntRef
.getEntryAddress(), I
);
821 XCOFF::SymbolAuxType Type
= *Obj
.getSymbolAuxType(AuxAddress
);
822 if (Type
== XCOFF::SymbolAuxType::AUX_CSECT
)
824 if (Type
== XCOFF::SymbolAuxType::AUX_FCN
) {
825 const XCOFFFunctionAuxEnt64
*AuxEntPtr
=
826 getAuxEntPtr
<XCOFFFunctionAuxEnt64
>(AuxAddress
);
827 printFunctionAuxEnt(AuxEntPtr
);
828 } else if (Type
== XCOFF::SymbolAuxType::AUX_EXCEPT
) {
829 const XCOFFExceptionAuxEnt
*AuxEntPtr
=
830 getAuxEntPtr
<XCOFFExceptionAuxEnt
>(AuxAddress
);
831 printExceptionAuxEnt(AuxEntPtr
);
833 printUnexpectedRawAuxEnt(W
, AuxAddress
);
836 const XCOFFFunctionAuxEnt32
*AuxEntPtr
=
837 getAuxEntPtr
<XCOFFFunctionAuxEnt32
>(AuxAddress
);
838 printFunctionAuxEnt(AuxEntPtr
);
842 // Print the CSECT auxiliary entry.
843 auto ErrOrCsectAuxRef
= SymbolEntRef
.getXCOFFCsectAuxRef();
844 if (!ErrOrCsectAuxRef
)
845 reportUniqueWarning(ErrOrCsectAuxRef
.takeError());
847 printCsectAuxEnt(*ErrOrCsectAuxRef
);
851 case XCOFF::C_STAT
: {
854 const XCOFFSectAuxEntForStat
*StatAuxEntPtr
=
855 getAuxEntPtr
<XCOFFSectAuxEntForStat
>(
856 XCOFFObjectFile::getAdvancedSymbolEntryAddress(
857 SymbolEntRef
.getEntryAddress(), 1));
858 printSectAuxEntForStat(StatAuxEntPtr
);
861 case XCOFF::C_DWARF
: {
864 uintptr_t AuxAddress
= XCOFFObjectFile::getAdvancedSymbolEntryAddress(
865 SymbolEntRef
.getEntryAddress(), 1);
868 const XCOFFSectAuxEntForDWARF64
*AuxEntPtr
=
869 getAuxEntPtr
<XCOFFSectAuxEntForDWARF64
>(AuxAddress
);
870 printSectAuxEntForDWARF
<XCOFFSectAuxEntForDWARF64
>(AuxEntPtr
);
872 const XCOFFSectAuxEntForDWARF32
*AuxEntPtr
=
873 getAuxEntPtr
<XCOFFSectAuxEntForDWARF32
>(AuxAddress
);
874 printSectAuxEntForDWARF
<XCOFFSectAuxEntForDWARF32
>(AuxEntPtr
);
882 uintptr_t AuxAddress
= XCOFFObjectFile::getAdvancedSymbolEntryAddress(
883 SymbolEntRef
.getEntryAddress(), 1);
886 const XCOFFBlockAuxEnt64
*AuxEntPtr
=
887 getAuxEntPtr
<XCOFFBlockAuxEnt64
>(AuxAddress
);
888 printBlockAuxEnt(AuxEntPtr
);
890 const XCOFFBlockAuxEnt32
*AuxEntPtr
=
891 getAuxEntPtr
<XCOFFBlockAuxEnt32
>(AuxAddress
);
892 printBlockAuxEnt(AuxEntPtr
);
897 for (int i
= 1; i
<= NumberOfAuxEntries
; i
++) {
898 printUnexpectedRawAuxEnt(W
,
899 XCOFFObjectFile::getAdvancedSymbolEntryAddress(
900 SymbolEntRef
.getEntryAddress(), i
));
906 void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) {
907 ListScope
Group(W
, "Symbols");
908 for (const SymbolRef
&S
: Obj
.symbols())
912 void XCOFFDumper::printStringTable() {
913 DictScope
DS(W
, "StringTable");
914 StringRef StrTable
= Obj
.getStringTable();
915 uint32_t StrTabSize
= StrTable
.size();
916 W
.printNumber("Length", StrTabSize
);
917 // Print strings from the fifth byte, since the first four bytes contain the
918 // length (in bytes) of the string table (including the length field).
920 printAsStringList(StrTable
, 4);
923 void XCOFFDumper::printDynamicSymbols() {
924 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
927 void XCOFFDumper::printUnwindInfo() {
928 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
931 void XCOFFDumper::printStackMap() const {
932 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
935 void XCOFFDumper::printNeededLibraries() {
936 ListScope
D(W
, "NeededLibraries");
937 auto ImportFilesOrError
= Obj
.getImportFileTable();
938 if (!ImportFilesOrError
) {
939 reportUniqueWarning(ImportFilesOrError
.takeError());
943 StringRef ImportFileTable
= ImportFilesOrError
.get();
944 const char *CurrentStr
= ImportFileTable
.data();
945 const char *TableEnd
= ImportFileTable
.end();
946 // Default column width for names is 13 even if no names are that long.
947 size_t BaseWidth
= 13;
949 // Get the max width of BASE columns.
950 for (size_t StrIndex
= 0; CurrentStr
< TableEnd
; ++StrIndex
) {
951 size_t CurrentLen
= strlen(CurrentStr
);
952 CurrentStr
+= strlen(CurrentStr
) + 1;
953 if (StrIndex
% 3 == 1)
954 BaseWidth
= std::max(BaseWidth
, CurrentLen
);
957 auto &OS
= static_cast<formatted_raw_ostream
&>(W
.startLine());
958 // Each entry consists of 3 strings: the path_name, base_name and
959 // archive_member_name. The first entry is a default LIBPATH value and other
960 // entries have no path_name. We just dump the base_name and
961 // archive_member_name here.
962 OS
<< left_justify("BASE", BaseWidth
) << " MEMBER\n";
963 CurrentStr
= ImportFileTable
.data();
964 for (size_t StrIndex
= 0; CurrentStr
< TableEnd
;
965 ++StrIndex
, CurrentStr
+= strlen(CurrentStr
) + 1) {
966 if (StrIndex
>= 3 && StrIndex
% 3 != 0) {
967 if (StrIndex
% 3 == 1)
968 OS
<< " " << left_justify(CurrentStr
, BaseWidth
) << " ";
970 OS
<< CurrentStr
<< "\n";
975 const EnumEntry
<XCOFF::SectionTypeFlags
> SectionTypeFlagsNames
[] = {
978 ECase(STYP_PAD
), ECase(STYP_DWARF
), ECase(STYP_TEXT
),
979 ECase(STYP_DATA
), ECase(STYP_BSS
), ECase(STYP_EXCEPT
),
980 ECase(STYP_INFO
), ECase(STYP_TDATA
), ECase(STYP_TBSS
),
981 ECase(STYP_LOADER
), ECase(STYP_DEBUG
), ECase(STYP_TYPCHK
),
986 template <typename T
>
987 void XCOFFDumper::printOverflowSectionHeader(T
&Sec
) const {
989 reportWarning(make_error
<StringError
>("An 64-bit XCOFF object file may not "
990 "contain an overflow section header.",
991 object_error::parse_failed
),
995 W
.printString("Name", Sec
.getName());
996 W
.printNumber("NumberOfRelocations", Sec
.PhysicalAddress
);
997 W
.printNumber("NumberOfLineNumbers", Sec
.VirtualAddress
);
998 W
.printHex("Size", Sec
.SectionSize
);
999 W
.printHex("RawDataOffset", Sec
.FileOffsetToRawData
);
1000 W
.printHex("RelocationPointer", Sec
.FileOffsetToRelocationInfo
);
1001 W
.printHex("LineNumberPointer", Sec
.FileOffsetToLineNumberInfo
);
1002 W
.printNumber("IndexOfSectionOverflowed", Sec
.NumberOfRelocations
);
1003 W
.printNumber("IndexOfSectionOverflowed", Sec
.NumberOfLineNumbers
);
1006 template <typename T
>
1007 void XCOFFDumper::printGenericSectionHeader(T
&Sec
) const {
1008 W
.printString("Name", Sec
.getName());
1009 W
.printHex("PhysicalAddress", Sec
.PhysicalAddress
);
1010 W
.printHex("VirtualAddress", Sec
.VirtualAddress
);
1011 W
.printHex("Size", Sec
.SectionSize
);
1012 W
.printHex("RawDataOffset", Sec
.FileOffsetToRawData
);
1013 W
.printHex("RelocationPointer", Sec
.FileOffsetToRelocationInfo
);
1014 W
.printHex("LineNumberPointer", Sec
.FileOffsetToLineNumberInfo
);
1015 W
.printNumber("NumberOfRelocations", Sec
.NumberOfRelocations
);
1016 W
.printNumber("NumberOfLineNumbers", Sec
.NumberOfLineNumbers
);
1019 enum PrintStyle
{ Hex
, Number
};
1020 template <typename T
, typename V
>
1021 static void printAuxMemberHelper(PrintStyle Style
, const char *MemberName
,
1022 const T
&Member
, const V
*AuxHeader
,
1023 uint16_t AuxSize
, uint16_t &PartialFieldOffset
,
1024 const char *&PartialFieldName
,
1026 ptrdiff_t Offset
= reinterpret_cast<const char *>(&Member
) -
1027 reinterpret_cast<const char *>(AuxHeader
);
1028 if (Offset
+ sizeof(Member
) <= AuxSize
)
1029 Style
== Hex
? W
.printHex(MemberName
, Member
)
1030 : W
.printNumber(MemberName
, Member
);
1031 else if (Offset
< AuxSize
) {
1032 PartialFieldOffset
= Offset
;
1033 PartialFieldName
= MemberName
;
1038 void checkAndPrintAuxHeaderParseError(const char *PartialFieldName
,
1039 uint16_t PartialFieldOffset
,
1040 uint16_t AuxSize
, T
&AuxHeader
,
1041 XCOFFDumper
*Dumper
) {
1042 if (PartialFieldOffset
< AuxSize
) {
1043 Dumper
->reportUniqueWarning(Twine("only partial field for ") +
1044 PartialFieldName
+ " at offset (" +
1045 Twine(PartialFieldOffset
) + ")");
1046 Dumper
->getScopedPrinter().printBinary(
1048 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader
) +
1050 AuxSize
- PartialFieldOffset
));
1051 } else if (sizeof(AuxHeader
) < AuxSize
)
1052 Dumper
->getScopedPrinter().printBinary(
1053 "Extra raw data", "",
1054 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader
) +
1056 AuxSize
- sizeof(AuxHeader
)));
1059 void XCOFFDumper::printAuxiliaryHeader(
1060 const XCOFFAuxiliaryHeader32
*AuxHeader
) {
1061 if (AuxHeader
== nullptr)
1063 uint16_t AuxSize
= Obj
.getOptionalHeaderSize();
1064 uint16_t PartialFieldOffset
= AuxSize
;
1065 const char *PartialFieldName
= nullptr;
1067 auto PrintAuxMember
= [&](PrintStyle Style
, const char *MemberName
,
1069 printAuxMemberHelper(Style
, MemberName
, Member
, AuxHeader
, AuxSize
,
1070 PartialFieldOffset
, PartialFieldName
, W
);
1073 PrintAuxMember(Hex
, "Magic", AuxHeader
->AuxMagic
);
1074 PrintAuxMember(Hex
, "Version", AuxHeader
->Version
);
1075 PrintAuxMember(Hex
, "Size of .text section", AuxHeader
->TextSize
);
1076 PrintAuxMember(Hex
, "Size of .data section", AuxHeader
->InitDataSize
);
1077 PrintAuxMember(Hex
, "Size of .bss section", AuxHeader
->BssDataSize
);
1078 PrintAuxMember(Hex
, "Entry point address", AuxHeader
->EntryPointAddr
);
1079 PrintAuxMember(Hex
, ".text section start address", AuxHeader
->TextStartAddr
);
1080 PrintAuxMember(Hex
, ".data section start address", AuxHeader
->DataStartAddr
);
1081 PrintAuxMember(Hex
, "TOC anchor address", AuxHeader
->TOCAnchorAddr
);
1082 PrintAuxMember(Number
, "Section number of entryPoint",
1083 AuxHeader
->SecNumOfEntryPoint
);
1084 PrintAuxMember(Number
, "Section number of .text", AuxHeader
->SecNumOfText
);
1085 PrintAuxMember(Number
, "Section number of .data", AuxHeader
->SecNumOfData
);
1086 PrintAuxMember(Number
, "Section number of TOC", AuxHeader
->SecNumOfTOC
);
1087 PrintAuxMember(Number
, "Section number of loader data",
1088 AuxHeader
->SecNumOfLoader
);
1089 PrintAuxMember(Number
, "Section number of .bss", AuxHeader
->SecNumOfBSS
);
1090 PrintAuxMember(Hex
, "Maxium alignment of .text", AuxHeader
->MaxAlignOfText
);
1091 PrintAuxMember(Hex
, "Maxium alignment of .data", AuxHeader
->MaxAlignOfData
);
1092 PrintAuxMember(Hex
, "Module type", AuxHeader
->ModuleType
);
1093 PrintAuxMember(Hex
, "CPU type of objects", AuxHeader
->CpuFlag
);
1094 PrintAuxMember(Hex
, "(Reserved)", AuxHeader
->CpuType
);
1095 PrintAuxMember(Hex
, "Maximum stack size", AuxHeader
->MaxStackSize
);
1096 PrintAuxMember(Hex
, "Maximum data size", AuxHeader
->MaxDataSize
);
1097 PrintAuxMember(Hex
, "Reserved for debugger", AuxHeader
->ReservedForDebugger
);
1098 PrintAuxMember(Hex
, "Text page size", AuxHeader
->TextPageSize
);
1099 PrintAuxMember(Hex
, "Data page size", AuxHeader
->DataPageSize
);
1100 PrintAuxMember(Hex
, "Stack page size", AuxHeader
->StackPageSize
);
1101 if (offsetof(XCOFFAuxiliaryHeader32
, FlagAndTDataAlignment
) +
1102 sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment
) <=
1104 W
.printHex("Flag", AuxHeader
->getFlag());
1105 W
.printHex("Alignment of thread-local storage",
1106 AuxHeader
->getTDataAlignment());
1109 PrintAuxMember(Number
, "Section number for .tdata", AuxHeader
->SecNumOfTData
);
1110 PrintAuxMember(Number
, "Section number for .tbss", AuxHeader
->SecNumOfTBSS
);
1112 checkAndPrintAuxHeaderParseError(PartialFieldName
, PartialFieldOffset
,
1113 AuxSize
, *AuxHeader
, this);
1116 void XCOFFDumper::printAuxiliaryHeader(
1117 const XCOFFAuxiliaryHeader64
*AuxHeader
) {
1118 if (AuxHeader
== nullptr)
1120 uint16_t AuxSize
= Obj
.getOptionalHeaderSize();
1121 uint16_t PartialFieldOffset
= AuxSize
;
1122 const char *PartialFieldName
= nullptr;
1124 auto PrintAuxMember
= [&](PrintStyle Style
, const char *MemberName
,
1126 printAuxMemberHelper(Style
, MemberName
, Member
, AuxHeader
, AuxSize
,
1127 PartialFieldOffset
, PartialFieldName
, W
);
1130 PrintAuxMember(Hex
, "Magic", AuxHeader
->AuxMagic
);
1131 PrintAuxMember(Hex
, "Version", AuxHeader
->Version
);
1132 PrintAuxMember(Hex
, "Reserved for debugger", AuxHeader
->ReservedForDebugger
);
1133 PrintAuxMember(Hex
, ".text section start address", AuxHeader
->TextStartAddr
);
1134 PrintAuxMember(Hex
, ".data section start address", AuxHeader
->DataStartAddr
);
1135 PrintAuxMember(Hex
, "TOC anchor address", AuxHeader
->TOCAnchorAddr
);
1136 PrintAuxMember(Number
, "Section number of entryPoint",
1137 AuxHeader
->SecNumOfEntryPoint
);
1138 PrintAuxMember(Number
, "Section number of .text", AuxHeader
->SecNumOfText
);
1139 PrintAuxMember(Number
, "Section number of .data", AuxHeader
->SecNumOfData
);
1140 PrintAuxMember(Number
, "Section number of TOC", AuxHeader
->SecNumOfTOC
);
1141 PrintAuxMember(Number
, "Section number of loader data",
1142 AuxHeader
->SecNumOfLoader
);
1143 PrintAuxMember(Number
, "Section number of .bss", AuxHeader
->SecNumOfBSS
);
1144 PrintAuxMember(Hex
, "Maxium alignment of .text", AuxHeader
->MaxAlignOfText
);
1145 PrintAuxMember(Hex
, "Maxium alignment of .data", AuxHeader
->MaxAlignOfData
);
1146 PrintAuxMember(Hex
, "Module type", AuxHeader
->ModuleType
);
1147 PrintAuxMember(Hex
, "CPU type of objects", AuxHeader
->CpuFlag
);
1148 PrintAuxMember(Hex
, "(Reserved)", AuxHeader
->CpuType
);
1149 PrintAuxMember(Hex
, "Text page size", AuxHeader
->TextPageSize
);
1150 PrintAuxMember(Hex
, "Data page size", AuxHeader
->DataPageSize
);
1151 PrintAuxMember(Hex
, "Stack page size", AuxHeader
->StackPageSize
);
1152 if (offsetof(XCOFFAuxiliaryHeader64
, FlagAndTDataAlignment
) +
1153 sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment
) <=
1155 W
.printHex("Flag", AuxHeader
->getFlag());
1156 W
.printHex("Alignment of thread-local storage",
1157 AuxHeader
->getTDataAlignment());
1159 PrintAuxMember(Hex
, "Size of .text section", AuxHeader
->TextSize
);
1160 PrintAuxMember(Hex
, "Size of .data section", AuxHeader
->InitDataSize
);
1161 PrintAuxMember(Hex
, "Size of .bss section", AuxHeader
->BssDataSize
);
1162 PrintAuxMember(Hex
, "Entry point address", AuxHeader
->EntryPointAddr
);
1163 PrintAuxMember(Hex
, "Maximum stack size", AuxHeader
->MaxStackSize
);
1164 PrintAuxMember(Hex
, "Maximum data size", AuxHeader
->MaxDataSize
);
1165 PrintAuxMember(Number
, "Section number for .tdata", AuxHeader
->SecNumOfTData
);
1166 PrintAuxMember(Number
, "Section number for .tbss", AuxHeader
->SecNumOfTBSS
);
1167 PrintAuxMember(Hex
, "Additional flags 64-bit XCOFF", AuxHeader
->XCOFF64Flag
);
1169 checkAndPrintAuxHeaderParseError(PartialFieldName
, PartialFieldOffset
,
1170 AuxSize
, *AuxHeader
, this);
1173 template <typename T
>
1174 void XCOFFDumper::printSectionHeaders(ArrayRef
<T
> Sections
) {
1175 ListScope
Group(W
, "Sections");
1178 for (const T
&Sec
: Sections
) {
1179 DictScope
SecDS(W
, "Section");
1181 W
.printNumber("Index", Index
++);
1182 uint16_t SectionType
= Sec
.getSectionType();
1183 switch (SectionType
) {
1184 case XCOFF::STYP_OVRFLO
:
1185 printOverflowSectionHeader(Sec
);
1187 case XCOFF::STYP_LOADER
:
1188 case XCOFF::STYP_EXCEPT
:
1189 case XCOFF::STYP_TYPCHK
:
1190 // TODO The interpretation of loader, exception and type check section
1191 // headers are different from that of generic section headers. We will
1192 // implement them later. We interpret them as generic section headers for
1195 printGenericSectionHeader(Sec
);
1198 if (Sec
.isReservedSectionType())
1199 W
.printHex("Flags", "Reserved", SectionType
);
1201 W
.printEnum("Type", SectionType
, ArrayRef(SectionTypeFlagsNames
));
1204 if (opts::SectionRelocations
)
1205 report_fatal_error("Dumping section relocations is unimplemented");
1207 if (opts::SectionSymbols
)
1208 report_fatal_error("Dumping symbols is unimplemented");
1210 if (opts::SectionData
)
1211 report_fatal_error("Dumping section data is unimplemented");
1215 std::unique_ptr
<ObjDumper
>
1216 createXCOFFDumper(const object::XCOFFObjectFile
&XObj
, ScopedPrinter
&Writer
) {
1217 return std::make_unique
<XCOFFDumper
>(XObj
, Writer
);