brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.1 KiB · 4c851e1 Raw
492 lines · cpp
1//===- BytesOutputStyle.cpp ----------------------------------- *- C++ --*-===//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#include "BytesOutputStyle.h"10 11#include "StreamUtil.h"12#include "llvm-pdbutil.h"13 14#include "llvm/DebugInfo/CodeView/Formatters.h"15#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"16#include "llvm/DebugInfo/MSF/MSFCommon.h"17#include "llvm/DebugInfo/MSF/MappedBlockStream.h"18#include "llvm/DebugInfo/PDB/Native/DbiStream.h"19#include "llvm/DebugInfo/PDB/Native/FormatUtil.h"20#include "llvm/DebugInfo/PDB/Native/InfoStream.h"21#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"22#include "llvm/DebugInfo/PDB/Native/PDBFile.h"23#include "llvm/DebugInfo/PDB/Native/RawError.h"24#include "llvm/DebugInfo/PDB/Native/TpiStream.h"25#include "llvm/Support/BinaryStreamReader.h"26#include "llvm/Support/FormatAdapters.h"27#include "llvm/Support/FormatVariadic.h"28 29using namespace llvm;30using namespace llvm::codeview;31using namespace llvm::msf;32using namespace llvm::pdb;33 34namespace {35struct StreamSpec {36  uint32_t SI = 0;37  uint32_t Begin = 0;38  uint32_t Size = 0;39};40} // namespace41 42static Expected<StreamSpec> parseStreamSpec(StringRef Str) {43  StreamSpec Result;44  if (Str.consumeInteger(0, Result.SI))45    return make_error<RawError>(raw_error_code::invalid_format,46                                "Invalid Stream Specification");47  if (Str.consume_front(":")) {48    if (Str.consumeInteger(0, Result.Begin))49      return make_error<RawError>(raw_error_code::invalid_format,50                                  "Invalid Stream Specification");51  }52  if (Str.consume_front("@")) {53    if (Str.consumeInteger(0, Result.Size))54      return make_error<RawError>(raw_error_code::invalid_format,55                                  "Invalid Stream Specification");56  }57 58  if (!Str.empty())59    return make_error<RawError>(raw_error_code::invalid_format,60                                "Invalid Stream Specification");61  return Result;62}63 64static SmallVector<StreamSpec, 2> parseStreamSpecs(LinePrinter &P) {65  SmallVector<StreamSpec, 2> Result;66 67  for (auto &Str : opts::bytes::DumpStreamData) {68    auto ESS = parseStreamSpec(Str);69    if (!ESS) {70      P.formatLine("Error parsing stream spec {0}: {1}", Str,71                   toString(ESS.takeError()));72      continue;73    }74    Result.push_back(*ESS);75  }76  return Result;77}78 79static void printHeader(LinePrinter &P, const Twine &S) {80  P.NewLine();81  P.formatLine("{0,=60}", S);82  P.formatLine("{0}", fmt_repeat('=', 60));83}84 85BytesOutputStyle::BytesOutputStyle(PDBFile &File)86    : File(File), P(2, false, outs(), opts::Filters) {}87 88Error BytesOutputStyle::dump() {89 90  if (opts::bytes::DumpBlockRange) {91    auto &R = *opts::bytes::DumpBlockRange;92    uint32_t Max = R.Max.value_or(R.Min);93 94    if (Max < R.Min)95      return make_error<StringError>(96          "Invalid block range specified.  Max < Min",97          inconvertibleErrorCode());98    if (Max >= File.getBlockCount())99      return make_error<StringError>(100          "Invalid block range specified.  Requested block out of bounds",101          inconvertibleErrorCode());102 103    dumpBlockRanges(R.Min, Max);104    P.NewLine();105  }106 107  if (opts::bytes::DumpByteRange) {108    auto &R = *opts::bytes::DumpByteRange;109    uint32_t Max = R.Max.value_or(File.getFileSize());110 111    if (Max < R.Min)112      return make_error<StringError>("Invalid byte range specified.  Max < Min",113                                     inconvertibleErrorCode());114    if (Max >= File.getFileSize())115      return make_error<StringError>(116          "Invalid byte range specified.  Requested byte larger than file size",117          inconvertibleErrorCode());118 119    dumpByteRanges(R.Min, Max);120    P.NewLine();121  }122 123  if (opts::bytes::Fpm) {124    dumpFpm();125    P.NewLine();126  }127 128  if (!opts::bytes::DumpStreamData.empty()) {129    dumpStreamBytes();130    P.NewLine();131  }132 133  if (opts::bytes::NameMap) {134    dumpNameMap();135    P.NewLine();136  }137 138  if (opts::bytes::SectionContributions) {139    dumpSectionContributions();140    P.NewLine();141  }142 143  if (opts::bytes::SectionMap) {144    dumpSectionMap();145    P.NewLine();146  }147 148  if (opts::bytes::ModuleInfos) {149    dumpModuleInfos();150    P.NewLine();151  }152 153  if (opts::bytes::FileInfo) {154    dumpFileInfo();155    P.NewLine();156  }157 158  if (opts::bytes::TypeServerMap) {159    dumpTypeServerMap();160    P.NewLine();161  }162 163  if (opts::bytes::ECData) {164    dumpECData();165    P.NewLine();166  }167 168  if (!opts::bytes::TypeIndex.empty()) {169    dumpTypeIndex(StreamTPI, opts::bytes::TypeIndex);170    P.NewLine();171  }172 173  if (!opts::bytes::IdIndex.empty()) {174    dumpTypeIndex(StreamIPI, opts::bytes::IdIndex);175    P.NewLine();176  }177 178  if (opts::bytes::ModuleSyms) {179    dumpModuleSyms();180    P.NewLine();181  }182 183  if (opts::bytes::ModuleC11) {184    dumpModuleC11();185    P.NewLine();186  }187 188  if (opts::bytes::ModuleC13) {189    dumpModuleC13();190    P.NewLine();191  }192 193  return Error::success();194}195 196void BytesOutputStyle::dumpNameMap() {197  printHeader(P, "Named Stream Map");198 199  AutoIndent Indent(P);200 201  auto &InfoS = Err(File.getPDBInfoStream());202  BinarySubstreamRef NS = InfoS.getNamedStreamsBuffer();203  auto Layout = File.getStreamLayout(StreamPDB);204  P.formatMsfStreamData("Named Stream Map", File, Layout, NS);205}206 207void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) {208  printHeader(P, "MSF Blocks");209 210  AutoIndent Indent(P);211  for (uint32_t I = Min; I <= Max; ++I) {212    uint64_t Base = I;213    Base *= File.getBlockSize();214 215    auto ExpectedData = File.getBlockData(I, File.getBlockSize());216    if (!ExpectedData) {217      P.formatLine("Could not get block {0}.  Reason = {1}", I,218                   toString(ExpectedData.takeError()));219      continue;220    }221    std::string Label = formatv("Block {0}", I).str();222    P.formatBinary(Label, *ExpectedData, Base, 0);223  }224}225 226void BytesOutputStyle::dumpSectionContributions() {227  printHeader(P, "Section Contributions");228 229  AutoIndent Indent(P);230 231  auto &DbiS = Err(File.getPDBDbiStream());232  BinarySubstreamRef NS = DbiS.getSectionContributionData();233  auto Layout = File.getStreamLayout(StreamDBI);234  P.formatMsfStreamData("Section Contributions", File, Layout, NS);235}236 237void BytesOutputStyle::dumpSectionMap() {238  printHeader(P, "Section Map");239 240  AutoIndent Indent(P);241 242  auto &DbiS = Err(File.getPDBDbiStream());243  BinarySubstreamRef NS = DbiS.getSecMapSubstreamData();244  auto Layout = File.getStreamLayout(StreamDBI);245  P.formatMsfStreamData("Section Map", File, Layout, NS);246}247 248void BytesOutputStyle::dumpModuleInfos() {249  printHeader(P, "Module Infos");250 251  AutoIndent Indent(P);252 253  auto &DbiS = Err(File.getPDBDbiStream());254  BinarySubstreamRef NS = DbiS.getModiSubstreamData();255  auto Layout = File.getStreamLayout(StreamDBI);256  P.formatMsfStreamData("Module Infos", File, Layout, NS);257}258 259void BytesOutputStyle::dumpFileInfo() {260  printHeader(P, "File Info");261 262  AutoIndent Indent(P);263 264  auto &DbiS = Err(File.getPDBDbiStream());265  BinarySubstreamRef NS = DbiS.getFileInfoSubstreamData();266  auto Layout = File.getStreamLayout(StreamDBI);267  P.formatMsfStreamData("File Info", File, Layout, NS);268}269 270void BytesOutputStyle::dumpTypeServerMap() {271  printHeader(P, "Type Server Map");272 273  AutoIndent Indent(P);274 275  auto &DbiS = Err(File.getPDBDbiStream());276  BinarySubstreamRef NS = DbiS.getTypeServerMapSubstreamData();277  auto Layout = File.getStreamLayout(StreamDBI);278  P.formatMsfStreamData("Type Server Map", File, Layout, NS);279}280 281void BytesOutputStyle::dumpECData() {282  printHeader(P, "Edit and Continue Data");283 284  AutoIndent Indent(P);285 286  auto &DbiS = Err(File.getPDBDbiStream());287  BinarySubstreamRef NS = DbiS.getECSubstreamData();288  auto Layout = File.getStreamLayout(StreamDBI);289  P.formatMsfStreamData("Edit and Continue Data", File, Layout, NS);290}291 292void BytesOutputStyle::dumpTypeIndex(uint32_t StreamIdx,293                                     ArrayRef<uint32_t> Indices) {294  assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);295  assert(!Indices.empty());296 297  bool IsTpi = (StreamIdx == StreamTPI);298 299  StringRef Label = IsTpi ? "Type (TPI) Records" : "Index (IPI) Records";300  printHeader(P, Label);301  auto &Stream = Err(IsTpi ? File.getPDBTpiStream() : File.getPDBIpiStream());302 303  AutoIndent Indent(P);304 305  auto Substream = Stream.getTypeRecordsSubstream();306  auto &Types = Err(initializeTypes(StreamIdx));307  auto Layout = File.getStreamLayout(StreamIdx);308  for (const auto &Id : Indices) {309    TypeIndex TI(Id);310    if (TI.toArrayIndex() >= Types.capacity()) {311      P.formatLine("Error: TypeIndex {0} does not exist", TI);312      continue;313    }314 315    auto Type = Types.getType(TI);316    uint32_t Offset = Types.getOffsetOfType(TI);317    auto OneType = Substream.slice(Offset, Type.length());318    P.formatMsfStreamData(formatv("Type {0}", TI).str(), File, Layout, OneType);319  }320}321 322template <typename CallbackT>323static void iterateOneModule(PDBFile &File, LinePrinter &P,324                             const DbiModuleList &Modules, uint32_t I,325                             uint32_t Digits, uint32_t IndentLevel,326                             CallbackT Callback) {327  if (I >= Modules.getModuleCount()) {328    P.formatLine("Mod {0:4} | Invalid module index ",329                 fmt_align(I, AlignStyle::Right, std::max(Digits, 4U)));330    return;331  }332 333  auto Modi = Modules.getModuleDescriptor(I);334  P.formatLine("Mod {0:4} | `{1}`: ",335               fmt_align(I, AlignStyle::Right, std::max(Digits, 4U)),336               Modi.getModuleName());337 338  uint16_t ModiStream = Modi.getModuleStreamIndex();339  AutoIndent Indent2(P, IndentLevel);340  if (ModiStream == kInvalidStreamIndex)341    return;342 343  auto ModStreamData = File.createIndexedStream(ModiStream);344  ModuleDebugStreamRef ModStream(Modi, std::move(ModStreamData));345  if (auto EC = ModStream.reload()) {346    P.formatLine("Could not parse debug information.");347    return;348  }349  auto Layout = File.getStreamLayout(ModiStream);350  Callback(I, ModStream, Layout);351}352 353template <typename CallbackT>354static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,355                           CallbackT Callback) {356  AutoIndent Indent(P);357  if (!File.hasPDBDbiStream()) {358    P.formatLine("DBI Stream not present");359    return;360  }361 362  ExitOnError Err("Unexpected error processing modules");363 364  auto &Stream = Err(File.getPDBDbiStream());365 366  const DbiModuleList &Modules = Stream.modules();367 368  if (opts::bytes::ModuleIndex.getNumOccurrences() > 0) {369    iterateOneModule(File, P, Modules, opts::bytes::ModuleIndex, 1, IndentLevel,370                     Callback);371  } else {372    uint32_t Count = Modules.getModuleCount();373    uint32_t Digits = NumDigits(Count);374    for (uint32_t I = 0; I < Count; ++I) {375      iterateOneModule(File, P, Modules, I, Digits, IndentLevel, Callback);376    }377  }378}379 380void BytesOutputStyle::dumpModuleSyms() {381  printHeader(P, "Module Symbols");382 383  AutoIndent Indent(P);384 385  iterateModules(File, P, 2,386                 [this](uint32_t Modi, const ModuleDebugStreamRef &Stream,387                        const MSFStreamLayout &Layout) {388                   auto Symbols = Stream.getSymbolsSubstream();389                   P.formatMsfStreamData("Symbols", File, Layout, Symbols);390                 });391}392 393void BytesOutputStyle::dumpModuleC11() {394  printHeader(P, "C11 Debug Chunks");395 396  AutoIndent Indent(P);397 398  iterateModules(File, P, 2,399                 [this](uint32_t Modi, const ModuleDebugStreamRef &Stream,400                        const MSFStreamLayout &Layout) {401                   auto Chunks = Stream.getC11LinesSubstream();402                   P.formatMsfStreamData("C11 Debug Chunks", File, Layout,403                                         Chunks);404                 });405}406 407void BytesOutputStyle::dumpModuleC13() {408  printHeader(P, "Debug Chunks");409 410  AutoIndent Indent(P);411 412  iterateModules(413      File, P, 2,414      [this](uint32_t Modi, const ModuleDebugStreamRef &Stream,415             const MSFStreamLayout &Layout) {416        auto Chunks = Stream.getC13LinesSubstream();417        if (opts::bytes::SplitChunks) {418          for (const auto &SS : Stream.subsections()) {419            BinarySubstreamRef ThisChunk;420            std::tie(ThisChunk, Chunks) = Chunks.split(SS.getRecordLength());421            P.formatMsfStreamData(formatChunkKind(SS.kind()), File, Layout,422                                  ThisChunk);423          }424        } else {425          P.formatMsfStreamData("Debug Chunks", File, Layout, Chunks);426        }427      });428}429 430void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {431  printHeader(P, "MSF Bytes");432 433  AutoIndent Indent(P);434 435  BinaryStreamReader Reader(File.getMsfBuffer());436  ArrayRef<uint8_t> Data;437  consumeError(Reader.skip(Min));438  uint32_t Size = Max - Min + 1;439  auto EC = Reader.readBytes(Data, Size);440  assert(!EC);441  consumeError(std::move(EC));442  P.formatBinary("Bytes", Data, Min);443}444 445Expected<codeview::LazyRandomTypeCollection &>446BytesOutputStyle::initializeTypes(uint32_t StreamIdx) {447  auto &TypeCollection = (StreamIdx == StreamTPI) ? TpiTypes : IpiTypes;448  if (TypeCollection)449    return *TypeCollection;450 451  auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()452                                      : File.getPDBIpiStream();453  if (!Tpi)454    return Tpi.takeError();455 456  auto &Types = Tpi->typeArray();457  uint32_t Count = Tpi->getNumTypeRecords();458  auto Offsets = Tpi->getTypeIndexOffsets();459  TypeCollection =460      std::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);461 462  return *TypeCollection;463}464 465void BytesOutputStyle::dumpFpm() {466  printHeader(P, "Free Page Map");467 468  msf::MSFStreamLayout FpmLayout = File.getFpmStreamLayout();469  P.formatMsfStreamBlocks(File, FpmLayout);470}471 472void BytesOutputStyle::dumpStreamBytes() {473  if (StreamPurposes.empty())474    discoverStreamPurposes(File, StreamPurposes);475 476  printHeader(P, "Stream Data");477  ExitOnError Err("Unexpected error reading stream data");478 479  auto Specs = parseStreamSpecs(P);480 481  for (const auto &Spec : Specs) {482    AutoIndent Indent(P);483    if (Spec.SI >= StreamPurposes.size()) {484      P.formatLine("Stream {0}: Not present", Spec.SI);485      continue;486    }487    P.formatMsfStreamData("Data", File, Spec.SI,488                          StreamPurposes[Spec.SI].getShortName(), Spec.Begin,489                          Spec.Size);490  }491}492