brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.2 KiB · dbc77b1 Raw
340 lines · cpp
1//===- LinePrinter.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 "llvm/DebugInfo/PDB/Native/LinePrinter.h"10 11#include "llvm/ADT/STLExtras.h"12#include "llvm/DebugInfo/MSF/MSFCommon.h"13#include "llvm/DebugInfo/MSF/MappedBlockStream.h"14#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"15#include "llvm/DebugInfo/PDB/Native/InputFile.h"16#include "llvm/DebugInfo/PDB/Native/NativeSession.h"17#include "llvm/DebugInfo/PDB/Native/PDBFile.h"18#include "llvm/DebugInfo/PDB/UDTLayout.h"19#include "llvm/Object/COFF.h"20#include "llvm/Support/BinaryStreamReader.h"21#include "llvm/Support/Format.h"22#include "llvm/Support/FormatAdapters.h"23#include "llvm/Support/FormatVariadic.h"24#include "llvm/Support/Regex.h"25 26#include <algorithm>27 28using namespace llvm;29using namespace llvm::msf;30using namespace llvm::pdb;31 32namespace {33bool IsItemExcluded(llvm::StringRef Item,34                    std::list<llvm::Regex> &IncludeFilters,35                    std::list<llvm::Regex> &ExcludeFilters) {36  if (Item.empty())37    return false;38 39  auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };40 41  // Include takes priority over exclude.  If the user specified include42  // filters, and none of them include this item, them item is gone.43  if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))44    return true;45 46  if (any_of(ExcludeFilters, match_pred))47    return true;48 49  return false;50}51} // namespace52 53using namespace llvm;54 55LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream,56                         const FilterOptions &Filters)57    : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor),58      Filters(Filters) {59  SetFilters(ExcludeTypeFilters, Filters.ExcludeTypes.begin(),60             Filters.ExcludeTypes.end());61  SetFilters(ExcludeSymbolFilters, Filters.ExcludeSymbols.begin(),62             Filters.ExcludeSymbols.end());63  SetFilters(ExcludeCompilandFilters, Filters.ExcludeCompilands.begin(),64             Filters.ExcludeCompilands.end());65 66  SetFilters(IncludeTypeFilters, Filters.IncludeTypes.begin(),67             Filters.IncludeTypes.end());68  SetFilters(IncludeSymbolFilters, Filters.IncludeSymbols.begin(),69             Filters.IncludeSymbols.end());70  SetFilters(IncludeCompilandFilters, Filters.IncludeCompilands.begin(),71             Filters.IncludeCompilands.end());72}73 74void LinePrinter::Indent(uint32_t Amount) {75  if (Amount == 0)76    Amount = IndentSpaces;77  CurrentIndent += Amount;78}79 80void LinePrinter::Unindent(uint32_t Amount) {81  if (Amount == 0)82    Amount = IndentSpaces;83  CurrentIndent = std::max<int>(0, CurrentIndent - Amount);84}85 86void LinePrinter::NewLine() {87  OS << "\n";88  OS.indent(CurrentIndent);89}90 91void LinePrinter::print(const Twine &T) { OS << T; }92 93void LinePrinter::printLine(const Twine &T) {94  NewLine();95  OS << T;96}97 98bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {99  if (IsTypeExcluded(Class.getName(), Class.getSize()))100    return true;101  if (Class.deepPaddingSize() < Filters.PaddingThreshold)102    return true;103  return false;104}105 106void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,107                               uint64_t StartOffset) {108  NewLine();109  OS << Label << " (";110  if (!Data.empty()) {111    OS << "\n";112    OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,113                                  CurrentIndent + IndentSpaces, true);114    NewLine();115  }116  OS << ")";117}118 119void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,120                               uint64_t Base, uint64_t StartOffset) {121  NewLine();122  OS << Label << " (";123  if (!Data.empty()) {124    OS << "\n";125    Base += StartOffset;126    OS << format_bytes_with_ascii(Data, Base, 32, 4,127                                  CurrentIndent + IndentSpaces, true);128    NewLine();129  }130  OS << ")";131}132 133namespace {134struct Run {135  Run() = default;136  explicit Run(uint32_t Block) : Block(Block) {}137  uint32_t Block = 0;138  uint64_t ByteLen = 0;139};140} // namespace141 142static std::vector<Run> computeBlockRuns(uint32_t BlockSize,143                                         const msf::MSFStreamLayout &Layout) {144  std::vector<Run> Runs;145  if (Layout.Length == 0)146    return Runs;147 148  ArrayRef<support::ulittle32_t> Blocks = Layout.Blocks;149  assert(!Blocks.empty());150  uint64_t StreamBytesRemaining = Layout.Length;151  uint32_t CurrentBlock = Blocks[0];152  Runs.emplace_back(CurrentBlock);153  while (!Blocks.empty()) {154    Run *CurrentRun = &Runs.back();155    uint32_t NextBlock = Blocks.front();156    if (NextBlock < CurrentBlock || (NextBlock - CurrentBlock > 1)) {157      Runs.emplace_back(NextBlock);158      CurrentRun = &Runs.back();159    }160    uint64_t Used =161        std::min(static_cast<uint64_t>(BlockSize), StreamBytesRemaining);162    CurrentRun->ByteLen += Used;163    StreamBytesRemaining -= Used;164    CurrentBlock = NextBlock;165    Blocks = Blocks.drop_front();166  }167  return Runs;168}169 170static std::pair<Run, uint64_t> findRun(uint64_t Offset, ArrayRef<Run> Runs) {171  for (const auto &R : Runs) {172    if (Offset < R.ByteLen)173      return std::make_pair(R, Offset);174    Offset -= R.ByteLen;175  }176  llvm_unreachable("Invalid offset!");177}178 179void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,180                                      uint32_t StreamIdx,181                                      StringRef StreamPurpose, uint64_t Offset,182                                      uint64_t Size) {183  if (StreamIdx >= File.getNumStreams()) {184    formatLine("Stream {0}: Not present", StreamIdx);185    return;186  }187  if (Size + Offset > File.getStreamByteSize(StreamIdx)) {188    formatLine(189        "Stream {0}: Invalid offset and size, range out of stream bounds",190        StreamIdx);191    return;192  }193 194  auto S = File.createIndexedStream(StreamIdx);195  if (!S) {196    NewLine();197    formatLine("Stream {0}: Not present", StreamIdx);198    return;199  }200 201  uint64_t End =202      (Size == 0) ? S->getLength() : std::min(Offset + Size, S->getLength());203  Size = End - Offset;204 205  formatLine("Stream {0}: {1} (dumping {2:N} / {3:N} bytes)", StreamIdx,206             StreamPurpose, Size, S->getLength());207  AutoIndent Indent(*this);208  BinaryStreamRef Slice(*S);209  BinarySubstreamRef Substream;210  Substream.Offset = Offset;211  Substream.StreamData = Slice.drop_front(Offset).keep_front(Size);212 213  auto Layout = File.getStreamLayout(StreamIdx);214  formatMsfStreamData(Label, File, Layout, Substream);215}216 217void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,218                                      const msf::MSFStreamLayout &Stream,219                                      BinarySubstreamRef Substream) {220  BinaryStreamReader Reader(Substream.StreamData);221 222  auto Runs = computeBlockRuns(File.getBlockSize(), Stream);223 224  NewLine();225  OS << Label << " (";226  while (Reader.bytesRemaining() > 0) {227    OS << "\n";228 229    Run FoundRun;230    uint64_t RunOffset;231    std::tie(FoundRun, RunOffset) = findRun(Substream.Offset, Runs);232    assert(FoundRun.ByteLen >= RunOffset);233    uint64_t Len = FoundRun.ByteLen - RunOffset;234    Len = std::min(Len, Reader.bytesRemaining());235    uint64_t Base = FoundRun.Block * File.getBlockSize() + RunOffset;236    ArrayRef<uint8_t> Data;237    consumeError(Reader.readBytes(Data, Len));238    OS << format_bytes_with_ascii(Data, Base, 32, 4,239                                  CurrentIndent + IndentSpaces, true);240    if (Reader.bytesRemaining() > 0) {241      NewLine();242      OS << formatv("  {0}",243                    fmt_align("<discontinuity>", AlignStyle::Center, 114, '-'));244    }245    Substream.Offset += Len;246  }247  NewLine();248  OS << ")";249}250 251void LinePrinter::formatMsfStreamBlocks(252    PDBFile &File, const msf::MSFStreamLayout &StreamLayout) {253  auto Blocks = ArrayRef(StreamLayout.Blocks);254  uint64_t L = StreamLayout.Length;255 256  while (L > 0) {257    NewLine();258    assert(!Blocks.empty());259    OS << formatv("Block {0} (\n", uint32_t(Blocks.front()));260    uint64_t UsedBytes =261        std::min(L, static_cast<uint64_t>(File.getBlockSize()));262    ArrayRef<uint8_t> BlockData =263        cantFail(File.getBlockData(Blocks.front(), File.getBlockSize()));264    uint64_t BaseOffset = Blocks.front();265    BaseOffset *= File.getBlockSize();266    OS << format_bytes_with_ascii(BlockData, BaseOffset, 32, 4,267                                  CurrentIndent + IndentSpaces, true);268    NewLine();269    OS << ")";270    NewLine();271    L -= UsedBytes;272    Blocks = Blocks.drop_front();273  }274}275 276bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint64_t Size) {277  if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))278    return true;279  if (Size < Filters.SizeThreshold)280    return true;281  return false;282}283 284bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {285  return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);286}287 288bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {289  return IsItemExcluded(CompilandName, IncludeCompilandFilters,290                        ExcludeCompilandFilters);291}292 293WithColor::WithColor(LinePrinter &P, PDB_ColorItem C)294    : OS(P.OS), UseColor(P.hasColor()) {295  if (UseColor)296    applyColor(C);297}298 299WithColor::~WithColor() {300  if (UseColor)301    OS.resetColor();302}303 304void WithColor::applyColor(PDB_ColorItem C) {305  switch (C) {306  case PDB_ColorItem::None:307    OS.resetColor();308    return;309  case PDB_ColorItem::Comment:310    OS.changeColor(raw_ostream::GREEN, false);311    return;312  case PDB_ColorItem::Address:313    OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);314    return;315  case PDB_ColorItem::Keyword:316    OS.changeColor(raw_ostream::MAGENTA, true);317    return;318  case PDB_ColorItem::Register:319  case PDB_ColorItem::Offset:320    OS.changeColor(raw_ostream::YELLOW, false);321    return;322  case PDB_ColorItem::Type:323    OS.changeColor(raw_ostream::CYAN, true);324    return;325  case PDB_ColorItem::Identifier:326    OS.changeColor(raw_ostream::CYAN, false);327    return;328  case PDB_ColorItem::Path:329    OS.changeColor(raw_ostream::CYAN, false);330    return;331  case PDB_ColorItem::Padding:332  case PDB_ColorItem::SectionHeader:333    OS.changeColor(raw_ostream::RED, true);334    return;335  case PDB_ColorItem::LiteralValue:336    OS.changeColor(raw_ostream::GREEN, true);337    return;338  }339}340