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) {} 355f757f3fSDimitry 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, 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> 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> 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 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 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 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