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