[AMDGPU][True16][CodeGen] true16 codegen pattern for v_med3_u/i16 (#121850)
[llvm-project.git] / llvm / tools / llvm-objdump / XCOFFDump.cpp
blob92f9ee4fb9f96d6bce2cb4d9caa20d7dc8c1d97d
1 //===-- XCOFFDump.cpp - XCOFF-specific dumper -----------------------------===//
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 /// \file
10 /// This file implements the XCOFF-specific dumper for llvm-objdump.
11 ///
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"
25 #include <algorithm>
27 using namespace llvm;
28 using namespace llvm::object;
29 using namespace llvm::XCOFF;
30 using namespace llvm::support;
32 namespace {
33 class XCOFFDumper : public objdump::Dumper {
34 enum PrintStyle { Hex, Number };
35 const XCOFFObjectFile &Obj;
36 unsigned Width;
38 public:
39 XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O), Obj(O) {}
41 private:
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,
56 uint16_t AuxSize,
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() {
67 printFileHeader();
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)
85 << ")\n";
88 void XCOFFDumper::printBinary(StringRef Name, ArrayRef<uint8_t> Data) {
89 unsigned OrgWidth = Width;
90 Width = 0;
91 outs() << formatName(Name) << " (" << format_bytes(Data) << ")\n";
92 Width = OrgWidth;
95 void XCOFFDumper::printAuxiliaryHeader() {
96 Width = 36;
97 if (Obj.is64Bit())
98 printAuxiliaryHeader(Obj.auxiliaryHeader64());
99 else
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,
107 uint16_t AuxSize,
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) {
113 if (Style == Hex)
114 printHex(MemberName, Member);
115 else
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) {
128 std::string Buf;
129 raw_string_ostream OS(Buf);
130 OS.flush();
131 OS << FormattedString("Raw data", 0, FormattedString::JustifyLeft) << " ("
132 << format_bytes(
133 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
134 PartialFieldOffset,
135 AuxSize - PartialFieldOffset))
136 << ")\n";
137 reportUniqueWarning(Twine("only partial field for ") + PartialFieldName +
138 " at offset (" + Twine(PartialFieldOffset) + ")\n" +
139 OS.str());
140 } else if (sizeof(AuxHeader) < AuxSize) {
141 printBinary(
142 "Extra raw data",
143 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
144 sizeof(AuxHeader),
145 AuxSize - sizeof(AuxHeader)));
149 void XCOFFDumper::printAuxiliaryHeader(
150 const XCOFFAuxiliaryHeader32 *AuxHeader) {
151 if (AuxHeader == nullptr)
152 return;
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,
159 auto &Member) {
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);
173 PrintAuxMember(
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) <=
193 AuxSize) {
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)
210 return;
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,
217 auto &Member) {
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);
228 PrintAuxMember(
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) <=
245 AuxSize) {
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() {
266 Width = 20;
267 outs() << "\n---File Header:\n";
268 printHex("Magic:", Obj.getMagic());
269 printNumber("NumberOfSections:", Obj.getNumberOfSections());
271 int32_t Timestamp = Obj.getTimeStamp();
272 if (Timestamp > 0) {
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);
286 } else {
287 // Negative timestamp values are reserved for future use.
288 printStrHex("Timestamp:", Timestamp == 0 ? "None" : "Reserved Value",
289 Timestamp);
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
294 // objects.
295 if (Obj.is64Bit()) {
296 printHex("SymbolTableOffset:", Obj.getSymbolTableOffset64());
297 printNumber("SymbolTableEntries:", Obj.getNumberOfSymbolTableEntries64());
298 } else {
299 printHex("SymbolTableOffset:", Obj.getSymbolTableOffset32());
300 int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
301 if (SymTabEntries >= 0)
302 printNumber("SymbolTableEntries:", SymTabEntries);
303 else
304 printStrHex("SymbolTableEntries:", "Reserved Value", SymTabEntries);
307 printHex("OptionalHeaderSize:", Obj.getOptionalHeaderSize());
308 printHex("Flags:", Obj.getFlags());
311 } // namespace
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();
329 if (!SymNameOrErr)
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())
347 return std::nullopt;
349 auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
350 if (!CsectAuxEntOrErr)
351 return std::nullopt;
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())
361 return std::nullopt;
363 Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
364 if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())
365 return std::nullopt;
366 uint32_t Idx =
367 static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());
368 DataRefImpl DRI;
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())
376 return false;
378 auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
379 if (!CsectAuxEntOrErr)
380 return false;
382 return CsectAuxEntOrErr.get().isLabel();
385 std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
386 StringRef SymbolName) {
387 assert(SymbolInfo.isXCOFF() && "Must be a XCOFFSymInfo.");
389 std::string Result;
390 // Dummy symbols have no symbol index.
391 if (SymbolInfo.XCOFFSymInfo.Index)
392 Result =
393 ("(idx: " + Twine(*SymbolInfo.XCOFFSymInfo.Index) + ") " + SymbolName)
394 .str();
395 else
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());
405 return Result;
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()) { \
417 OS << '\n'; \
418 printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI); \
419 Index += 4; \
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) {
427 uint64_t Index = 0;
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";
432 Index += 4;
434 uint64_t Size = End - Address;
435 bool Is64Bit = Obj->is64Bit();
437 // XCOFFTracebackTable::create modifies the size parameter, so ensure Size
438 // isn't changed.
439 uint64_t SizeCopy = End - Address;
440 Expected<XCOFFTracebackTable> TTOrErr =
441 XCOFFTracebackTable::create(Bytes.data() + Index, SizeCopy, Is64Bit);
443 if (!TTOrErr) {
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)
457 LastNonZero = Size;
459 formatted_raw_ostream FOS(WarningStream);
460 while (Index < LastNonZero) {
461 printRawData(Bytes.slice(Index, 4), Address + Index, FOS, STI);
462 Index += 4;
463 WarningStream << '\n';
466 // Print all remaining zeroes as ...
467 if (Size - LastNonZero >= 8)
468 WarningStream << "\t\t...\n";
470 reportWarning(WarningMsgStr, Obj->getFileName());
471 return;
474 auto PrintBytes = [&](uint64_t N) {
475 printRawData(Bytes.slice(Index, N), Address + Index, OS, STI);
476 Index += N;
479 XCOFFTracebackTable TbTable = *TTOrErr;
480 // Print the first of the 8 bytes of mandatory fields.
481 PrintBytes(1);
482 OS << format("\t# Version = %i", TbTable.getVersion()) << '\n';
484 // Print the second of the 8 bytes of mandatory fields.
485 PrintBytes(1);
486 TracebackTable::LanguageID LangId =
487 static_cast<TracebackTable::LanguageID>(TbTable.getLanguageID());
488 OS << "\t# Language = " << getNameForTracebackTableLanguageId(LangId) << '\n';
490 auto Split = [&]() {
491 OS << '\n';
492 OS.indent(TabStop);
495 // Print the third of the 8 bytes of mandatory fields.
496 PrintBytes(1);
497 PRINTBOOL("\t#", TbTable, isGlobalLinkage);
498 PRINTBOOL(",", TbTable, isOutOfLineEpilogOrPrologue);
499 Split();
500 PRINTBOOL("\t ", TbTable, hasTraceBackTableOffset);
501 PRINTBOOL(",", TbTable, isInternalProcedure);
502 Split();
503 PRINTBOOL("\t ", TbTable, hasControlledStorage);
504 PRINTBOOL(",", TbTable, isTOCless);
505 Split();
506 PRINTBOOL("\t ", TbTable, isFloatingPointPresent);
507 Split();
508 PRINTBOOL("\t ", TbTable, isFloatingPointOperationLogOrAbortEnabled);
509 OS << '\n';
511 // Print the 4th of the 8 bytes of mandatory fields.
512 PrintBytes(1);
513 PRINTBOOL("\t#", TbTable, isInterruptHandler);
514 PRINTBOOL(",", TbTable, isFuncNamePresent);
515 PRINTBOOL(",", TbTable, isAllocaUsed);
516 Split();
517 PRINTGET("\t ", TbTable, OnConditionDirective);
518 PRINTBOOL(",", TbTable, isCRSaved);
519 PRINTBOOL(",", TbTable, isLRSaved);
520 OS << '\n';
522 // Print the 5th of the 8 bytes of mandatory fields.
523 PrintBytes(1);
524 PRINTBOOL("\t#", TbTable, isBackChainStored);
525 PRINTBOOL(",", TbTable, isFixup);
526 PRINTGET(",", TbTable, NumOfFPRsSaved);
527 OS << '\n';
529 // Print the 6th of the 8 bytes of mandatory fields.
530 PrintBytes(1);
531 PRINTBOOL("\t#", TbTable, hasExtensionTable);
532 PRINTBOOL(",", TbTable, hasVectorInfo);
533 PRINTGET(",", TbTable, NumOfGPRsSaved);
534 OS << '\n';
536 // Print the 7th of the 8 bytes of mandatory fields.
537 PrintBytes(1);
538 PRINTGET("\t#", TbTable, NumberOfFixedParms);
539 OS << '\n';
541 // Print the 8th of the 8 bytes of mandatory fields.
542 PrintBytes(1);
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) {
554 OS << '\n';
555 PrintBytes(4);
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) {
565 OS << '\n';
566 reportWarning(
567 "the length of the function name must be greater than zero if the "
568 "isFuncNamePresent bit is set in the traceback table",
569 Obj->getFileName());
570 return;
573 OS << '\n';
574 PrintBytes(2);
575 OS << "\t# FunctionNameLen = " << FunctionNameLen;
577 uint16_t RemainingBytes = FunctionNameLen;
578 bool HasPrinted = false;
579 while (RemainingBytes > 0) {
580 OS << '\n';
581 uint16_t PrintLen = RemainingBytes >= 4 ? 4 : RemainingBytes;
582 printRawData(Bytes.slice(Index, PrintLen), Address + Index, OS, STI);
583 Index += PrintLen;
584 RemainingBytes -= PrintLen;
586 if (!HasPrinted) {
587 OS << "\t# FunctionName = " << *TbTable.getFunctionName();
588 HasPrinted = true;
593 if (TbTable.isAllocaUsed()) {
594 OS << '\n';
595 PrintBytes(1);
596 OS << format("\t# AllocaRegister = %u", *TbTable.getAllocaRegister());
599 if (TbTable.getVectorExt()) {
600 OS << '\n';
601 TBVectorExt VecExt = *TbTable.getVectorExt();
602 // Print first byte of VectorExt.
603 PrintBytes(1);
604 PRINTGET("\t#", VecExt, NumberOfVRSaved);
605 PRINTBOOL(",", VecExt, isVRSavedOnStack);
606 PRINTBOOL(",", VecExt, hasVarArgs);
607 OS << '\n';
609 // Print the second byte of VectorExt.
610 PrintBytes(1);
611 PRINTGET("\t#", VecExt, NumberOfVectorParms);
612 PRINTBOOL(",", VecExt, hasVMXInstruction);
613 OS << '\n';
615 PrintBytes(4);
616 OS << "\t# VectorParmsInfoString = " << VecExt.getVectorParmsInfo();
618 // There are two bytes of padding after vector info.
619 OS << '\n';
620 PrintBytes(2);
621 OS << "\t# Padding";
624 if (TbTable.getExtensionTable()) {
625 OS << '\n';
626 PrintBytes(1);
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.
634 if (Index % 4) {
635 OS << '\n';
636 PrintBytes(4 - Index % 4);
637 OS << "\t# Alignment padding for eh info displacement";
639 OS << '\n';
640 // The size of the displacement (address) is 4 bytes in 32-bit object files,
641 // and 8 bytes in 64-bit object files.
642 PrintBytes(4);
643 OS << "\t# EH info displacement";
644 if (Is64Bit) {
645 OS << '\n';
646 PrintBytes(4);
650 OS << '\n';
651 if (End == Address + Index)
652 return;
654 Size = End - Address;
656 const char *LineSuffix = "\t# Padding\n";
657 auto IsWordZero = [&](uint64_t WordPos) {
658 if (WordPos >= Size)
659 return false;
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;
669 while (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) {
675 // Print the line.
676 printRawData(Bytes.slice(Index, LineLength), Address + Index, OS, STI);
677 OS << LineSuffix;
678 LineSuffix = "\n";
681 Index += LineLength;
682 if (Index == Size)
683 return;
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]) {
688 if (ShouldPrintLine)
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);
700 #undef PRINTBOOL
701 #undef PRINTGET
702 #undef PRINTOPTIONAL