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