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