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" 17*06c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 185ffd83dbSDimitry Andric #include "llvm/Demangle/Demangle.h" 19*06c3fb27SDimitry Andric #include "llvm/MC/MCInstPrinter.h" 20*06c3fb27SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 21*06c3fb27SDimitry Andric #include "llvm/Support/Casting.h" 22*06c3fb27SDimitry Andric #include "llvm/Support/Endian.h" 23*06c3fb27SDimitry Andric #include "llvm/Support/FormattedStream.h" 24*06c3fb27SDimitry Andric #include <algorithm> 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric using namespace llvm; 275ffd83dbSDimitry Andric using namespace llvm::object; 28*06c3fb27SDimitry Andric using namespace llvm::XCOFF; 29*06c3fb27SDimitry Andric using namespace llvm::support; 30*06c3fb27SDimitry Andric 31*06c3fb27SDimitry Andric namespace { 32*06c3fb27SDimitry Andric class XCOFFDumper : public objdump::Dumper { 33*06c3fb27SDimitry Andric public: 34*06c3fb27SDimitry Andric XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {} 35*06c3fb27SDimitry Andric void printPrivateHeaders(bool MachOOnlyFirst) override; 36*06c3fb27SDimitry Andric }; 37*06c3fb27SDimitry Andric } // namespace 38*06c3fb27SDimitry Andric 39*06c3fb27SDimitry Andric std::unique_ptr<objdump::Dumper> 40*06c3fb27SDimitry Andric objdump::createXCOFFDumper(const object::XCOFFObjectFile &Obj) { 41*06c3fb27SDimitry Andric return std::make_unique<XCOFFDumper>(Obj); 42*06c3fb27SDimitry Andric } 43*06c3fb27SDimitry Andric 44*06c3fb27SDimitry Andric void XCOFFDumper::printPrivateHeaders(bool) {} 455ffd83dbSDimitry Andric 46753f127fSDimitry Andric Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj, 475ffd83dbSDimitry Andric const RelocationRef &Rel, 485ffd83dbSDimitry Andric SmallVectorImpl<char> &Result) { 495ffd83dbSDimitry Andric symbol_iterator SymI = Rel.getSymbol(); 50753f127fSDimitry Andric if (SymI == Obj.symbol_end()) 515ffd83dbSDimitry Andric return make_error<GenericBinaryError>( 525ffd83dbSDimitry Andric "invalid symbol reference in relocation entry", 535ffd83dbSDimitry Andric object_error::parse_failed); 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric Expected<StringRef> SymNameOrErr = SymI->getName(); 565ffd83dbSDimitry Andric if (!SymNameOrErr) 575ffd83dbSDimitry Andric return SymNameOrErr.takeError(); 585ffd83dbSDimitry Andric 59*06c3fb27SDimitry Andric std::string SymName = 60*06c3fb27SDimitry Andric Demangle ? demangle(*SymNameOrErr) : SymNameOrErr->str(); 615ffd83dbSDimitry Andric if (SymbolDescription) 625ffd83dbSDimitry Andric SymName = getXCOFFSymbolDescription(createSymbolInfo(Obj, *SymI), SymName); 635ffd83dbSDimitry Andric 645ffd83dbSDimitry Andric Result.append(SymName.begin(), SymName.end()); 655ffd83dbSDimitry Andric return Error::success(); 665ffd83dbSDimitry Andric } 675ffd83dbSDimitry Andric 68bdd1243dSDimitry Andric std::optional<XCOFF::StorageMappingClass> 69753f127fSDimitry Andric objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile &Obj, 705ffd83dbSDimitry Andric const SymbolRef &Sym) { 71753f127fSDimitry Andric const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl()); 725ffd83dbSDimitry Andric 73fe6060f1SDimitry Andric if (!SymRef.isCsectSymbol()) 74bdd1243dSDimitry Andric return std::nullopt; 75fe6060f1SDimitry Andric 76fe6060f1SDimitry Andric auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef(); 77fe6060f1SDimitry Andric if (!CsectAuxEntOrErr) 78bdd1243dSDimitry Andric return std::nullopt; 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric return CsectAuxEntOrErr.get().getStorageMappingClass(); 815ffd83dbSDimitry Andric } 825ffd83dbSDimitry Andric 83bdd1243dSDimitry Andric std::optional<object::SymbolRef> 84753f127fSDimitry Andric objdump::getXCOFFSymbolContainingSymbolRef(const XCOFFObjectFile &Obj, 85349cc55cSDimitry Andric const SymbolRef &Sym) { 86753f127fSDimitry Andric const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl()); 87349cc55cSDimitry Andric if (!SymRef.isCsectSymbol()) 88bdd1243dSDimitry Andric return std::nullopt; 89349cc55cSDimitry Andric 90349cc55cSDimitry Andric Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef(); 91349cc55cSDimitry Andric if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel()) 92bdd1243dSDimitry Andric return std::nullopt; 93349cc55cSDimitry Andric uint32_t Idx = 94349cc55cSDimitry Andric static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength()); 95349cc55cSDimitry Andric DataRefImpl DRI; 96753f127fSDimitry Andric DRI.p = Obj.getSymbolByIndex(Idx); 97753f127fSDimitry Andric return SymbolRef(DRI, &Obj); 98349cc55cSDimitry Andric } 99349cc55cSDimitry Andric 100753f127fSDimitry Andric bool objdump::isLabel(const XCOFFObjectFile &Obj, const SymbolRef &Sym) { 101753f127fSDimitry Andric const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl()); 102fe6060f1SDimitry Andric if (!SymRef.isCsectSymbol()) 1035ffd83dbSDimitry Andric return false; 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef(); 106fe6060f1SDimitry Andric if (!CsectAuxEntOrErr) 107fe6060f1SDimitry Andric return false; 108fe6060f1SDimitry Andric 109fe6060f1SDimitry Andric return CsectAuxEntOrErr.get().isLabel(); 1105ffd83dbSDimitry Andric } 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo, 1135ffd83dbSDimitry Andric StringRef SymbolName) { 1145ffd83dbSDimitry Andric assert(SymbolInfo.isXCOFF() && "Must be a XCOFFSymInfo."); 1155ffd83dbSDimitry Andric 1165ffd83dbSDimitry Andric std::string Result; 1175ffd83dbSDimitry Andric // Dummy symbols have no symbol index. 1185ffd83dbSDimitry Andric if (SymbolInfo.XCOFFSymInfo.Index) 119bdd1243dSDimitry Andric Result = 120bdd1243dSDimitry Andric ("(idx: " + Twine(*SymbolInfo.XCOFFSymInfo.Index) + ") " + SymbolName) 1215ffd83dbSDimitry Andric .str(); 1225ffd83dbSDimitry Andric else 1235ffd83dbSDimitry Andric Result.append(SymbolName.begin(), SymbolName.end()); 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric if (SymbolInfo.XCOFFSymInfo.StorageMappingClass && 1265ffd83dbSDimitry Andric !SymbolInfo.XCOFFSymInfo.IsLabel) { 1275ffd83dbSDimitry Andric const XCOFF::StorageMappingClass Smc = 12881ad6265SDimitry Andric *SymbolInfo.XCOFFSymInfo.StorageMappingClass; 1295ffd83dbSDimitry Andric Result.append(("[" + XCOFF::getMappingClassString(Smc) + "]").str()); 1305ffd83dbSDimitry Andric } 1315ffd83dbSDimitry Andric 1325ffd83dbSDimitry Andric return Result; 1335ffd83dbSDimitry Andric } 134*06c3fb27SDimitry Andric 135*06c3fb27SDimitry Andric #define PRINTBOOL(Prefix, Obj, Field) \ 136*06c3fb27SDimitry Andric OS << Prefix << " " << ((Obj.Field()) ? "+" : "-") << #Field 137*06c3fb27SDimitry Andric 138*06c3fb27SDimitry Andric #define PRINTGET(Prefix, Obj, Field) \ 139*06c3fb27SDimitry Andric OS << Prefix << " " << #Field << " = " \ 140*06c3fb27SDimitry Andric << static_cast<unsigned>(Obj.get##Field()) 141*06c3fb27SDimitry Andric 142*06c3fb27SDimitry Andric #define PRINTOPTIONAL(Field) \ 143*06c3fb27SDimitry Andric if (TbTable.get##Field()) { \ 144*06c3fb27SDimitry Andric OS << '\n'; \ 145*06c3fb27SDimitry Andric printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI); \ 146*06c3fb27SDimitry Andric Index += 4; \ 147*06c3fb27SDimitry Andric OS << "\t# " << #Field << " = " << *TbTable.get##Field(); \ 148*06c3fb27SDimitry Andric } 149*06c3fb27SDimitry Andric 150*06c3fb27SDimitry Andric void objdump::dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address, 151*06c3fb27SDimitry Andric formatted_raw_ostream &OS, uint64_t End, 152*06c3fb27SDimitry Andric const MCSubtargetInfo &STI, 153*06c3fb27SDimitry Andric const XCOFFObjectFile *Obj) { 154*06c3fb27SDimitry Andric uint64_t Index = 0; 155*06c3fb27SDimitry Andric unsigned TabStop = getInstStartColumn(STI) - 1; 156*06c3fb27SDimitry Andric // Print traceback table boundary. 157*06c3fb27SDimitry Andric printRawData(Bytes.slice(Index, 4), Address, OS, STI); 158*06c3fb27SDimitry Andric OS << "\t# Traceback table start\n"; 159*06c3fb27SDimitry Andric Index += 4; 160*06c3fb27SDimitry Andric 161*06c3fb27SDimitry Andric uint64_t Size = End - Address; 162*06c3fb27SDimitry Andric bool Is64Bit = Obj->is64Bit(); 163*06c3fb27SDimitry Andric 164*06c3fb27SDimitry Andric // XCOFFTracebackTable::create modifies the size parameter, so ensure Size 165*06c3fb27SDimitry Andric // isn't changed. 166*06c3fb27SDimitry Andric uint64_t SizeCopy = End - Address; 167*06c3fb27SDimitry Andric Expected<XCOFFTracebackTable> TTOrErr = 168*06c3fb27SDimitry Andric XCOFFTracebackTable::create(Bytes.data() + Index, SizeCopy, Is64Bit); 169*06c3fb27SDimitry Andric 170*06c3fb27SDimitry Andric if (!TTOrErr) { 171*06c3fb27SDimitry Andric std::string WarningMsgStr; 172*06c3fb27SDimitry Andric raw_string_ostream WarningStream(WarningMsgStr); 173*06c3fb27SDimitry Andric WarningStream << "failure parsing traceback table with address: 0x" 174*06c3fb27SDimitry Andric << utohexstr(Address) + "\n>>> " 175*06c3fb27SDimitry Andric << toString(TTOrErr.takeError()) 176*06c3fb27SDimitry Andric << "\n>>> Raw traceback table data is:\n"; 177*06c3fb27SDimitry Andric 178*06c3fb27SDimitry Andric uint64_t LastNonZero = Index; 179*06c3fb27SDimitry Andric for (uint64_t I = Index; I < Size; I += 4) 180*06c3fb27SDimitry Andric if (support::endian::read32be(Bytes.slice(I, 4).data()) != 0) 181*06c3fb27SDimitry Andric LastNonZero = I + 4 > Size ? Size : I + 4; 182*06c3fb27SDimitry Andric 183*06c3fb27SDimitry Andric if (Size - LastNonZero <= 4) 184*06c3fb27SDimitry Andric LastNonZero = Size; 185*06c3fb27SDimitry Andric 186*06c3fb27SDimitry Andric formatted_raw_ostream FOS(WarningStream); 187*06c3fb27SDimitry Andric while (Index < LastNonZero) { 188*06c3fb27SDimitry Andric printRawData(Bytes.slice(Index, 4), Address + Index, FOS, STI); 189*06c3fb27SDimitry Andric Index += 4; 190*06c3fb27SDimitry Andric WarningStream << '\n'; 191*06c3fb27SDimitry Andric } 192*06c3fb27SDimitry Andric 193*06c3fb27SDimitry Andric // Print all remaining zeroes as ... 194*06c3fb27SDimitry Andric if (Size - LastNonZero >= 8) 195*06c3fb27SDimitry Andric WarningStream << "\t\t...\n"; 196*06c3fb27SDimitry Andric 197*06c3fb27SDimitry Andric reportWarning(WarningMsgStr, Obj->getFileName()); 198*06c3fb27SDimitry Andric return; 199*06c3fb27SDimitry Andric } 200*06c3fb27SDimitry Andric 201*06c3fb27SDimitry Andric auto PrintBytes = [&](uint64_t N) { 202*06c3fb27SDimitry Andric printRawData(Bytes.slice(Index, N), Address + Index, OS, STI); 203*06c3fb27SDimitry Andric Index += N; 204*06c3fb27SDimitry Andric }; 205*06c3fb27SDimitry Andric 206*06c3fb27SDimitry Andric XCOFFTracebackTable TbTable = *TTOrErr; 207*06c3fb27SDimitry Andric // Print the first of the 8 bytes of mandatory fields. 208*06c3fb27SDimitry Andric PrintBytes(1); 209*06c3fb27SDimitry Andric OS << format("\t# Version = %i", TbTable.getVersion()) << '\n'; 210*06c3fb27SDimitry Andric 211*06c3fb27SDimitry Andric // Print the second of the 8 bytes of mandatory fields. 212*06c3fb27SDimitry Andric PrintBytes(1); 213*06c3fb27SDimitry Andric TracebackTable::LanguageID LangId = 214*06c3fb27SDimitry Andric static_cast<TracebackTable::LanguageID>(TbTable.getLanguageID()); 215*06c3fb27SDimitry Andric OS << "\t# Language = " << getNameForTracebackTableLanguageId(LangId) << '\n'; 216*06c3fb27SDimitry Andric 217*06c3fb27SDimitry Andric auto Split = [&]() { 218*06c3fb27SDimitry Andric OS << '\n'; 219*06c3fb27SDimitry Andric OS.indent(TabStop); 220*06c3fb27SDimitry Andric }; 221*06c3fb27SDimitry Andric 222*06c3fb27SDimitry Andric // Print the third of the 8 bytes of mandatory fields. 223*06c3fb27SDimitry Andric PrintBytes(1); 224*06c3fb27SDimitry Andric PRINTBOOL("\t#", TbTable, isGlobalLinkage); 225*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isOutOfLineEpilogOrPrologue); 226*06c3fb27SDimitry Andric Split(); 227*06c3fb27SDimitry Andric PRINTBOOL("\t ", TbTable, hasTraceBackTableOffset); 228*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isInternalProcedure); 229*06c3fb27SDimitry Andric Split(); 230*06c3fb27SDimitry Andric PRINTBOOL("\t ", TbTable, hasControlledStorage); 231*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isTOCless); 232*06c3fb27SDimitry Andric Split(); 233*06c3fb27SDimitry Andric PRINTBOOL("\t ", TbTable, isFloatingPointPresent); 234*06c3fb27SDimitry Andric Split(); 235*06c3fb27SDimitry Andric PRINTBOOL("\t ", TbTable, isFloatingPointOperationLogOrAbortEnabled); 236*06c3fb27SDimitry Andric OS << '\n'; 237*06c3fb27SDimitry Andric 238*06c3fb27SDimitry Andric // Print the 4th of the 8 bytes of mandatory fields. 239*06c3fb27SDimitry Andric PrintBytes(1); 240*06c3fb27SDimitry Andric PRINTBOOL("\t#", TbTable, isInterruptHandler); 241*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isFuncNamePresent); 242*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isAllocaUsed); 243*06c3fb27SDimitry Andric Split(); 244*06c3fb27SDimitry Andric PRINTGET("\t ", TbTable, OnConditionDirective); 245*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isCRSaved); 246*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isLRSaved); 247*06c3fb27SDimitry Andric OS << '\n'; 248*06c3fb27SDimitry Andric 249*06c3fb27SDimitry Andric // Print the 5th of the 8 bytes of mandatory fields. 250*06c3fb27SDimitry Andric PrintBytes(1); 251*06c3fb27SDimitry Andric PRINTBOOL("\t#", TbTable, isBackChainStored); 252*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, isFixup); 253*06c3fb27SDimitry Andric PRINTGET(",", TbTable, NumOfFPRsSaved); 254*06c3fb27SDimitry Andric OS << '\n'; 255*06c3fb27SDimitry Andric 256*06c3fb27SDimitry Andric // Print the 6th of the 8 bytes of mandatory fields. 257*06c3fb27SDimitry Andric PrintBytes(1); 258*06c3fb27SDimitry Andric PRINTBOOL("\t#", TbTable, hasExtensionTable); 259*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, hasVectorInfo); 260*06c3fb27SDimitry Andric PRINTGET(",", TbTable, NumOfGPRsSaved); 261*06c3fb27SDimitry Andric OS << '\n'; 262*06c3fb27SDimitry Andric 263*06c3fb27SDimitry Andric // Print the 7th of the 8 bytes of mandatory fields. 264*06c3fb27SDimitry Andric PrintBytes(1); 265*06c3fb27SDimitry Andric PRINTGET("\t#", TbTable, NumberOfFixedParms); 266*06c3fb27SDimitry Andric OS << '\n'; 267*06c3fb27SDimitry Andric 268*06c3fb27SDimitry Andric // Print the 8th of the 8 bytes of mandatory fields. 269*06c3fb27SDimitry Andric PrintBytes(1); 270*06c3fb27SDimitry Andric PRINTGET("\t#", TbTable, NumberOfFPParms); 271*06c3fb27SDimitry Andric PRINTBOOL(",", TbTable, hasParmsOnStack); 272*06c3fb27SDimitry Andric 273*06c3fb27SDimitry Andric PRINTOPTIONAL(ParmsType); 274*06c3fb27SDimitry Andric PRINTOPTIONAL(TraceBackTableOffset); 275*06c3fb27SDimitry Andric PRINTOPTIONAL(HandlerMask); 276*06c3fb27SDimitry Andric PRINTOPTIONAL(NumOfCtlAnchors); 277*06c3fb27SDimitry Andric 278*06c3fb27SDimitry Andric if (TbTable.getControlledStorageInfoDisp()) { 279*06c3fb27SDimitry Andric SmallVector<uint32_t, 8> Disp = *TbTable.getControlledStorageInfoDisp(); 280*06c3fb27SDimitry Andric for (unsigned I = 0; I < Disp.size(); ++I) { 281*06c3fb27SDimitry Andric OS << '\n'; 282*06c3fb27SDimitry Andric PrintBytes(4); 283*06c3fb27SDimitry Andric OS << "\t" << (I ? " " : "#") << " ControlledStorageInfoDisp[" << I 284*06c3fb27SDimitry Andric << "] = " << Disp[I]; 285*06c3fb27SDimitry Andric } 286*06c3fb27SDimitry Andric } 287*06c3fb27SDimitry Andric 288*06c3fb27SDimitry Andric // If there is a name, print the function name and function name length. 289*06c3fb27SDimitry Andric if (TbTable.isFuncNamePresent()) { 290*06c3fb27SDimitry Andric uint16_t FunctionNameLen = TbTable.getFunctionName()->size(); 291*06c3fb27SDimitry Andric if (FunctionNameLen == 0) { 292*06c3fb27SDimitry Andric OS << '\n'; 293*06c3fb27SDimitry Andric reportWarning( 294*06c3fb27SDimitry Andric "the length of the function name must be greater than zero if the " 295*06c3fb27SDimitry Andric "isFuncNamePresent bit is set in the traceback table", 296*06c3fb27SDimitry Andric Obj->getFileName()); 297*06c3fb27SDimitry Andric return; 298*06c3fb27SDimitry Andric } 299*06c3fb27SDimitry Andric 300*06c3fb27SDimitry Andric OS << '\n'; 301*06c3fb27SDimitry Andric PrintBytes(2); 302*06c3fb27SDimitry Andric OS << "\t# FunctionNameLen = " << FunctionNameLen; 303*06c3fb27SDimitry Andric 304*06c3fb27SDimitry Andric uint16_t RemainingBytes = FunctionNameLen; 305*06c3fb27SDimitry Andric bool HasPrinted = false; 306*06c3fb27SDimitry Andric while (RemainingBytes > 0) { 307*06c3fb27SDimitry Andric OS << '\n'; 308*06c3fb27SDimitry Andric uint16_t PrintLen = RemainingBytes >= 4 ? 4 : RemainingBytes; 309*06c3fb27SDimitry Andric printRawData(Bytes.slice(Index, PrintLen), Address + Index, OS, STI); 310*06c3fb27SDimitry Andric Index += PrintLen; 311*06c3fb27SDimitry Andric RemainingBytes -= PrintLen; 312*06c3fb27SDimitry Andric 313*06c3fb27SDimitry Andric if (!HasPrinted) { 314*06c3fb27SDimitry Andric OS << "\t# FunctionName = " << *TbTable.getFunctionName(); 315*06c3fb27SDimitry Andric HasPrinted = true; 316*06c3fb27SDimitry Andric } 317*06c3fb27SDimitry Andric } 318*06c3fb27SDimitry Andric } 319*06c3fb27SDimitry Andric 320*06c3fb27SDimitry Andric if (TbTable.isAllocaUsed()) { 321*06c3fb27SDimitry Andric OS << '\n'; 322*06c3fb27SDimitry Andric PrintBytes(1); 323*06c3fb27SDimitry Andric OS << format("\t# AllocaRegister = %u", *TbTable.getAllocaRegister()); 324*06c3fb27SDimitry Andric } 325*06c3fb27SDimitry Andric 326*06c3fb27SDimitry Andric if (TbTable.getVectorExt()) { 327*06c3fb27SDimitry Andric OS << '\n'; 328*06c3fb27SDimitry Andric TBVectorExt VecExt = *TbTable.getVectorExt(); 329*06c3fb27SDimitry Andric // Print first byte of VectorExt. 330*06c3fb27SDimitry Andric PrintBytes(1); 331*06c3fb27SDimitry Andric PRINTGET("\t#", VecExt, NumberOfVRSaved); 332*06c3fb27SDimitry Andric PRINTBOOL(",", VecExt, isVRSavedOnStack); 333*06c3fb27SDimitry Andric PRINTBOOL(",", VecExt, hasVarArgs); 334*06c3fb27SDimitry Andric OS << '\n'; 335*06c3fb27SDimitry Andric 336*06c3fb27SDimitry Andric // Print the second byte of VectorExt. 337*06c3fb27SDimitry Andric PrintBytes(1); 338*06c3fb27SDimitry Andric PRINTGET("\t#", VecExt, NumberOfVectorParms); 339*06c3fb27SDimitry Andric PRINTBOOL(",", VecExt, hasVMXInstruction); 340*06c3fb27SDimitry Andric OS << '\n'; 341*06c3fb27SDimitry Andric 342*06c3fb27SDimitry Andric PrintBytes(4); 343*06c3fb27SDimitry Andric OS << "\t# VectorParmsInfoString = " << VecExt.getVectorParmsInfo(); 344*06c3fb27SDimitry Andric 345*06c3fb27SDimitry Andric // There are two bytes of padding after vector info. 346*06c3fb27SDimitry Andric OS << '\n'; 347*06c3fb27SDimitry Andric PrintBytes(2); 348*06c3fb27SDimitry Andric OS << "\t# Padding"; 349*06c3fb27SDimitry Andric } 350*06c3fb27SDimitry Andric 351*06c3fb27SDimitry Andric if (TbTable.getExtensionTable()) { 352*06c3fb27SDimitry Andric OS << '\n'; 353*06c3fb27SDimitry Andric PrintBytes(1); 354*06c3fb27SDimitry Andric ExtendedTBTableFlag Flag = 355*06c3fb27SDimitry Andric static_cast<ExtendedTBTableFlag>(*TbTable.getExtensionTable()); 356*06c3fb27SDimitry Andric OS << "\t# ExtensionTable = " << getExtendedTBTableFlagString(Flag); 357*06c3fb27SDimitry Andric } 358*06c3fb27SDimitry Andric 359*06c3fb27SDimitry Andric if (TbTable.getEhInfoDisp()) { 360*06c3fb27SDimitry Andric // There are 4 bytes alignment before eh info displacement. 361*06c3fb27SDimitry Andric if (Index % 4) { 362*06c3fb27SDimitry Andric OS << '\n'; 363*06c3fb27SDimitry Andric PrintBytes(4 - Index % 4); 364*06c3fb27SDimitry Andric OS << "\t# Alignment padding for eh info displacement"; 365*06c3fb27SDimitry Andric } 366*06c3fb27SDimitry Andric OS << '\n'; 367*06c3fb27SDimitry Andric // The size of the displacement (address) is 4 bytes in 32-bit object files, 368*06c3fb27SDimitry Andric // and 8 bytes in 64-bit object files. 369*06c3fb27SDimitry Andric PrintBytes(4); 370*06c3fb27SDimitry Andric OS << "\t# EH info displacement"; 371*06c3fb27SDimitry Andric if (Is64Bit) { 372*06c3fb27SDimitry Andric OS << '\n'; 373*06c3fb27SDimitry Andric PrintBytes(4); 374*06c3fb27SDimitry Andric } 375*06c3fb27SDimitry Andric } 376*06c3fb27SDimitry Andric 377*06c3fb27SDimitry Andric OS << '\n'; 378*06c3fb27SDimitry Andric if (End == Address + Index) 379*06c3fb27SDimitry Andric return; 380*06c3fb27SDimitry Andric 381*06c3fb27SDimitry Andric Size = End - Address; 382*06c3fb27SDimitry Andric 383*06c3fb27SDimitry Andric const char *LineSuffix = "\t# Padding\n"; 384*06c3fb27SDimitry Andric auto IsWordZero = [&](uint64_t WordPos) { 385*06c3fb27SDimitry Andric if (WordPos >= Size) 386*06c3fb27SDimitry Andric return false; 387*06c3fb27SDimitry Andric uint64_t LineLength = std::min(4 - WordPos % 4, Size - WordPos); 388*06c3fb27SDimitry Andric return std::all_of(Bytes.begin() + WordPos, 389*06c3fb27SDimitry Andric Bytes.begin() + WordPos + LineLength, 390*06c3fb27SDimitry Andric [](uint8_t Byte) { return Byte == 0; }); 391*06c3fb27SDimitry Andric }; 392*06c3fb27SDimitry Andric 393*06c3fb27SDimitry Andric bool AreWordsZero[] = {IsWordZero(Index), IsWordZero(alignTo(Index, 4) + 4), 394*06c3fb27SDimitry Andric IsWordZero(alignTo(Index, 4) + 8)}; 395*06c3fb27SDimitry Andric bool ShouldPrintLine = true; 396*06c3fb27SDimitry Andric while (true) { 397*06c3fb27SDimitry Andric // Determine the length of the line (4, except for the first line, which 398*06c3fb27SDimitry Andric // will be just enough to align to the word boundary, and the last line, 399*06c3fb27SDimitry Andric // which will be the remainder of the data). 400*06c3fb27SDimitry Andric uint64_t LineLength = std::min(4 - Index % 4, Size - Index); 401*06c3fb27SDimitry Andric if (ShouldPrintLine) { 402*06c3fb27SDimitry Andric // Print the line. 403*06c3fb27SDimitry Andric printRawData(Bytes.slice(Index, LineLength), Address + Index, OS, STI); 404*06c3fb27SDimitry Andric OS << LineSuffix; 405*06c3fb27SDimitry Andric LineSuffix = "\n"; 406*06c3fb27SDimitry Andric } 407*06c3fb27SDimitry Andric 408*06c3fb27SDimitry Andric Index += LineLength; 409*06c3fb27SDimitry Andric if (Index == Size) 410*06c3fb27SDimitry Andric return; 411*06c3fb27SDimitry Andric 412*06c3fb27SDimitry Andric // For 3 or more consecutive lines of zeros, skip all but the first one, and 413*06c3fb27SDimitry Andric // replace them with "...". 414*06c3fb27SDimitry Andric if (AreWordsZero[0] && AreWordsZero[1] && AreWordsZero[2]) { 415*06c3fb27SDimitry Andric if (ShouldPrintLine) 416*06c3fb27SDimitry Andric OS << std::string(8, ' ') << "...\n"; 417*06c3fb27SDimitry Andric ShouldPrintLine = false; 418*06c3fb27SDimitry Andric } else if (!AreWordsZero[1]) { 419*06c3fb27SDimitry Andric // We have reached the end of a skipped block of zeros. 420*06c3fb27SDimitry Andric ShouldPrintLine = true; 421*06c3fb27SDimitry Andric } 422*06c3fb27SDimitry Andric AreWordsZero[0] = AreWordsZero[1]; 423*06c3fb27SDimitry Andric AreWordsZero[1] = AreWordsZero[2]; 424*06c3fb27SDimitry Andric AreWordsZero[2] = IsWordZero(Index + 8); 425*06c3fb27SDimitry Andric } 426*06c3fb27SDimitry Andric } 427*06c3fb27SDimitry Andric #undef PRINTBOOL 428*06c3fb27SDimitry Andric #undef PRINTGET 429*06c3fb27SDimitry Andric #undef PRINTOPTIONAL 430