brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.5 KiB · 61dd0b8 Raw
744 lines · cpp
1//===-- XCOFFDump.cpp - XCOFF-specific dumper -----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements the XCOFF-specific dumper for llvm-objdump.11///12//===----------------------------------------------------------------------===//13 14#include "XCOFFDump.h"15 16#include "llvm-objdump.h"17#include "llvm/ADT/StringExtras.h"18#include "llvm/Demangle/Demangle.h"19#include "llvm/MC/MCInstPrinter.h"20#include "llvm/MC/MCSubtargetInfo.h"21#include "llvm/Support/Endian.h"22#include "llvm/Support/Format.h"23#include "llvm/Support/FormattedStream.h"24#include "llvm/Support/raw_ostream.h"25#include <algorithm>26 27using namespace llvm;28using namespace llvm::object;29using namespace llvm::XCOFF;30using namespace llvm::support;31 32namespace {33class XCOFFDumper : public objdump::Dumper {34  enum PrintStyle { Hex, Number };35  const XCOFFObjectFile &Obj;36  unsigned Width;37 38public:39  XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O), Obj(O) {}40 41private:42  void printPrivateHeaders() override;43  void printFileHeader();44  void printAuxiliaryHeader();45  void printLoaderSectionHeader();46  void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);47  void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);48  template <typename AuxHeaderMemberType, typename XCOFFAuxiliaryHeader>49  void printAuxMemberHelper(PrintStyle Style, const char *MemberName,50                            const AuxHeaderMemberType &Member,51                            const XCOFFAuxiliaryHeader *AuxHeader,52                            uint16_t AuxSize, uint16_t &PartialFieldOffset,53                            const char *&PartialFieldName);54  template <typename XCOFFAuxiliaryHeader>55  void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,56                                        uint16_t PartialFieldOffset,57                                        uint16_t AuxSize,58                                        XCOFFAuxiliaryHeader &AuxHeader);59 60  void printBinary(StringRef Name, ArrayRef<uint8_t> Data);61  void printHex(StringRef Name, uint64_t Value);62  void printNumber(StringRef Name, uint64_t Value);63  FormattedString formatName(StringRef Name);64  void printStrHex(StringRef Name, StringRef Str, uint64_t Value);65};66 67void XCOFFDumper::printPrivateHeaders() {68  printFileHeader();69  printAuxiliaryHeader();70  printLoaderSectionHeader();71}72 73FormattedString XCOFFDumper::formatName(StringRef Name) {74  return FormattedString(Name, Width, FormattedString::JustifyLeft);75}76 77void XCOFFDumper::printHex(StringRef Name, uint64_t Value) {78  outs() << formatName(Name) << format_hex(Value, 0) << "\n";79}80 81void XCOFFDumper::printNumber(StringRef Name, uint64_t Value) {82  outs() << formatName(Name) << format_decimal(Value, 0) << "\n";83}84 85void XCOFFDumper::printStrHex(StringRef Name, StringRef Str, uint64_t Value) {86  outs() << formatName(Name) << Str << " (" << format_decimal(Value, 0)87         << ")\n";88}89 90void XCOFFDumper::printBinary(StringRef Name, ArrayRef<uint8_t> Data) {91  unsigned OrgWidth = Width;92  Width = 0;93  outs() << formatName(Name) << " (" << format_bytes(Data) << ")\n";94  Width = OrgWidth;95}96 97void XCOFFDumper::printAuxiliaryHeader() {98  Width = 36;99  if (Obj.is64Bit())100    printAuxiliaryHeader(Obj.auxiliaryHeader64());101  else102    printAuxiliaryHeader(Obj.auxiliaryHeader32());103}104 105template <typename AuxHeaderMemberType, typename XCOFFAuxiliaryHeader>106void XCOFFDumper::printAuxMemberHelper(PrintStyle Style, const char *MemberName,107                                       const AuxHeaderMemberType &Member,108                                       const XCOFFAuxiliaryHeader *AuxHeader,109                                       uint16_t AuxSize,110                                       uint16_t &PartialFieldOffset,111                                       const char *&PartialFieldName) {112  ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -113                     reinterpret_cast<const char *>(AuxHeader);114  if (Offset + sizeof(Member) <= AuxSize) {115    if (Style == Hex)116      printHex(MemberName, Member);117    else118      printNumber(MemberName, Member);119  } else if (Offset < AuxSize) {120    PartialFieldOffset = Offset;121    PartialFieldName = MemberName;122  }123}124 125template <typename XCOFFAuxiliaryHeader>126void XCOFFDumper::checkAndPrintAuxHeaderParseError(127    const char *PartialFieldName, uint16_t PartialFieldOffset, uint16_t AuxSize,128    XCOFFAuxiliaryHeader &AuxHeader) {129  if (PartialFieldOffset < AuxSize) {130    std::string Buf;131    raw_string_ostream OS(Buf);132    OS.flush();133    OS << FormattedString("Raw data", 0, FormattedString::JustifyLeft) << " ("134       << format_bytes(135              ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +136                                    PartialFieldOffset,137                                AuxSize - PartialFieldOffset))138       << ")\n";139    reportUniqueWarning(Twine("only partial field for ") + PartialFieldName +140                        " at offset (" + Twine(PartialFieldOffset) + ")\n" +141                        OS.str());142  } else if (sizeof(AuxHeader) < AuxSize) {143    printBinary(144        "Extra raw data",145        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +146                              sizeof(AuxHeader),147                          AuxSize - sizeof(AuxHeader)));148  }149}150 151void XCOFFDumper::printAuxiliaryHeader(152    const XCOFFAuxiliaryHeader32 *AuxHeader) {153  if (AuxHeader == nullptr)154    return;155  outs() << "\n---Auxiliary Header:\n";156  uint16_t AuxSize = Obj.getOptionalHeaderSize();157  uint16_t PartialFieldOffset = AuxSize;158  const char *PartialFieldName = nullptr;159 160  auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,161                            auto &Member) {162    printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,163                         PartialFieldOffset, PartialFieldName);164  };165 166  PrintAuxMember(Hex, "Magic:", AuxHeader->AuxMagic);167  PrintAuxMember(Hex, "Version:", AuxHeader->Version);168  PrintAuxMember(Hex, "Size of .text section:", AuxHeader->TextSize);169  PrintAuxMember(Hex, "Size of .data section:", AuxHeader->InitDataSize);170  PrintAuxMember(Hex, "Size of .bss section:", AuxHeader->BssDataSize);171  PrintAuxMember(Hex, "Entry point address:", AuxHeader->EntryPointAddr);172  PrintAuxMember(Hex, ".text section start address:", AuxHeader->TextStartAddr);173  PrintAuxMember(Hex, ".data section start address:", AuxHeader->DataStartAddr);174  PrintAuxMember(Hex, "TOC anchor address:", AuxHeader->TOCAnchorAddr);175  PrintAuxMember(176      Number, "Section number of entryPoint:", AuxHeader->SecNumOfEntryPoint);177  PrintAuxMember(Number, "Section number of .text:", AuxHeader->SecNumOfText);178  PrintAuxMember(Number, "Section number of .data:", AuxHeader->SecNumOfData);179  PrintAuxMember(Number, "Section number of TOC:", AuxHeader->SecNumOfTOC);180  PrintAuxMember(Number,181                 "Section number of loader data:", AuxHeader->SecNumOfLoader);182  PrintAuxMember(Number, "Section number of .bss:", AuxHeader->SecNumOfBSS);183  PrintAuxMember(Hex, "Maxium alignment of .text:", AuxHeader->MaxAlignOfText);184  PrintAuxMember(Hex, "Maxium alignment of .data:", AuxHeader->MaxAlignOfData);185  PrintAuxMember(Hex, "Module type:", AuxHeader->ModuleType);186  PrintAuxMember(Hex, "CPU type of objects:", AuxHeader->CpuFlag);187  PrintAuxMember(Hex, "Maximum stack size:", AuxHeader->MaxStackSize);188  PrintAuxMember(Hex, "Maximum data size:", AuxHeader->MaxDataSize);189  PrintAuxMember(Hex, "Reserved for debugger:", AuxHeader->ReservedForDebugger);190  PrintAuxMember(Hex, "Text page size:", AuxHeader->TextPageSize);191  PrintAuxMember(Hex, "Data page size:", AuxHeader->DataPageSize);192  PrintAuxMember(Hex, "Stack page size:", AuxHeader->StackPageSize);193  if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +194          sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=195      AuxSize) {196    printHex("Flag:", AuxHeader->getFlag());197    printHex("Alignment of thread-local storage:",198             AuxHeader->getTDataAlignment());199  }200 201  PrintAuxMember(Number,202                 "Section number for .tdata:", AuxHeader->SecNumOfTData);203  PrintAuxMember(Number, "Section number for .tbss:", AuxHeader->SecNumOfTBSS);204 205  checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,206                                   AuxSize, *AuxHeader);207}208 209void XCOFFDumper::printAuxiliaryHeader(210    const XCOFFAuxiliaryHeader64 *AuxHeader) {211  if (AuxHeader == nullptr)212    return;213  uint16_t AuxSize = Obj.getOptionalHeaderSize();214  outs() << "\n---Auxiliary Header:\n";215  uint16_t PartialFieldOffset = AuxSize;216  const char *PartialFieldName = nullptr;217 218  auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,219                            auto &Member) {220    printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,221                         PartialFieldOffset, PartialFieldName);222  };223 224  PrintAuxMember(Hex, "Magic:", AuxHeader->AuxMagic);225  PrintAuxMember(Hex, "Version:", AuxHeader->Version);226  PrintAuxMember(Hex, "Reserved for debugger:", AuxHeader->ReservedForDebugger);227  PrintAuxMember(Hex, ".text section start address:", AuxHeader->TextStartAddr);228  PrintAuxMember(Hex, ".data section start address:", AuxHeader->DataStartAddr);229  PrintAuxMember(Hex, "TOC anchor address:", AuxHeader->TOCAnchorAddr);230  PrintAuxMember(231      Number, "Section number of entryPoint:", AuxHeader->SecNumOfEntryPoint);232  PrintAuxMember(Number, "Section number of .text:", AuxHeader->SecNumOfText);233  PrintAuxMember(Number, "Section number of .data:", AuxHeader->SecNumOfData);234  PrintAuxMember(Number, "Section number of TOC:", AuxHeader->SecNumOfTOC);235  PrintAuxMember(Number,236                 "Section number of loader data:", AuxHeader->SecNumOfLoader);237  PrintAuxMember(Number, "Section number of .bss:", AuxHeader->SecNumOfBSS);238  PrintAuxMember(Hex, "Maxium alignment of .text:", AuxHeader->MaxAlignOfText);239  PrintAuxMember(Hex, "Maxium alignment of .data:", AuxHeader->MaxAlignOfData);240  PrintAuxMember(Hex, "Module type:", AuxHeader->ModuleType);241  PrintAuxMember(Hex, "CPU type of objects:", AuxHeader->CpuFlag);242  PrintAuxMember(Hex, "Text page size:", AuxHeader->TextPageSize);243  PrintAuxMember(Hex, "Data page size:", AuxHeader->DataPageSize);244  PrintAuxMember(Hex, "Stack page size:", AuxHeader->StackPageSize);245  if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +246          sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=247      AuxSize) {248    printHex("Flag:", AuxHeader->getFlag());249    printHex("Alignment of thread-local storage:",250             AuxHeader->getTDataAlignment());251  }252  PrintAuxMember(Hex, "Size of .text section:", AuxHeader->TextSize);253  PrintAuxMember(Hex, "Size of .data section:", AuxHeader->InitDataSize);254  PrintAuxMember(Hex, "Size of .bss section:", AuxHeader->BssDataSize);255  PrintAuxMember(Hex, "Entry point address:", AuxHeader->EntryPointAddr);256  PrintAuxMember(Hex, "Maximum stack size:", AuxHeader->MaxStackSize);257  PrintAuxMember(Hex, "Maximum data size:", AuxHeader->MaxDataSize);258  PrintAuxMember(Number,259                 "Section number for .tdata:", AuxHeader->SecNumOfTData);260  PrintAuxMember(Number, "Section number for .tbss:", AuxHeader->SecNumOfTBSS);261  PrintAuxMember(Hex, "Additional flags 64-bit XCOFF:", AuxHeader->XCOFF64Flag);262 263  checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,264                                   AuxSize, *AuxHeader);265}266 267void XCOFFDumper::printLoaderSectionHeader() {268  Expected<uintptr_t> LoaderSectionAddrOrError =269      Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);270  if (!LoaderSectionAddrOrError) {271    reportUniqueWarning(LoaderSectionAddrOrError.takeError());272    return;273  }274  uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();275 276  if (LoaderSectionAddr == 0)277    return;278 279  auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {280    printNumber("Version:", LDHeader->Version);281    printNumber("NumberOfSymbolEntries:", LDHeader->NumberOfSymTabEnt);282    printNumber("NumberOfRelocationEntries:", LDHeader->NumberOfRelTabEnt);283    printNumber("LengthOfImportFileIDStringTable:",284                LDHeader->LengthOfImpidStrTbl);285    printNumber("NumberOfImportFileIDs:", LDHeader->NumberOfImpid);286    printHex("OffsetToImportFileIDs:", LDHeader->OffsetToImpid);287    printNumber("LengthOfStringTable:", LDHeader->LengthOfStrTbl);288    printHex("OffsetToStringTable:", LDHeader->OffsetToStrTbl);289  };290 291  Width = 35;292  outs() << "\n---Loader Section Header:\n";293  if (Obj.is64Bit()) {294    const LoaderSectionHeader64 *LoaderSec64 =295        reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);296    PrintLoadSecHeaderCommon(LoaderSec64);297    printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);298    printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);299  } else {300    const LoaderSectionHeader32 *LoaderSec32 =301        reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);302    PrintLoadSecHeaderCommon(LoaderSec32);303  }304}305 306void XCOFFDumper::printFileHeader() {307  Width = 20;308  outs() << "\n---File Header:\n";309  printHex("Magic:", Obj.getMagic());310  printNumber("NumberOfSections:", Obj.getNumberOfSections());311 312  int32_t Timestamp = Obj.getTimeStamp();313  if (Timestamp > 0) {314    // This handling of the timestamp assumes that the host system's time_t is315    // compatible with AIX time_t. If a platform is not compatible, the lit316    // tests will let us know.317    time_t TimeDate = Timestamp;318 319    char FormattedTime[20] = {};320 321    size_t BytesFormatted = std::strftime(FormattedTime, sizeof(FormattedTime),322                                          "%F %T", std::gmtime(&TimeDate));323    assert(BytesFormatted && "The size of the buffer FormattedTime is less "324                             "than the size of the date/time string.");325    (void)BytesFormatted;326    printStrHex("Timestamp:", FormattedTime, Timestamp);327  } else {328    // Negative timestamp values are reserved for future use.329    printStrHex("Timestamp:", Timestamp == 0 ? "None" : "Reserved Value",330                Timestamp);331  }332 333  // The number of symbol table entries is an unsigned value in 64-bit objects334  // and a signed value (with negative values being 'reserved') in 32-bit335  // objects.336  if (Obj.is64Bit()) {337    printHex("SymbolTableOffset:", Obj.getSymbolTableOffset64());338    printNumber("SymbolTableEntries:", Obj.getNumberOfSymbolTableEntries64());339  } else {340    printHex("SymbolTableOffset:", Obj.getSymbolTableOffset32());341    int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();342    if (SymTabEntries >= 0)343      printNumber("SymbolTableEntries:", SymTabEntries);344    else345      printStrHex("SymbolTableEntries:", "Reserved Value", SymTabEntries);346  }347 348  printHex("OptionalHeaderSize:", Obj.getOptionalHeaderSize());349  printHex("Flags:", Obj.getFlags());350}351 352} // namespace353 354std::unique_ptr<objdump::Dumper>355objdump::createXCOFFDumper(const object::XCOFFObjectFile &Obj) {356  return std::make_unique<XCOFFDumper>(Obj);357}358 359Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj,360                                             const RelocationRef &Rel,361                                             bool SymbolDescription,362                                             SmallVectorImpl<char> &Result) {363  symbol_iterator SymI = Rel.getSymbol();364  if (SymI == Obj.symbol_end())365    return make_error<GenericBinaryError>(366        "invalid symbol reference in relocation entry",367        object_error::parse_failed);368 369  Expected<StringRef> SymNameOrErr = SymI->getName();370  if (!SymNameOrErr)371    return SymNameOrErr.takeError();372 373  std::string SymName =374      Demangle ? demangle(*SymNameOrErr) : SymNameOrErr->str();375  if (SymbolDescription)376    SymName = getXCOFFSymbolDescription(createSymbolInfo(Obj, *SymI), SymName);377 378  Result.append(SymName.begin(), SymName.end());379  return Error::success();380}381 382std::optional<XCOFF::StorageMappingClass>383objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile &Obj,384                                const SymbolRef &Sym) {385  const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());386 387  if (!SymRef.isCsectSymbol())388    return std::nullopt;389 390  auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();391  if (!CsectAuxEntOrErr)392    return std::nullopt;393 394  return CsectAuxEntOrErr.get().getStorageMappingClass();395}396 397std::optional<object::SymbolRef>398objdump::getXCOFFSymbolContainingSymbolRef(const XCOFFObjectFile &Obj,399                                           const SymbolRef &Sym) {400  const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());401  if (!SymRef.isCsectSymbol())402    return std::nullopt;403 404  Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();405  if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())406    return std::nullopt;407  uint32_t Idx =408      static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());409  DataRefImpl DRI;410  DRI.p = Obj.getSymbolByIndex(Idx);411  return SymbolRef(DRI, &Obj);412}413 414bool objdump::isLabel(const XCOFFObjectFile &Obj, const SymbolRef &Sym) {415  const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());416  if (!SymRef.isCsectSymbol())417    return false;418 419  auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();420  if (!CsectAuxEntOrErr)421    return false;422 423  return CsectAuxEntOrErr.get().isLabel();424}425 426std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,427                                               StringRef SymbolName) {428  assert(SymbolInfo.isXCOFF() && "Must be a XCOFFSymInfo.");429 430  std::string Result;431  // Dummy symbols have no symbol index.432  if (SymbolInfo.XCOFFSymInfo.Index)433    Result =434        ("(idx: " + Twine(*SymbolInfo.XCOFFSymInfo.Index) + ") " + SymbolName)435            .str();436  else437    Result.append(SymbolName.begin(), SymbolName.end());438 439  if (SymbolInfo.XCOFFSymInfo.StorageMappingClass &&440      !SymbolInfo.XCOFFSymInfo.IsLabel) {441    const XCOFF::StorageMappingClass Smc =442        *SymbolInfo.XCOFFSymInfo.StorageMappingClass;443    Result.append(("[" + XCOFF::getMappingClassString(Smc) + "]").str());444  }445 446  return Result;447}448 449#define PRINTBOOL(Prefix, Obj, Field)                                          \450  OS << Prefix << " " << ((Obj.Field()) ? "+" : "-") << #Field451 452#define PRINTGET(Prefix, Obj, Field)                                           \453  OS << Prefix << " " << #Field << " = "                                       \454     << static_cast<unsigned>(Obj.get##Field())455 456#define PRINTOPTIONAL(Field)                                                   \457  if (TbTable.get##Field()) {                                                  \458    OS << '\n';                                                                \459    printRawData(Bytes.slice(Index, 4), Address + Index, OS, STI);             \460    Index += 4;                                                                \461    OS << "\t# " << #Field << " = " << *TbTable.get##Field();                  \462  }463 464void objdump::dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,465                                 formatted_raw_ostream &OS, uint64_t End,466                                 const MCSubtargetInfo &STI,467                                 const XCOFFObjectFile *Obj) {468  uint64_t Index = 0;469  unsigned TabStop = getInstStartColumn(STI) - 1;470  // Print traceback table boundary.471  printRawData(Bytes.slice(Index, 4), Address, OS, STI);472  OS << "\t# Traceback table start\n";473  Index += 4;474 475  uint64_t Size = End - Address;476  bool Is64Bit = Obj->is64Bit();477 478  // XCOFFTracebackTable::create modifies the size parameter, so ensure Size479  // isn't changed.480  uint64_t SizeCopy = End - Address;481  Expected<XCOFFTracebackTable> TTOrErr =482      XCOFFTracebackTable::create(Bytes.data() + Index, SizeCopy, Is64Bit);483 484  if (!TTOrErr) {485    std::string WarningMsgStr;486    raw_string_ostream WarningStream(WarningMsgStr);487    WarningStream << "failure parsing traceback table with address: 0x"488                  << utohexstr(Address) + "\n>>> "489                  << toString(TTOrErr.takeError())490                  << "\n>>> Raw traceback table data is:\n";491 492    uint64_t LastNonZero = Index;493    for (uint64_t I = Index; I < Size; I += 4)494      if (support::endian::read32be(Bytes.slice(I, 4).data()) != 0)495        LastNonZero = I + 4 > Size ? Size : I + 4;496 497    if (Size - LastNonZero <= 4)498      LastNonZero = Size;499 500    formatted_raw_ostream FOS(WarningStream);501    while (Index < LastNonZero) {502      printRawData(Bytes.slice(Index, 4), Address + Index, FOS, STI);503      Index += 4;504      WarningStream << '\n';505    }506 507    // Print all remaining zeroes as ...508    if (Size - LastNonZero >= 8)509      WarningStream << "\t\t...\n";510 511    reportWarning(WarningMsgStr, Obj->getFileName());512    return;513  }514 515  auto PrintBytes = [&](uint64_t N) {516    printRawData(Bytes.slice(Index, N), Address + Index, OS, STI);517    Index += N;518  };519 520  XCOFFTracebackTable TbTable = *TTOrErr;521  // Print the first of the 8 bytes of mandatory fields.522  PrintBytes(1);523  OS << format("\t# Version = %i", TbTable.getVersion()) << '\n';524 525  // Print the second of the 8 bytes of mandatory fields.526  PrintBytes(1);527  TracebackTable::LanguageID LangId =528      static_cast<TracebackTable::LanguageID>(TbTable.getLanguageID());529  OS << "\t# Language = " << getNameForTracebackTableLanguageId(LangId) << '\n';530 531  auto Split = [&]() {532    OS << '\n';533    OS.indent(TabStop);534  };535 536  // Print the third of the 8 bytes of mandatory fields.537  PrintBytes(1);538  PRINTBOOL("\t#", TbTable, isGlobalLinkage);539  PRINTBOOL(",", TbTable, isOutOfLineEpilogOrPrologue);540  Split();541  PRINTBOOL("\t ", TbTable, hasTraceBackTableOffset);542  PRINTBOOL(",", TbTable, isInternalProcedure);543  Split();544  PRINTBOOL("\t ", TbTable, hasControlledStorage);545  PRINTBOOL(",", TbTable, isTOCless);546  Split();547  PRINTBOOL("\t ", TbTable, isFloatingPointPresent);548  Split();549  PRINTBOOL("\t ", TbTable, isFloatingPointOperationLogOrAbortEnabled);550  OS << '\n';551 552  // Print the 4th of the 8 bytes of mandatory fields.553  PrintBytes(1);554  PRINTBOOL("\t#", TbTable, isInterruptHandler);555  PRINTBOOL(",", TbTable, isFuncNamePresent);556  PRINTBOOL(",", TbTable, isAllocaUsed);557  Split();558  PRINTGET("\t ", TbTable, OnConditionDirective);559  PRINTBOOL(",", TbTable, isCRSaved);560  PRINTBOOL(",", TbTable, isLRSaved);561  OS << '\n';562 563  // Print the 5th of the 8 bytes of mandatory fields.564  PrintBytes(1);565  PRINTBOOL("\t#", TbTable, isBackChainStored);566  PRINTBOOL(",", TbTable, isFixup);567  PRINTGET(",", TbTable, NumOfFPRsSaved);568  OS << '\n';569 570  // Print the 6th of the 8 bytes of mandatory fields.571  PrintBytes(1);572  PRINTBOOL("\t#", TbTable, hasExtensionTable);573  PRINTBOOL(",", TbTable, hasVectorInfo);574  PRINTGET(",", TbTable, NumOfGPRsSaved);575  OS << '\n';576 577  // Print the 7th of the 8 bytes of mandatory fields.578  PrintBytes(1);579  PRINTGET("\t#", TbTable, NumberOfFixedParms);580  OS << '\n';581 582  // Print the 8th of the 8 bytes of mandatory fields.583  PrintBytes(1);584  PRINTGET("\t#", TbTable, NumberOfFPParms);585  PRINTBOOL(",", TbTable, hasParmsOnStack);586 587  PRINTOPTIONAL(ParmsType);588  PRINTOPTIONAL(TraceBackTableOffset);589  PRINTOPTIONAL(HandlerMask);590  PRINTOPTIONAL(NumOfCtlAnchors);591 592  if (TbTable.getControlledStorageInfoDisp()) {593    SmallVector<uint32_t, 8> Disp = *TbTable.getControlledStorageInfoDisp();594    for (unsigned I = 0; I < Disp.size(); ++I) {595      OS << '\n';596      PrintBytes(4);597      OS << "\t" << (I ? " " : "#") << " ControlledStorageInfoDisp[" << I598         << "] = " << Disp[I];599    }600  }601 602  // If there is a name, print the function name and function name length.603  if (TbTable.isFuncNamePresent()) {604    uint16_t FunctionNameLen = TbTable.getFunctionName()->size();605    if (FunctionNameLen == 0) {606      OS << '\n';607      reportWarning(608          "the length of the function name must be greater than zero if the "609          "isFuncNamePresent bit is set in the traceback table",610          Obj->getFileName());611      return;612    }613 614    OS << '\n';615    PrintBytes(2);616    OS << "\t# FunctionNameLen = " << FunctionNameLen;617 618    uint16_t RemainingBytes = FunctionNameLen;619    bool HasPrinted = false;620    while (RemainingBytes > 0) {621      OS << '\n';622      uint16_t PrintLen = RemainingBytes >= 4 ? 4 : RemainingBytes;623      printRawData(Bytes.slice(Index, PrintLen), Address + Index, OS, STI);624      Index += PrintLen;625      RemainingBytes -= PrintLen;626 627      if (!HasPrinted) {628        OS << "\t# FunctionName = " << *TbTable.getFunctionName();629        HasPrinted = true;630      }631    }632  }633 634  if (TbTable.isAllocaUsed()) {635    OS << '\n';636    PrintBytes(1);637    OS << format("\t# AllocaRegister = %u", *TbTable.getAllocaRegister());638  }639 640  if (TbTable.getVectorExt()) {641    OS << '\n';642    TBVectorExt VecExt = *TbTable.getVectorExt();643    // Print first byte of VectorExt.644    PrintBytes(1);645    PRINTGET("\t#", VecExt, NumberOfVRSaved);646    PRINTBOOL(",", VecExt, isVRSavedOnStack);647    PRINTBOOL(",", VecExt, hasVarArgs);648    OS << '\n';649 650    // Print the second byte of VectorExt.651    PrintBytes(1);652    PRINTGET("\t#", VecExt, NumberOfVectorParms);653    PRINTBOOL(",", VecExt, hasVMXInstruction);654    OS << '\n';655 656    PrintBytes(4);657    OS << "\t# VectorParmsInfoString = " << VecExt.getVectorParmsInfo();658 659    // There are two bytes of padding after vector info.660    OS << '\n';661    PrintBytes(2);662    OS << "\t# Padding";663  }664 665  if (TbTable.getExtensionTable()) {666    OS << '\n';667    PrintBytes(1);668    ExtendedTBTableFlag Flag =669        static_cast<ExtendedTBTableFlag>(*TbTable.getExtensionTable());670    OS << "\t# ExtensionTable = " << getExtendedTBTableFlagString(Flag);671  }672 673  if (TbTable.getEhInfoDisp()) {674    // There are 4 bytes alignment before eh info displacement.675    if (Index % 4) {676      OS << '\n';677      PrintBytes(4 - Index % 4);678      OS << "\t# Alignment padding for eh info displacement";679    }680    OS << '\n';681    // The size of the displacement (address) is 4 bytes in 32-bit object files,682    // and 8 bytes in 64-bit object files.683    PrintBytes(4);684    OS << "\t# EH info displacement";685    if (Is64Bit) {686      OS << '\n';687      PrintBytes(4);688    }689  }690 691  OS << '\n';692  if (End == Address + Index)693    return;694 695  Size = End - Address;696 697  const char *LineSuffix = "\t# Padding\n";698  auto IsWordZero = [&](uint64_t WordPos) {699    if (WordPos >= Size)700      return false;701    uint64_t LineLength = std::min(4 - WordPos % 4, Size - WordPos);702    return std::all_of(Bytes.begin() + WordPos,703                       Bytes.begin() + WordPos + LineLength,704                       [](uint8_t Byte) { return Byte == 0; });705  };706 707  bool AreWordsZero[] = {IsWordZero(Index), IsWordZero(alignTo(Index, 4) + 4),708                         IsWordZero(alignTo(Index, 4) + 8)};709  bool ShouldPrintLine = true;710  while (true) {711    // Determine the length of the line (4, except for the first line, which712    // will be just enough to align to the word boundary, and the last line,713    // which will be the remainder of the data).714    uint64_t LineLength = std::min(4 - Index % 4, Size - Index);715    if (ShouldPrintLine) {716      // Print the line.717      printRawData(Bytes.slice(Index, LineLength), Address + Index, OS, STI);718      OS << LineSuffix;719      LineSuffix = "\n";720    }721 722    Index += LineLength;723    if (Index == Size)724      return;725 726    // For 3 or more consecutive lines of zeros, skip all but the first one, and727    // replace them with "...".728    if (AreWordsZero[0] && AreWordsZero[1] && AreWordsZero[2]) {729      if (ShouldPrintLine)730        OS << std::string(8, ' ') << "...\n";731      ShouldPrintLine = false;732    } else if (!AreWordsZero[1]) {733      // We have reached the end of a skipped block of zeros.734      ShouldPrintLine = true;735    }736    AreWordsZero[0] = AreWordsZero[1];737    AreWordsZero[1] = AreWordsZero[2];738    AreWordsZero[2] = IsWordZero(Index + 8);739  }740}741#undef PRINTBOOL742#undef PRINTGET743#undef PRINTOPTIONAL744