1 //===-- XCOFFDump.cpp - XCOFF-specific dumper -----------------------------===//
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 //===----------------------------------------------------------------------===//
10 /// This file implements the XCOFF-specific dumper for llvm-objdump.
12 //===----------------------------------------------------------------------===//
14 #include "XCOFFDump.h"
16 #include "llvm-objdump.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Demangle/Demangle.h"
19 #include "llvm/MC/MCInstPrinter.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/FormattedStream.h"
24 #include "llvm/Support/raw_ostream.h"
28 using namespace llvm::object
;
29 using namespace llvm::XCOFF
;
30 using namespace llvm::support
;
33 class XCOFFDumper
: public objdump::Dumper
{
34 enum PrintStyle
{ Hex
, Number
};
35 const XCOFFObjectFile
&Obj
;
39 XCOFFDumper(const object::XCOFFObjectFile
&O
) : Dumper(O
), Obj(O
) {}
42 void printPrivateHeaders() override
;
43 void printFileHeader();
44 void printAuxiliaryHeader();
45 void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32
*AuxHeader
);
46 void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64
*AuxHeader
);
47 template <typename AuxHeaderMemberType
, typename XCOFFAuxiliaryHeader
>
48 void printAuxMemberHelper(PrintStyle Style
, const char *MemberName
,
49 const AuxHeaderMemberType
&Member
,
50 const XCOFFAuxiliaryHeader
*AuxHeader
,
51 uint16_t AuxSize
, uint16_t &PartialFieldOffset
,
52 const char *&PartialFieldName
);
53 template <typename XCOFFAuxiliaryHeader
>
54 void checkAndPrintAuxHeaderParseError(const char *PartialFieldName
,
55 uint16_t PartialFieldOffset
,
57 XCOFFAuxiliaryHeader
&AuxHeader
);
59 void printBinary(StringRef Name
, ArrayRef
<uint8_t> Data
);
60 void printHex(StringRef Name
, uint64_t Value
);
61 void printNumber(StringRef Name
, uint64_t Value
);
62 FormattedString
formatName(StringRef Name
);
63 void printStrHex(StringRef Name
, StringRef Str
, uint64_t Value
);
66 void XCOFFDumper::printPrivateHeaders() {
68 printAuxiliaryHeader();
71 FormattedString
XCOFFDumper::formatName(StringRef Name
) {
72 return FormattedString(Name
, Width
, FormattedString::JustifyLeft
);
75 void XCOFFDumper::printHex(StringRef Name
, uint64_t Value
) {
76 outs() << formatName(Name
) << format_hex(Value
, 0) << "\n";
79 void XCOFFDumper::printNumber(StringRef Name
, uint64_t Value
) {
80 outs() << formatName(Name
) << format_decimal(Value
, 0) << "\n";
83 void XCOFFDumper::printStrHex(StringRef Name
, StringRef Str
, uint64_t Value
) {
84 outs() << formatName(Name
) << Str
<< " (" << format_decimal(Value
, 0)
88 void XCOFFDumper::printBinary(StringRef Name
, ArrayRef
<uint8_t> Data
) {
89 unsigned OrgWidth
= Width
;
91 outs() << formatName(Name
) << " (" << format_bytes(Data
) << ")\n";
95 void XCOFFDumper::printAuxiliaryHeader() {
98 printAuxiliaryHeader(Obj
.auxiliaryHeader64());
100 printAuxiliaryHeader(Obj
.auxiliaryHeader32());
103 template <typename AuxHeaderMemberType
, typename XCOFFAuxiliaryHeader
>
104 void XCOFFDumper::printAuxMemberHelper(PrintStyle Style
, const char *MemberName
,
105 const AuxHeaderMemberType
&Member
,
106 const XCOFFAuxiliaryHeader
*AuxHeader
,
108 uint16_t &PartialFieldOffset
,
109 const char *&PartialFieldName
) {
110 ptrdiff_t Offset
= reinterpret_cast<const char *>(&Member
) -
111 reinterpret_cast<const char *>(AuxHeader
);
112 if (Offset
+ sizeof(Member
) <= AuxSize
) {
114 printHex(MemberName
, Member
);
116 printNumber(MemberName
, Member
);
117 } else if (Offset
< AuxSize
) {
118 PartialFieldOffset
= Offset
;
119 PartialFieldName
= MemberName
;
123 template <typename XCOFFAuxiliaryHeader
>
124 void XCOFFDumper::checkAndPrintAuxHeaderParseError(
125 const char *PartialFieldName
, uint16_t PartialFieldOffset
, uint16_t AuxSize
,
126 XCOFFAuxiliaryHeader
&AuxHeader
) {
127 if (PartialFieldOffset
< AuxSize
) {
129 raw_string_ostream
OS(Buf
);
131 OS
<< FormattedString("Raw data", 0, FormattedString::JustifyLeft
) << " ("
133 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader
) +
135 AuxSize
- PartialFieldOffset
))
137 reportUniqueWarning(Twine("only partial field for ") + PartialFieldName
+
138 " at offset (" + Twine(PartialFieldOffset
) + ")\n" +
140 } else if (sizeof(AuxHeader
) < AuxSize
) {
143 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader
) +
145 AuxSize
- sizeof(AuxHeader
)));
149 void XCOFFDumper::printAuxiliaryHeader(
150 const XCOFFAuxiliaryHeader32
*AuxHeader
) {
151 if (AuxHeader
== nullptr)
153 outs() << "\n---Auxiliary Header:\n";
154 uint16_t AuxSize
= Obj
.getOptionalHeaderSize();
155 uint16_t PartialFieldOffset
= AuxSize
;
156 const char *PartialFieldName
= nullptr;
158 auto PrintAuxMember
= [&](PrintStyle Style
, const char *MemberName
,
160 printAuxMemberHelper(Style
, MemberName
, Member
, AuxHeader
, AuxSize
,
161 PartialFieldOffset
, PartialFieldName
);
164 PrintAuxMember(Hex
, "Magic:", AuxHeader
->AuxMagic
);
165 PrintAuxMember(Hex
, "Version:", AuxHeader
->Version
);
166 PrintAuxMember(Hex
, "Size of .text section:", AuxHeader
->TextSize
);
167 PrintAuxMember(Hex
, "Size of .data section:", AuxHeader
->InitDataSize
);
168 PrintAuxMember(Hex
, "Size of .bss section:", AuxHeader
->BssDataSize
);
169 PrintAuxMember(Hex
, "Entry point address:", AuxHeader
->EntryPointAddr
);
170 PrintAuxMember(Hex
, ".text section start address:", AuxHeader
->TextStartAddr
);
171 PrintAuxMember(Hex
, ".data section start address:", AuxHeader
->DataStartAddr
);
172 PrintAuxMember(Hex
, "TOC anchor address:", AuxHeader
->TOCAnchorAddr
);
174 Number
, "Section number of entryPoint:", AuxHeader
->SecNumOfEntryPoint
);
175 PrintAuxMember(Number
, "Section number of .text:", AuxHeader
->SecNumOfText
);
176 PrintAuxMember(Number
, "Section number of .data:", AuxHeader
->SecNumOfData
);
177 PrintAuxMember(Number
, "Section number of TOC:", AuxHeader
->SecNumOfTOC
);
178 PrintAuxMember(Number
,
179 "Section number of loader data:", AuxHeader
->SecNumOfLoader
);
180 PrintAuxMember(Number
, "Section number of .bss:", AuxHeader
->SecNumOfBSS
);
181 PrintAuxMember(Hex
, "Maxium alignment of .text:", AuxHeader
->MaxAlignOfText
);
182 PrintAuxMember(Hex
, "Maxium alignment of .data:", AuxHeader
->MaxAlignOfData
);
183 PrintAuxMember(Hex
, "Module type:", AuxHeader
->ModuleType
);
184 PrintAuxMember(Hex
, "CPU type of objects:", AuxHeader
->CpuFlag
);
185 PrintAuxMember(Hex
, "Maximum stack size:", AuxHeader
->MaxStackSize
);
186 PrintAuxMember(Hex
, "Maximum data size:", AuxHeader
->MaxDataSize
);
187 PrintAuxMember(Hex
, "Reserved for debugger:", AuxHeader
->ReservedForDebugger
);
188 PrintAuxMember(Hex
, "Text page size:", AuxHeader
->TextPageSize
);
189 PrintAuxMember(Hex
, "Data page size:", AuxHeader
->DataPageSize
);
190 PrintAuxMember(Hex
, "Stack page size:", AuxHeader
->StackPageSize
);
191 if (offsetof(XCOFFAuxiliaryHeader32
, FlagAndTDataAlignment
) +
192 sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment
) <=
194 printHex("Flag:", AuxHeader
->getFlag());
195 printHex("Alignment of thread-local storage:",
196 AuxHeader
->getTDataAlignment());
199 PrintAuxMember(Number
,
200 "Section number for .tdata:", AuxHeader
->SecNumOfTData
);
201 PrintAuxMember(Number
, "Section number for .tbss:", AuxHeader
->SecNumOfTBSS
);
203 checkAndPrintAuxHeaderParseError(PartialFieldName
, PartialFieldOffset
,
204 AuxSize
, *AuxHeader
);
207 void XCOFFDumper::printAuxiliaryHeader(
208 const XCOFFAuxiliaryHeader64
*AuxHeader
) {
209 if (AuxHeader
== nullptr)
211 uint16_t AuxSize
= Obj
.getOptionalHeaderSize();
212 outs() << "\n---Auxiliary Header:\n";
213 uint16_t PartialFieldOffset
= AuxSize
;
214 const char *PartialFieldName
= nullptr;
216 auto PrintAuxMember
= [&](PrintStyle Style
, const char *MemberName
,
218 printAuxMemberHelper(Style
, MemberName
, Member
, AuxHeader
, AuxSize
,
219 PartialFieldOffset
, PartialFieldName
);
222 PrintAuxMember(Hex
, "Magic:", AuxHeader
->AuxMagic
);
223 PrintAuxMember(Hex
, "Version:", AuxHeader
->Version
);
224 PrintAuxMember(Hex
, "Reserved for debugger:", AuxHeader
->ReservedForDebugger
);
225 PrintAuxMember(Hex
, ".text section start address:", AuxHeader
->TextStartAddr
);
226 PrintAuxMember(Hex
, ".data section start address:", AuxHeader
->DataStartAddr
);
227 PrintAuxMember(Hex
, "TOC anchor address:", AuxHeader
->TOCAnchorAddr
);
229 Number
, "Section number of entryPoint:", AuxHeader
->SecNumOfEntryPoint
);
230 PrintAuxMember(Number
, "Section number of .text:", AuxHeader
->SecNumOfText
);
231 PrintAuxMember(Number
, "Section number of .data:", AuxHeader
->SecNumOfData
);
232 PrintAuxMember(Number
, "Section number of TOC:", AuxHeader
->SecNumOfTOC
);
233 PrintAuxMember(Number
,
234 "Section number of loader data:", AuxHeader
->SecNumOfLoader
);
235 PrintAuxMember(Number
, "Section number of .bss:", AuxHeader
->SecNumOfBSS
);
236 PrintAuxMember(Hex
, "Maxium alignment of .text:", AuxHeader
->MaxAlignOfText
);
237 PrintAuxMember(Hex
, "Maxium alignment of .data:", AuxHeader
->MaxAlignOfData
);
238 PrintAuxMember(Hex
, "Module type:", AuxHeader
->ModuleType
);
239 PrintAuxMember(Hex
, "CPU type of objects:", AuxHeader
->CpuFlag
);
240 PrintAuxMember(Hex
, "Text page size:", AuxHeader
->TextPageSize
);
241 PrintAuxMember(Hex
, "Data page size:", AuxHeader
->DataPageSize
);
242 PrintAuxMember(Hex
, "Stack page size:", AuxHeader
->StackPageSize
);
243 if (offsetof(XCOFFAuxiliaryHeader64
, FlagAndTDataAlignment
) +
244 sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment
) <=
246 printHex("Flag:", AuxHeader
->getFlag());
247 printHex("Alignment of thread-local storage:",
248 AuxHeader
->getTDataAlignment());
250 PrintAuxMember(Hex
, "Size of .text section:", AuxHeader
->TextSize
);
251 PrintAuxMember(Hex
, "Size of .data section:", AuxHeader
->InitDataSize
);
252 PrintAuxMember(Hex
, "Size of .bss section:", AuxHeader
->BssDataSize
);
253 PrintAuxMember(Hex
, "Entry point address:", AuxHeader
->EntryPointAddr
);
254 PrintAuxMember(Hex
, "Maximum stack size:", AuxHeader
->MaxStackSize
);
255 PrintAuxMember(Hex
, "Maximum data size:", AuxHeader
->MaxDataSize
);
256 PrintAuxMember(Number
,
257 "Section number for .tdata:", AuxHeader
->SecNumOfTData
);
258 PrintAuxMember(Number
, "Section number for .tbss:", AuxHeader
->SecNumOfTBSS
);
259 PrintAuxMember(Hex
, "Additional flags 64-bit XCOFF:", AuxHeader
->XCOFF64Flag
);
261 checkAndPrintAuxHeaderParseError(PartialFieldName
, PartialFieldOffset
,
262 AuxSize
, *AuxHeader
);
265 void XCOFFDumper::printFileHeader() {
267 outs() << "\n---File Header:\n";
268 printHex("Magic:", Obj
.getMagic());
269 printNumber("NumberOfSections:", Obj
.getNumberOfSections());
271 int32_t Timestamp
= Obj
.getTimeStamp();
273 // This handling of the timestamp assumes that the host system's time_t is
274 // compatible with AIX time_t. If a platform is not compatible, the lit
275 // tests will let us know.
276 time_t TimeDate
= Timestamp
;
278 char FormattedTime
[20] = {};
280 size_t BytesFormatted
= std::strftime(FormattedTime
, sizeof(FormattedTime
),
281 "%F %T", std::gmtime(&TimeDate
));
282 assert(BytesFormatted
&& "The size of the buffer FormattedTime is less "
283 "than the size of the date/time string.");
284 (void)BytesFormatted
;
285 printStrHex("Timestamp:", FormattedTime
, Timestamp
);
287 // Negative timestamp values are reserved for future use.
288 printStrHex("Timestamp:", Timestamp
== 0 ? "None" : "Reserved Value",
292 // The number of symbol table entries is an unsigned value in 64-bit objects
293 // and a signed value (with negative values being 'reserved') in 32-bit
296 printHex("SymbolTableOffset:", Obj
.getSymbolTableOffset64());
297 printNumber("SymbolTableEntries:", Obj
.getNumberOfSymbolTableEntries64());
299 printHex("SymbolTableOffset:", Obj
.getSymbolTableOffset32());
300 int32_t SymTabEntries
= Obj
.getRawNumberOfSymbolTableEntries32();
301 if (SymTabEntries
>= 0)
302 printNumber("SymbolTableEntries:", SymTabEntries
);
304 printStrHex("SymbolTableEntries:", "Reserved Value", SymTabEntries
);
307 printHex("OptionalHeaderSize:", Obj
.getOptionalHeaderSize());
308 printHex("Flags:", Obj
.getFlags());
313 std::unique_ptr
<objdump::Dumper
>
314 objdump::createXCOFFDumper(const object::XCOFFObjectFile
&Obj
) {
315 return std::make_unique
<XCOFFDumper
>(Obj
);
318 Error
objdump::getXCOFFRelocationValueString(const XCOFFObjectFile
&Obj
,
319 const RelocationRef
&Rel
,
320 bool SymbolDescription
,
321 SmallVectorImpl
<char> &Result
) {
322 symbol_iterator SymI
= Rel
.getSymbol();
323 if (SymI
== Obj
.symbol_end())
324 return make_error
<GenericBinaryError
>(
325 "invalid symbol reference in relocation entry",
326 object_error::parse_failed
);
328 Expected
<StringRef
> SymNameOrErr
= SymI
->getName();
330 return SymNameOrErr
.takeError();
332 std::string SymName
=
333 Demangle
? demangle(*SymNameOrErr
) : SymNameOrErr
->str();
334 if (SymbolDescription
)
335 SymName
= getXCOFFSymbolDescription(createSymbolInfo(Obj
, *SymI
), SymName
);
337 Result
.append(SymName
.begin(), SymName
.end());
338 return Error::success();
341 std::optional
<XCOFF::StorageMappingClass
>
342 objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile
&Obj
,
343 const SymbolRef
&Sym
) {
344 const XCOFFSymbolRef SymRef
= Obj
.toSymbolRef(Sym
.getRawDataRefImpl());
346 if (!SymRef
.isCsectSymbol())
349 auto CsectAuxEntOrErr
= SymRef
.getXCOFFCsectAuxRef();
350 if (!CsectAuxEntOrErr
)
353 return CsectAuxEntOrErr
.get().getStorageMappingClass();
356 std::optional
<object::SymbolRef
>
357 objdump::getXCOFFSymbolContainingSymbolRef(const XCOFFObjectFile
&Obj
,
358 const SymbolRef
&Sym
) {
359 const XCOFFSymbolRef SymRef
= Obj
.toSymbolRef(Sym
.getRawDataRefImpl());
360 if (!SymRef
.isCsectSymbol())
363 Expected
<XCOFFCsectAuxRef
> CsectAuxEntOrErr
= SymRef
.getXCOFFCsectAuxRef();
364 if (!CsectAuxEntOrErr
|| !CsectAuxEntOrErr
.get().isLabel())
367 static_cast<uint32_t>(CsectAuxEntOrErr
.get().getSectionOrLength());
369 DRI
.p
= Obj
.getSymbolByIndex(Idx
);
370 return SymbolRef(DRI
, &Obj
);
373 bool objdump::isLabel(const XCOFFObjectFile
&Obj
, const SymbolRef
&Sym
) {
374 const XCOFFSymbolRef SymRef
= Obj
.toSymbolRef(Sym
.getRawDataRefImpl());
375 if (!SymRef
.isCsectSymbol())
378 auto CsectAuxEntOrErr
= SymRef
.getXCOFFCsectAuxRef();
379 if (!CsectAuxEntOrErr
)
382 return CsectAuxEntOrErr
.get().isLabel();
385 std::string
objdump::getXCOFFSymbolDescription(const SymbolInfoTy
&SymbolInfo
,
386 StringRef SymbolName
) {
387 assert(SymbolInfo
.isXCOFF() && "Must be a XCOFFSymInfo.");
390 // Dummy symbols have no symbol index.
391 if (SymbolInfo
.XCOFFSymInfo
.Index
)
393 ("(idx: " + Twine(*SymbolInfo
.XCOFFSymInfo
.Index
) + ") " + SymbolName
)
396 Result
.append(SymbolName
.begin(), SymbolName
.end());
398 if (SymbolInfo
.XCOFFSymInfo
.StorageMappingClass
&&
399 !SymbolInfo
.XCOFFSymInfo
.IsLabel
) {
400 const XCOFF::StorageMappingClass Smc
=
401 *SymbolInfo
.XCOFFSymInfo
.StorageMappingClass
;
402 Result
.append(("[" + XCOFF::getMappingClassString(Smc
) + "]").str());
408 #define PRINTBOOL(Prefix, Obj, Field) \
409 OS << Prefix << " " << ((Obj.Field()) ? "+" : "-") << #Field
411 #define PRINTGET(Prefix, Obj, Field) \
412 OS << Prefix << " " << #Field << " = " \
413 << static_cast<unsigned>(Obj.get##Field())
415 #define PRINTOPTIONAL(Field) \
416 if (TbTable.get##Field()) { \
418 printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI); \
420 OS << "\t# " << #Field << " = " << *TbTable.get##Field(); \
423 void objdump::dumpTracebackTable(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
424 formatted_raw_ostream
&OS
, uint64_t End
,
425 const MCSubtargetInfo
&STI
,
426 const XCOFFObjectFile
*Obj
) {
428 unsigned TabStop
= getInstStartColumn(STI
) - 1;
429 // Print traceback table boundary.
430 printRawData(Bytes
.slice(Index
, 4), Address
, OS
, STI
);
431 OS
<< "\t# Traceback table start\n";
434 uint64_t Size
= End
- Address
;
435 bool Is64Bit
= Obj
->is64Bit();
437 // XCOFFTracebackTable::create modifies the size parameter, so ensure Size
439 uint64_t SizeCopy
= End
- Address
;
440 Expected
<XCOFFTracebackTable
> TTOrErr
=
441 XCOFFTracebackTable::create(Bytes
.data() + Index
, SizeCopy
, Is64Bit
);
444 std::string WarningMsgStr
;
445 raw_string_ostream
WarningStream(WarningMsgStr
);
446 WarningStream
<< "failure parsing traceback table with address: 0x"
447 << utohexstr(Address
) + "\n>>> "
448 << toString(TTOrErr
.takeError())
449 << "\n>>> Raw traceback table data is:\n";
451 uint64_t LastNonZero
= Index
;
452 for (uint64_t I
= Index
; I
< Size
; I
+= 4)
453 if (support::endian::read32be(Bytes
.slice(I
, 4).data()) != 0)
454 LastNonZero
= I
+ 4 > Size
? Size
: I
+ 4;
456 if (Size
- LastNonZero
<= 4)
459 formatted_raw_ostream
FOS(WarningStream
);
460 while (Index
< LastNonZero
) {
461 printRawData(Bytes
.slice(Index
, 4), Address
+ Index
, FOS
, STI
);
463 WarningStream
<< '\n';
466 // Print all remaining zeroes as ...
467 if (Size
- LastNonZero
>= 8)
468 WarningStream
<< "\t\t...\n";
470 reportWarning(WarningMsgStr
, Obj
->getFileName());
474 auto PrintBytes
= [&](uint64_t N
) {
475 printRawData(Bytes
.slice(Index
, N
), Address
+ Index
, OS
, STI
);
479 XCOFFTracebackTable TbTable
= *TTOrErr
;
480 // Print the first of the 8 bytes of mandatory fields.
482 OS
<< format("\t# Version = %i", TbTable
.getVersion()) << '\n';
484 // Print the second of the 8 bytes of mandatory fields.
486 TracebackTable::LanguageID LangId
=
487 static_cast<TracebackTable::LanguageID
>(TbTable
.getLanguageID());
488 OS
<< "\t# Language = " << getNameForTracebackTableLanguageId(LangId
) << '\n';
495 // Print the third of the 8 bytes of mandatory fields.
497 PRINTBOOL("\t#", TbTable
, isGlobalLinkage
);
498 PRINTBOOL(",", TbTable
, isOutOfLineEpilogOrPrologue
);
500 PRINTBOOL("\t ", TbTable
, hasTraceBackTableOffset
);
501 PRINTBOOL(",", TbTable
, isInternalProcedure
);
503 PRINTBOOL("\t ", TbTable
, hasControlledStorage
);
504 PRINTBOOL(",", TbTable
, isTOCless
);
506 PRINTBOOL("\t ", TbTable
, isFloatingPointPresent
);
508 PRINTBOOL("\t ", TbTable
, isFloatingPointOperationLogOrAbortEnabled
);
511 // Print the 4th of the 8 bytes of mandatory fields.
513 PRINTBOOL("\t#", TbTable
, isInterruptHandler
);
514 PRINTBOOL(",", TbTable
, isFuncNamePresent
);
515 PRINTBOOL(",", TbTable
, isAllocaUsed
);
517 PRINTGET("\t ", TbTable
, OnConditionDirective
);
518 PRINTBOOL(",", TbTable
, isCRSaved
);
519 PRINTBOOL(",", TbTable
, isLRSaved
);
522 // Print the 5th of the 8 bytes of mandatory fields.
524 PRINTBOOL("\t#", TbTable
, isBackChainStored
);
525 PRINTBOOL(",", TbTable
, isFixup
);
526 PRINTGET(",", TbTable
, NumOfFPRsSaved
);
529 // Print the 6th of the 8 bytes of mandatory fields.
531 PRINTBOOL("\t#", TbTable
, hasExtensionTable
);
532 PRINTBOOL(",", TbTable
, hasVectorInfo
);
533 PRINTGET(",", TbTable
, NumOfGPRsSaved
);
536 // Print the 7th of the 8 bytes of mandatory fields.
538 PRINTGET("\t#", TbTable
, NumberOfFixedParms
);
541 // Print the 8th of the 8 bytes of mandatory fields.
543 PRINTGET("\t#", TbTable
, NumberOfFPParms
);
544 PRINTBOOL(",", TbTable
, hasParmsOnStack
);
546 PRINTOPTIONAL(ParmsType
);
547 PRINTOPTIONAL(TraceBackTableOffset
);
548 PRINTOPTIONAL(HandlerMask
);
549 PRINTOPTIONAL(NumOfCtlAnchors
);
551 if (TbTable
.getControlledStorageInfoDisp()) {
552 SmallVector
<uint32_t, 8> Disp
= *TbTable
.getControlledStorageInfoDisp();
553 for (unsigned I
= 0; I
< Disp
.size(); ++I
) {
556 OS
<< "\t" << (I
? " " : "#") << " ControlledStorageInfoDisp[" << I
557 << "] = " << Disp
[I
];
561 // If there is a name, print the function name and function name length.
562 if (TbTable
.isFuncNamePresent()) {
563 uint16_t FunctionNameLen
= TbTable
.getFunctionName()->size();
564 if (FunctionNameLen
== 0) {
567 "the length of the function name must be greater than zero if the "
568 "isFuncNamePresent bit is set in the traceback table",
575 OS
<< "\t# FunctionNameLen = " << FunctionNameLen
;
577 uint16_t RemainingBytes
= FunctionNameLen
;
578 bool HasPrinted
= false;
579 while (RemainingBytes
> 0) {
581 uint16_t PrintLen
= RemainingBytes
>= 4 ? 4 : RemainingBytes
;
582 printRawData(Bytes
.slice(Index
, PrintLen
), Address
+ Index
, OS
, STI
);
584 RemainingBytes
-= PrintLen
;
587 OS
<< "\t# FunctionName = " << *TbTable
.getFunctionName();
593 if (TbTable
.isAllocaUsed()) {
596 OS
<< format("\t# AllocaRegister = %u", *TbTable
.getAllocaRegister());
599 if (TbTable
.getVectorExt()) {
601 TBVectorExt VecExt
= *TbTable
.getVectorExt();
602 // Print first byte of VectorExt.
604 PRINTGET("\t#", VecExt
, NumberOfVRSaved
);
605 PRINTBOOL(",", VecExt
, isVRSavedOnStack
);
606 PRINTBOOL(",", VecExt
, hasVarArgs
);
609 // Print the second byte of VectorExt.
611 PRINTGET("\t#", VecExt
, NumberOfVectorParms
);
612 PRINTBOOL(",", VecExt
, hasVMXInstruction
);
616 OS
<< "\t# VectorParmsInfoString = " << VecExt
.getVectorParmsInfo();
618 // There are two bytes of padding after vector info.
624 if (TbTable
.getExtensionTable()) {
627 ExtendedTBTableFlag Flag
=
628 static_cast<ExtendedTBTableFlag
>(*TbTable
.getExtensionTable());
629 OS
<< "\t# ExtensionTable = " << getExtendedTBTableFlagString(Flag
);
632 if (TbTable
.getEhInfoDisp()) {
633 // There are 4 bytes alignment before eh info displacement.
636 PrintBytes(4 - Index
% 4);
637 OS
<< "\t# Alignment padding for eh info displacement";
640 // The size of the displacement (address) is 4 bytes in 32-bit object files,
641 // and 8 bytes in 64-bit object files.
643 OS
<< "\t# EH info displacement";
651 if (End
== Address
+ Index
)
654 Size
= End
- Address
;
656 const char *LineSuffix
= "\t# Padding\n";
657 auto IsWordZero
= [&](uint64_t WordPos
) {
660 uint64_t LineLength
= std::min(4 - WordPos
% 4, Size
- WordPos
);
661 return std::all_of(Bytes
.begin() + WordPos
,
662 Bytes
.begin() + WordPos
+ LineLength
,
663 [](uint8_t Byte
) { return Byte
== 0; });
666 bool AreWordsZero
[] = {IsWordZero(Index
), IsWordZero(alignTo(Index
, 4) + 4),
667 IsWordZero(alignTo(Index
, 4) + 8)};
668 bool ShouldPrintLine
= true;
670 // Determine the length of the line (4, except for the first line, which
671 // will be just enough to align to the word boundary, and the last line,
672 // which will be the remainder of the data).
673 uint64_t LineLength
= std::min(4 - Index
% 4, Size
- Index
);
674 if (ShouldPrintLine
) {
676 printRawData(Bytes
.slice(Index
, LineLength
), Address
+ Index
, OS
, STI
);
685 // For 3 or more consecutive lines of zeros, skip all but the first one, and
686 // replace them with "...".
687 if (AreWordsZero
[0] && AreWordsZero
[1] && AreWordsZero
[2]) {
689 OS
<< std::string(8, ' ') << "...\n";
690 ShouldPrintLine
= false;
691 } else if (!AreWordsZero
[1]) {
692 // We have reached the end of a skipped block of zeros.
693 ShouldPrintLine
= true;
695 AreWordsZero
[0] = AreWordsZero
[1];
696 AreWordsZero
[1] = AreWordsZero
[2];
697 AreWordsZero
[2] = IsWordZero(Index
+ 8);