xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
15ffd83dbSDimitry Andric //===-- XCOFFDump.cpp - XCOFF-specific dumper -----------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric ///
95ffd83dbSDimitry Andric /// \file
105ffd83dbSDimitry Andric /// This file implements the XCOFF-specific dumper for llvm-objdump.
115ffd83dbSDimitry Andric ///
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "XCOFFDump.h"
155ffd83dbSDimitry Andric 
165ffd83dbSDimitry Andric #include "llvm-objdump.h"
1706c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
185ffd83dbSDimitry Andric #include "llvm/Demangle/Demangle.h"
1906c3fb27SDimitry Andric #include "llvm/MC/MCInstPrinter.h"
2006c3fb27SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
2106c3fb27SDimitry Andric #include "llvm/Support/Casting.h"
2206c3fb27SDimitry Andric #include "llvm/Support/Endian.h"
2306c3fb27SDimitry Andric #include "llvm/Support/FormattedStream.h"
2406c3fb27SDimitry Andric #include <algorithm>
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric using namespace llvm;
275ffd83dbSDimitry Andric using namespace llvm::object;
2806c3fb27SDimitry Andric using namespace llvm::XCOFF;
2906c3fb27SDimitry Andric using namespace llvm::support;
3006c3fb27SDimitry Andric 
3106c3fb27SDimitry Andric namespace {
3206c3fb27SDimitry Andric class XCOFFDumper : public objdump::Dumper {
3306c3fb27SDimitry Andric public:
3406c3fb27SDimitry Andric   XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {}
35*5f757f3fSDimitry Andric   void printPrivateHeaders() override {}
3606c3fb27SDimitry Andric };
3706c3fb27SDimitry Andric } // namespace
3806c3fb27SDimitry Andric 
3906c3fb27SDimitry Andric std::unique_ptr<objdump::Dumper>
4006c3fb27SDimitry Andric objdump::createXCOFFDumper(const object::XCOFFObjectFile &Obj) {
4106c3fb27SDimitry Andric   return std::make_unique<XCOFFDumper>(Obj);
4206c3fb27SDimitry Andric }
4306c3fb27SDimitry Andric 
44753f127fSDimitry Andric Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj,
455ffd83dbSDimitry Andric                                              const RelocationRef &Rel,
465ffd83dbSDimitry Andric                                              SmallVectorImpl<char> &Result) {
475ffd83dbSDimitry Andric   symbol_iterator SymI = Rel.getSymbol();
48753f127fSDimitry Andric   if (SymI == Obj.symbol_end())
495ffd83dbSDimitry Andric     return make_error<GenericBinaryError>(
505ffd83dbSDimitry Andric         "invalid symbol reference in relocation entry",
515ffd83dbSDimitry Andric         object_error::parse_failed);
525ffd83dbSDimitry Andric 
535ffd83dbSDimitry Andric   Expected<StringRef> SymNameOrErr = SymI->getName();
545ffd83dbSDimitry Andric   if (!SymNameOrErr)
555ffd83dbSDimitry Andric     return SymNameOrErr.takeError();
565ffd83dbSDimitry Andric 
5706c3fb27SDimitry Andric   std::string SymName =
5806c3fb27SDimitry Andric       Demangle ? demangle(*SymNameOrErr) : SymNameOrErr->str();
595ffd83dbSDimitry Andric   if (SymbolDescription)
605ffd83dbSDimitry Andric     SymName = getXCOFFSymbolDescription(createSymbolInfo(Obj, *SymI), SymName);
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric   Result.append(SymName.begin(), SymName.end());
635ffd83dbSDimitry Andric   return Error::success();
645ffd83dbSDimitry Andric }
655ffd83dbSDimitry Andric 
66bdd1243dSDimitry Andric std::optional<XCOFF::StorageMappingClass>
67753f127fSDimitry Andric objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile &Obj,
685ffd83dbSDimitry Andric                                 const SymbolRef &Sym) {
69753f127fSDimitry Andric   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
705ffd83dbSDimitry Andric 
71fe6060f1SDimitry Andric   if (!SymRef.isCsectSymbol())
72bdd1243dSDimitry Andric     return std::nullopt;
73fe6060f1SDimitry Andric 
74fe6060f1SDimitry Andric   auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
75fe6060f1SDimitry Andric   if (!CsectAuxEntOrErr)
76bdd1243dSDimitry Andric     return std::nullopt;
77fe6060f1SDimitry Andric 
78fe6060f1SDimitry Andric   return CsectAuxEntOrErr.get().getStorageMappingClass();
795ffd83dbSDimitry Andric }
805ffd83dbSDimitry Andric 
81bdd1243dSDimitry Andric std::optional<object::SymbolRef>
82753f127fSDimitry Andric objdump::getXCOFFSymbolContainingSymbolRef(const XCOFFObjectFile &Obj,
83349cc55cSDimitry Andric                                            const SymbolRef &Sym) {
84753f127fSDimitry Andric   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
85349cc55cSDimitry Andric   if (!SymRef.isCsectSymbol())
86bdd1243dSDimitry Andric     return std::nullopt;
87349cc55cSDimitry Andric 
88349cc55cSDimitry Andric   Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
89349cc55cSDimitry Andric   if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())
90bdd1243dSDimitry Andric     return std::nullopt;
91349cc55cSDimitry Andric   uint32_t Idx =
92349cc55cSDimitry Andric       static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());
93349cc55cSDimitry Andric   DataRefImpl DRI;
94753f127fSDimitry Andric   DRI.p = Obj.getSymbolByIndex(Idx);
95753f127fSDimitry Andric   return SymbolRef(DRI, &Obj);
96349cc55cSDimitry Andric }
97349cc55cSDimitry Andric 
98753f127fSDimitry Andric bool objdump::isLabel(const XCOFFObjectFile &Obj, const SymbolRef &Sym) {
99753f127fSDimitry Andric   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
100fe6060f1SDimitry Andric   if (!SymRef.isCsectSymbol())
1015ffd83dbSDimitry Andric     return false;
102fe6060f1SDimitry Andric 
103fe6060f1SDimitry Andric   auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
104fe6060f1SDimitry Andric   if (!CsectAuxEntOrErr)
105fe6060f1SDimitry Andric     return false;
106fe6060f1SDimitry Andric 
107fe6060f1SDimitry Andric   return CsectAuxEntOrErr.get().isLabel();
1085ffd83dbSDimitry Andric }
1095ffd83dbSDimitry Andric 
1105ffd83dbSDimitry Andric std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
1115ffd83dbSDimitry Andric                                                StringRef SymbolName) {
1125ffd83dbSDimitry Andric   assert(SymbolInfo.isXCOFF() && "Must be a XCOFFSymInfo.");
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric   std::string Result;
1155ffd83dbSDimitry Andric   // Dummy symbols have no symbol index.
1165ffd83dbSDimitry Andric   if (SymbolInfo.XCOFFSymInfo.Index)
117bdd1243dSDimitry Andric     Result =
118bdd1243dSDimitry Andric         ("(idx: " + Twine(*SymbolInfo.XCOFFSymInfo.Index) + ") " + SymbolName)
1195ffd83dbSDimitry Andric             .str();
1205ffd83dbSDimitry Andric   else
1215ffd83dbSDimitry Andric     Result.append(SymbolName.begin(), SymbolName.end());
1225ffd83dbSDimitry Andric 
1235ffd83dbSDimitry Andric   if (SymbolInfo.XCOFFSymInfo.StorageMappingClass &&
1245ffd83dbSDimitry Andric       !SymbolInfo.XCOFFSymInfo.IsLabel) {
1255ffd83dbSDimitry Andric     const XCOFF::StorageMappingClass Smc =
12681ad6265SDimitry Andric         *SymbolInfo.XCOFFSymInfo.StorageMappingClass;
1275ffd83dbSDimitry Andric     Result.append(("[" + XCOFF::getMappingClassString(Smc) + "]").str());
1285ffd83dbSDimitry Andric   }
1295ffd83dbSDimitry Andric 
1305ffd83dbSDimitry Andric   return Result;
1315ffd83dbSDimitry Andric }
13206c3fb27SDimitry Andric 
13306c3fb27SDimitry Andric #define PRINTBOOL(Prefix, Obj, Field)                                          \
13406c3fb27SDimitry Andric   OS << Prefix << " " << ((Obj.Field()) ? "+" : "-") << #Field
13506c3fb27SDimitry Andric 
13606c3fb27SDimitry Andric #define PRINTGET(Prefix, Obj, Field)                                           \
13706c3fb27SDimitry Andric   OS << Prefix << " " << #Field << " = "                                       \
13806c3fb27SDimitry Andric      << static_cast<unsigned>(Obj.get##Field())
13906c3fb27SDimitry Andric 
14006c3fb27SDimitry Andric #define PRINTOPTIONAL(Field)                                                   \
14106c3fb27SDimitry Andric   if (TbTable.get##Field()) {                                                  \
14206c3fb27SDimitry Andric     OS << '\n';                                                                \
14306c3fb27SDimitry Andric     printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI);             \
14406c3fb27SDimitry Andric     Index += 4;                                                                \
14506c3fb27SDimitry Andric     OS << "\t# " << #Field << " = " << *TbTable.get##Field();                  \
14606c3fb27SDimitry Andric   }
14706c3fb27SDimitry Andric 
14806c3fb27SDimitry Andric void objdump::dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,
14906c3fb27SDimitry Andric                                  formatted_raw_ostream &OS, uint64_t End,
15006c3fb27SDimitry Andric                                  const MCSubtargetInfo &STI,
15106c3fb27SDimitry Andric                                  const XCOFFObjectFile *Obj) {
15206c3fb27SDimitry Andric   uint64_t Index = 0;
15306c3fb27SDimitry Andric   unsigned TabStop = getInstStartColumn(STI) - 1;
15406c3fb27SDimitry Andric   // Print traceback table boundary.
15506c3fb27SDimitry Andric   printRawData(Bytes.slice(Index, 4), Address, OS, STI);
15606c3fb27SDimitry Andric   OS << "\t# Traceback table start\n";
15706c3fb27SDimitry Andric   Index += 4;
15806c3fb27SDimitry Andric 
15906c3fb27SDimitry Andric   uint64_t Size = End - Address;
16006c3fb27SDimitry Andric   bool Is64Bit = Obj->is64Bit();
16106c3fb27SDimitry Andric 
16206c3fb27SDimitry Andric   // XCOFFTracebackTable::create modifies the size parameter, so ensure Size
16306c3fb27SDimitry Andric   // isn't changed.
16406c3fb27SDimitry Andric   uint64_t SizeCopy = End - Address;
16506c3fb27SDimitry Andric   Expected<XCOFFTracebackTable> TTOrErr =
16606c3fb27SDimitry Andric       XCOFFTracebackTable::create(Bytes.data() + Index, SizeCopy, Is64Bit);
16706c3fb27SDimitry Andric 
16806c3fb27SDimitry Andric   if (!TTOrErr) {
16906c3fb27SDimitry Andric     std::string WarningMsgStr;
17006c3fb27SDimitry Andric     raw_string_ostream WarningStream(WarningMsgStr);
17106c3fb27SDimitry Andric     WarningStream << "failure parsing traceback table with address: 0x"
17206c3fb27SDimitry Andric                   << utohexstr(Address) + "\n>>> "
17306c3fb27SDimitry Andric                   << toString(TTOrErr.takeError())
17406c3fb27SDimitry Andric                   << "\n>>> Raw traceback table data is:\n";
17506c3fb27SDimitry Andric 
17606c3fb27SDimitry Andric     uint64_t LastNonZero = Index;
17706c3fb27SDimitry Andric     for (uint64_t I = Index; I < Size; I += 4)
17806c3fb27SDimitry Andric       if (support::endian::read32be(Bytes.slice(I, 4).data()) != 0)
17906c3fb27SDimitry Andric         LastNonZero = I + 4 > Size ? Size : I + 4;
18006c3fb27SDimitry Andric 
18106c3fb27SDimitry Andric     if (Size - LastNonZero <= 4)
18206c3fb27SDimitry Andric       LastNonZero = Size;
18306c3fb27SDimitry Andric 
18406c3fb27SDimitry Andric     formatted_raw_ostream FOS(WarningStream);
18506c3fb27SDimitry Andric     while (Index < LastNonZero) {
18606c3fb27SDimitry Andric       printRawData(Bytes.slice(Index, 4), Address + Index, FOS, STI);
18706c3fb27SDimitry Andric       Index += 4;
18806c3fb27SDimitry Andric       WarningStream << '\n';
18906c3fb27SDimitry Andric     }
19006c3fb27SDimitry Andric 
19106c3fb27SDimitry Andric     // Print all remaining zeroes as ...
19206c3fb27SDimitry Andric     if (Size - LastNonZero >= 8)
19306c3fb27SDimitry Andric       WarningStream << "\t\t...\n";
19406c3fb27SDimitry Andric 
19506c3fb27SDimitry Andric     reportWarning(WarningMsgStr, Obj->getFileName());
19606c3fb27SDimitry Andric     return;
19706c3fb27SDimitry Andric   }
19806c3fb27SDimitry Andric 
19906c3fb27SDimitry Andric   auto PrintBytes = [&](uint64_t N) {
20006c3fb27SDimitry Andric     printRawData(Bytes.slice(Index, N), Address + Index, OS, STI);
20106c3fb27SDimitry Andric     Index += N;
20206c3fb27SDimitry Andric   };
20306c3fb27SDimitry Andric 
20406c3fb27SDimitry Andric   XCOFFTracebackTable TbTable = *TTOrErr;
20506c3fb27SDimitry Andric   // Print the first of the 8 bytes of mandatory fields.
20606c3fb27SDimitry Andric   PrintBytes(1);
20706c3fb27SDimitry Andric   OS << format("\t# Version = %i", TbTable.getVersion()) << '\n';
20806c3fb27SDimitry Andric 
20906c3fb27SDimitry Andric   // Print the second of the 8 bytes of mandatory fields.
21006c3fb27SDimitry Andric   PrintBytes(1);
21106c3fb27SDimitry Andric   TracebackTable::LanguageID LangId =
21206c3fb27SDimitry Andric       static_cast<TracebackTable::LanguageID>(TbTable.getLanguageID());
21306c3fb27SDimitry Andric   OS << "\t# Language = " << getNameForTracebackTableLanguageId(LangId) << '\n';
21406c3fb27SDimitry Andric 
21506c3fb27SDimitry Andric   auto Split = [&]() {
21606c3fb27SDimitry Andric     OS << '\n';
21706c3fb27SDimitry Andric     OS.indent(TabStop);
21806c3fb27SDimitry Andric   };
21906c3fb27SDimitry Andric 
22006c3fb27SDimitry Andric   // Print the third of the 8 bytes of mandatory fields.
22106c3fb27SDimitry Andric   PrintBytes(1);
22206c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, isGlobalLinkage);
22306c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isOutOfLineEpilogOrPrologue);
22406c3fb27SDimitry Andric   Split();
22506c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, hasTraceBackTableOffset);
22606c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isInternalProcedure);
22706c3fb27SDimitry Andric   Split();
22806c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, hasControlledStorage);
22906c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isTOCless);
23006c3fb27SDimitry Andric   Split();
23106c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, isFloatingPointPresent);
23206c3fb27SDimitry Andric   Split();
23306c3fb27SDimitry Andric   PRINTBOOL("\t ", TbTable, isFloatingPointOperationLogOrAbortEnabled);
23406c3fb27SDimitry Andric   OS << '\n';
23506c3fb27SDimitry Andric 
23606c3fb27SDimitry Andric   // Print the 4th of the 8 bytes of mandatory fields.
23706c3fb27SDimitry Andric   PrintBytes(1);
23806c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, isInterruptHandler);
23906c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isFuncNamePresent);
24006c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isAllocaUsed);
24106c3fb27SDimitry Andric   Split();
24206c3fb27SDimitry Andric   PRINTGET("\t ", TbTable, OnConditionDirective);
24306c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isCRSaved);
24406c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isLRSaved);
24506c3fb27SDimitry Andric   OS << '\n';
24606c3fb27SDimitry Andric 
24706c3fb27SDimitry Andric   // Print the 5th of the 8 bytes of mandatory fields.
24806c3fb27SDimitry Andric   PrintBytes(1);
24906c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, isBackChainStored);
25006c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, isFixup);
25106c3fb27SDimitry Andric   PRINTGET(",", TbTable, NumOfFPRsSaved);
25206c3fb27SDimitry Andric   OS << '\n';
25306c3fb27SDimitry Andric 
25406c3fb27SDimitry Andric   // Print the 6th of the 8 bytes of mandatory fields.
25506c3fb27SDimitry Andric   PrintBytes(1);
25606c3fb27SDimitry Andric   PRINTBOOL("\t#", TbTable, hasExtensionTable);
25706c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, hasVectorInfo);
25806c3fb27SDimitry Andric   PRINTGET(",", TbTable, NumOfGPRsSaved);
25906c3fb27SDimitry Andric   OS << '\n';
26006c3fb27SDimitry Andric 
26106c3fb27SDimitry Andric   // Print the 7th of the 8 bytes of mandatory fields.
26206c3fb27SDimitry Andric   PrintBytes(1);
26306c3fb27SDimitry Andric   PRINTGET("\t#", TbTable, NumberOfFixedParms);
26406c3fb27SDimitry Andric   OS << '\n';
26506c3fb27SDimitry Andric 
26606c3fb27SDimitry Andric   // Print the 8th of the 8 bytes of mandatory fields.
26706c3fb27SDimitry Andric   PrintBytes(1);
26806c3fb27SDimitry Andric   PRINTGET("\t#", TbTable, NumberOfFPParms);
26906c3fb27SDimitry Andric   PRINTBOOL(",", TbTable, hasParmsOnStack);
27006c3fb27SDimitry Andric 
27106c3fb27SDimitry Andric   PRINTOPTIONAL(ParmsType);
27206c3fb27SDimitry Andric   PRINTOPTIONAL(TraceBackTableOffset);
27306c3fb27SDimitry Andric   PRINTOPTIONAL(HandlerMask);
27406c3fb27SDimitry Andric   PRINTOPTIONAL(NumOfCtlAnchors);
27506c3fb27SDimitry Andric 
27606c3fb27SDimitry Andric   if (TbTable.getControlledStorageInfoDisp()) {
27706c3fb27SDimitry Andric     SmallVector<uint32_t, 8> Disp = *TbTable.getControlledStorageInfoDisp();
27806c3fb27SDimitry Andric     for (unsigned I = 0; I < Disp.size(); ++I) {
27906c3fb27SDimitry Andric       OS << '\n';
28006c3fb27SDimitry Andric       PrintBytes(4);
28106c3fb27SDimitry Andric       OS << "\t" << (I ? " " : "#") << " ControlledStorageInfoDisp[" << I
28206c3fb27SDimitry Andric          << "] = " << Disp[I];
28306c3fb27SDimitry Andric     }
28406c3fb27SDimitry Andric   }
28506c3fb27SDimitry Andric 
28606c3fb27SDimitry Andric   // If there is a name, print the function name and function name length.
28706c3fb27SDimitry Andric   if (TbTable.isFuncNamePresent()) {
28806c3fb27SDimitry Andric     uint16_t FunctionNameLen = TbTable.getFunctionName()->size();
28906c3fb27SDimitry Andric     if (FunctionNameLen == 0) {
29006c3fb27SDimitry Andric       OS << '\n';
29106c3fb27SDimitry Andric       reportWarning(
29206c3fb27SDimitry Andric           "the length of the function name must be greater than zero if the "
29306c3fb27SDimitry Andric           "isFuncNamePresent bit is set in the traceback table",
29406c3fb27SDimitry Andric           Obj->getFileName());
29506c3fb27SDimitry Andric       return;
29606c3fb27SDimitry Andric     }
29706c3fb27SDimitry Andric 
29806c3fb27SDimitry Andric     OS << '\n';
29906c3fb27SDimitry Andric     PrintBytes(2);
30006c3fb27SDimitry Andric     OS << "\t# FunctionNameLen = " << FunctionNameLen;
30106c3fb27SDimitry Andric 
30206c3fb27SDimitry Andric     uint16_t RemainingBytes = FunctionNameLen;
30306c3fb27SDimitry Andric     bool HasPrinted = false;
30406c3fb27SDimitry Andric     while (RemainingBytes > 0) {
30506c3fb27SDimitry Andric       OS << '\n';
30606c3fb27SDimitry Andric       uint16_t PrintLen = RemainingBytes >= 4 ? 4 : RemainingBytes;
30706c3fb27SDimitry Andric       printRawData(Bytes.slice(Index, PrintLen), Address + Index, OS, STI);
30806c3fb27SDimitry Andric       Index += PrintLen;
30906c3fb27SDimitry Andric       RemainingBytes -= PrintLen;
31006c3fb27SDimitry Andric 
31106c3fb27SDimitry Andric       if (!HasPrinted) {
31206c3fb27SDimitry Andric         OS << "\t# FunctionName = " << *TbTable.getFunctionName();
31306c3fb27SDimitry Andric         HasPrinted = true;
31406c3fb27SDimitry Andric       }
31506c3fb27SDimitry Andric     }
31606c3fb27SDimitry Andric   }
31706c3fb27SDimitry Andric 
31806c3fb27SDimitry Andric   if (TbTable.isAllocaUsed()) {
31906c3fb27SDimitry Andric     OS << '\n';
32006c3fb27SDimitry Andric     PrintBytes(1);
32106c3fb27SDimitry Andric     OS << format("\t# AllocaRegister = %u", *TbTable.getAllocaRegister());
32206c3fb27SDimitry Andric   }
32306c3fb27SDimitry Andric 
32406c3fb27SDimitry Andric   if (TbTable.getVectorExt()) {
32506c3fb27SDimitry Andric     OS << '\n';
32606c3fb27SDimitry Andric     TBVectorExt VecExt = *TbTable.getVectorExt();
32706c3fb27SDimitry Andric     // Print first byte of VectorExt.
32806c3fb27SDimitry Andric     PrintBytes(1);
32906c3fb27SDimitry Andric     PRINTGET("\t#", VecExt, NumberOfVRSaved);
33006c3fb27SDimitry Andric     PRINTBOOL(",", VecExt, isVRSavedOnStack);
33106c3fb27SDimitry Andric     PRINTBOOL(",", VecExt, hasVarArgs);
33206c3fb27SDimitry Andric     OS << '\n';
33306c3fb27SDimitry Andric 
33406c3fb27SDimitry Andric     // Print the second byte of VectorExt.
33506c3fb27SDimitry Andric     PrintBytes(1);
33606c3fb27SDimitry Andric     PRINTGET("\t#", VecExt, NumberOfVectorParms);
33706c3fb27SDimitry Andric     PRINTBOOL(",", VecExt, hasVMXInstruction);
33806c3fb27SDimitry Andric     OS << '\n';
33906c3fb27SDimitry Andric 
34006c3fb27SDimitry Andric     PrintBytes(4);
34106c3fb27SDimitry Andric     OS << "\t# VectorParmsInfoString = " << VecExt.getVectorParmsInfo();
34206c3fb27SDimitry Andric 
34306c3fb27SDimitry Andric     // There are two bytes of padding after vector info.
34406c3fb27SDimitry Andric     OS << '\n';
34506c3fb27SDimitry Andric     PrintBytes(2);
34606c3fb27SDimitry Andric     OS << "\t# Padding";
34706c3fb27SDimitry Andric   }
34806c3fb27SDimitry Andric 
34906c3fb27SDimitry Andric   if (TbTable.getExtensionTable()) {
35006c3fb27SDimitry Andric     OS << '\n';
35106c3fb27SDimitry Andric     PrintBytes(1);
35206c3fb27SDimitry Andric     ExtendedTBTableFlag Flag =
35306c3fb27SDimitry Andric         static_cast<ExtendedTBTableFlag>(*TbTable.getExtensionTable());
35406c3fb27SDimitry Andric     OS << "\t# ExtensionTable = " << getExtendedTBTableFlagString(Flag);
35506c3fb27SDimitry Andric   }
35606c3fb27SDimitry Andric 
35706c3fb27SDimitry Andric   if (TbTable.getEhInfoDisp()) {
35806c3fb27SDimitry Andric     // There are 4 bytes alignment before eh info displacement.
35906c3fb27SDimitry Andric     if (Index % 4) {
36006c3fb27SDimitry Andric       OS << '\n';
36106c3fb27SDimitry Andric       PrintBytes(4 - Index % 4);
36206c3fb27SDimitry Andric       OS << "\t# Alignment padding for eh info displacement";
36306c3fb27SDimitry Andric     }
36406c3fb27SDimitry Andric     OS << '\n';
36506c3fb27SDimitry Andric     // The size of the displacement (address) is 4 bytes in 32-bit object files,
36606c3fb27SDimitry Andric     // and 8 bytes in 64-bit object files.
36706c3fb27SDimitry Andric     PrintBytes(4);
36806c3fb27SDimitry Andric     OS << "\t# EH info displacement";
36906c3fb27SDimitry Andric     if (Is64Bit) {
37006c3fb27SDimitry Andric       OS << '\n';
37106c3fb27SDimitry Andric       PrintBytes(4);
37206c3fb27SDimitry Andric     }
37306c3fb27SDimitry Andric   }
37406c3fb27SDimitry Andric 
37506c3fb27SDimitry Andric   OS << '\n';
37606c3fb27SDimitry Andric   if (End == Address + Index)
37706c3fb27SDimitry Andric     return;
37806c3fb27SDimitry Andric 
37906c3fb27SDimitry Andric   Size = End - Address;
38006c3fb27SDimitry Andric 
38106c3fb27SDimitry Andric   const char *LineSuffix = "\t# Padding\n";
38206c3fb27SDimitry Andric   auto IsWordZero = [&](uint64_t WordPos) {
38306c3fb27SDimitry Andric     if (WordPos >= Size)
38406c3fb27SDimitry Andric       return false;
38506c3fb27SDimitry Andric     uint64_t LineLength = std::min(4 - WordPos % 4, Size - WordPos);
38606c3fb27SDimitry Andric     return std::all_of(Bytes.begin() + WordPos,
38706c3fb27SDimitry Andric                        Bytes.begin() + WordPos + LineLength,
38806c3fb27SDimitry Andric                        [](uint8_t Byte) { return Byte == 0; });
38906c3fb27SDimitry Andric   };
39006c3fb27SDimitry Andric 
39106c3fb27SDimitry Andric   bool AreWordsZero[] = {IsWordZero(Index), IsWordZero(alignTo(Index, 4) + 4),
39206c3fb27SDimitry Andric                          IsWordZero(alignTo(Index, 4) + 8)};
39306c3fb27SDimitry Andric   bool ShouldPrintLine = true;
39406c3fb27SDimitry Andric   while (true) {
39506c3fb27SDimitry Andric     // Determine the length of the line (4, except for the first line, which
39606c3fb27SDimitry Andric     // will be just enough to align to the word boundary, and the last line,
39706c3fb27SDimitry Andric     // which will be the remainder of the data).
39806c3fb27SDimitry Andric     uint64_t LineLength = std::min(4 - Index % 4, Size - Index);
39906c3fb27SDimitry Andric     if (ShouldPrintLine) {
40006c3fb27SDimitry Andric       // Print the line.
40106c3fb27SDimitry Andric       printRawData(Bytes.slice(Index, LineLength), Address + Index, OS, STI);
40206c3fb27SDimitry Andric       OS << LineSuffix;
40306c3fb27SDimitry Andric       LineSuffix = "\n";
40406c3fb27SDimitry Andric     }
40506c3fb27SDimitry Andric 
40606c3fb27SDimitry Andric     Index += LineLength;
40706c3fb27SDimitry Andric     if (Index == Size)
40806c3fb27SDimitry Andric       return;
40906c3fb27SDimitry Andric 
41006c3fb27SDimitry Andric     // For 3 or more consecutive lines of zeros, skip all but the first one, and
41106c3fb27SDimitry Andric     // replace them with "...".
41206c3fb27SDimitry Andric     if (AreWordsZero[0] && AreWordsZero[1] && AreWordsZero[2]) {
41306c3fb27SDimitry Andric       if (ShouldPrintLine)
41406c3fb27SDimitry Andric         OS << std::string(8, ' ') << "...\n";
41506c3fb27SDimitry Andric       ShouldPrintLine = false;
41606c3fb27SDimitry Andric     } else if (!AreWordsZero[1]) {
41706c3fb27SDimitry Andric       // We have reached the end of a skipped block of zeros.
41806c3fb27SDimitry Andric       ShouldPrintLine = true;
41906c3fb27SDimitry Andric     }
42006c3fb27SDimitry Andric     AreWordsZero[0] = AreWordsZero[1];
42106c3fb27SDimitry Andric     AreWordsZero[1] = AreWordsZero[2];
42206c3fb27SDimitry Andric     AreWordsZero[2] = IsWordZero(Index + 8);
42306c3fb27SDimitry Andric   }
42406c3fb27SDimitry Andric }
42506c3fb27SDimitry Andric #undef PRINTBOOL
42606c3fb27SDimitry Andric #undef PRINTGET
42706c3fb27SDimitry Andric #undef PRINTOPTIONAL
428