175112133SCarlos Alberto Enciso //===- LinePrinter.cpp ------------------------------------------*- C++ -*-===//
275112133SCarlos Alberto Enciso //
375112133SCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
475112133SCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information.
575112133SCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
675112133SCarlos Alberto Enciso //
775112133SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
875112133SCarlos Alberto Enciso 
975112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
1075112133SCarlos Alberto Enciso 
1175112133SCarlos Alberto Enciso #include "llvm/ADT/STLExtras.h"
1275112133SCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
1375112133SCarlos Alberto Enciso #include "llvm/DebugInfo/MSF/MSFCommon.h"
1475112133SCarlos Alberto Enciso #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1575112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
1675112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/InputFile.h"
1775112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
1875112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
1975112133SCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/UDTLayout.h"
2075112133SCarlos Alberto Enciso #include "llvm/Object/COFF.h"
2175112133SCarlos Alberto Enciso #include "llvm/Support/BinaryStreamReader.h"
2275112133SCarlos Alberto Enciso #include "llvm/Support/Format.h"
2375112133SCarlos Alberto Enciso #include "llvm/Support/FormatAdapters.h"
2475112133SCarlos Alberto Enciso #include "llvm/Support/FormatVariadic.h"
2575112133SCarlos Alberto Enciso #include "llvm/Support/Regex.h"
2675112133SCarlos Alberto Enciso 
2775112133SCarlos Alberto Enciso #include <algorithm>
2875112133SCarlos Alberto Enciso 
2975112133SCarlos Alberto Enciso using namespace llvm;
3075112133SCarlos Alberto Enciso using namespace llvm::msf;
3175112133SCarlos Alberto Enciso using namespace llvm::pdb;
3275112133SCarlos Alberto Enciso 
3375112133SCarlos Alberto Enciso namespace {
IsItemExcluded(llvm::StringRef Item,std::list<llvm::Regex> & IncludeFilters,std::list<llvm::Regex> & ExcludeFilters)3475112133SCarlos Alberto Enciso bool IsItemExcluded(llvm::StringRef Item,
3575112133SCarlos Alberto Enciso                     std::list<llvm::Regex> &IncludeFilters,
3675112133SCarlos Alberto Enciso                     std::list<llvm::Regex> &ExcludeFilters) {
3775112133SCarlos Alberto Enciso   if (Item.empty())
3875112133SCarlos Alberto Enciso     return false;
3975112133SCarlos Alberto Enciso 
4075112133SCarlos Alberto Enciso   auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };
4175112133SCarlos Alberto Enciso 
4275112133SCarlos Alberto Enciso   // Include takes priority over exclude.  If the user specified include
4375112133SCarlos Alberto Enciso   // filters, and none of them include this item, them item is gone.
4475112133SCarlos Alberto Enciso   if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))
4575112133SCarlos Alberto Enciso     return true;
4675112133SCarlos Alberto Enciso 
4775112133SCarlos Alberto Enciso   if (any_of(ExcludeFilters, match_pred))
4875112133SCarlos Alberto Enciso     return true;
4975112133SCarlos Alberto Enciso 
5075112133SCarlos Alberto Enciso   return false;
5175112133SCarlos Alberto Enciso }
5275112133SCarlos Alberto Enciso } // namespace
5375112133SCarlos Alberto Enciso 
5475112133SCarlos Alberto Enciso using namespace llvm;
5575112133SCarlos Alberto Enciso 
LinePrinter(int Indent,bool UseColor,llvm::raw_ostream & Stream,const FilterOptions & Filters)5675112133SCarlos Alberto Enciso LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream,
57*10c11f5cSCarlos Alberto Enciso                          const FilterOptions &Filters)
58*10c11f5cSCarlos Alberto Enciso     : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor),
59*10c11f5cSCarlos Alberto Enciso       Filters(Filters) {
6075112133SCarlos Alberto Enciso   SetFilters(ExcludeTypeFilters, Filters.ExcludeTypes.begin(),
6175112133SCarlos Alberto Enciso              Filters.ExcludeTypes.end());
6275112133SCarlos Alberto Enciso   SetFilters(ExcludeSymbolFilters, Filters.ExcludeSymbols.begin(),
6375112133SCarlos Alberto Enciso              Filters.ExcludeSymbols.end());
6475112133SCarlos Alberto Enciso   SetFilters(ExcludeCompilandFilters, Filters.ExcludeCompilands.begin(),
6575112133SCarlos Alberto Enciso              Filters.ExcludeCompilands.end());
6675112133SCarlos Alberto Enciso 
6775112133SCarlos Alberto Enciso   SetFilters(IncludeTypeFilters, Filters.IncludeTypes.begin(),
6875112133SCarlos Alberto Enciso              Filters.IncludeTypes.end());
6975112133SCarlos Alberto Enciso   SetFilters(IncludeSymbolFilters, Filters.IncludeSymbols.begin(),
7075112133SCarlos Alberto Enciso              Filters.IncludeSymbols.end());
7175112133SCarlos Alberto Enciso   SetFilters(IncludeCompilandFilters, Filters.IncludeCompilands.begin(),
7275112133SCarlos Alberto Enciso              Filters.IncludeCompilands.end());
7375112133SCarlos Alberto Enciso }
7475112133SCarlos Alberto Enciso 
Indent(uint32_t Amount)7575112133SCarlos Alberto Enciso void LinePrinter::Indent(uint32_t Amount) {
7675112133SCarlos Alberto Enciso   if (Amount == 0)
7775112133SCarlos Alberto Enciso     Amount = IndentSpaces;
7875112133SCarlos Alberto Enciso   CurrentIndent += Amount;
7975112133SCarlos Alberto Enciso }
8075112133SCarlos Alberto Enciso 
Unindent(uint32_t Amount)8175112133SCarlos Alberto Enciso void LinePrinter::Unindent(uint32_t Amount) {
8275112133SCarlos Alberto Enciso   if (Amount == 0)
8375112133SCarlos Alberto Enciso     Amount = IndentSpaces;
8475112133SCarlos Alberto Enciso   CurrentIndent = std::max<int>(0, CurrentIndent - Amount);
8575112133SCarlos Alberto Enciso }
8675112133SCarlos Alberto Enciso 
NewLine()8775112133SCarlos Alberto Enciso void LinePrinter::NewLine() {
8875112133SCarlos Alberto Enciso   OS << "\n";
8975112133SCarlos Alberto Enciso   OS.indent(CurrentIndent);
9075112133SCarlos Alberto Enciso }
9175112133SCarlos Alberto Enciso 
print(const Twine & T)9275112133SCarlos Alberto Enciso void LinePrinter::print(const Twine &T) { OS << T; }
9375112133SCarlos Alberto Enciso 
printLine(const Twine & T)9475112133SCarlos Alberto Enciso void LinePrinter::printLine(const Twine &T) {
9575112133SCarlos Alberto Enciso   NewLine();
9675112133SCarlos Alberto Enciso   OS << T;
9775112133SCarlos Alberto Enciso }
9875112133SCarlos Alberto Enciso 
IsClassExcluded(const ClassLayout & Class)9975112133SCarlos Alberto Enciso bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
10075112133SCarlos Alberto Enciso   if (IsTypeExcluded(Class.getName(), Class.getSize()))
10175112133SCarlos Alberto Enciso     return true;
10275112133SCarlos Alberto Enciso   if (Class.deepPaddingSize() < Filters.PaddingThreshold)
10375112133SCarlos Alberto Enciso     return true;
10475112133SCarlos Alberto Enciso   return false;
10575112133SCarlos Alberto Enciso }
10675112133SCarlos Alberto Enciso 
formatBinary(StringRef Label,ArrayRef<uint8_t> Data,uint64_t StartOffset)10775112133SCarlos Alberto Enciso void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
10875112133SCarlos Alberto Enciso                                uint64_t StartOffset) {
10975112133SCarlos Alberto Enciso   NewLine();
11075112133SCarlos Alberto Enciso   OS << Label << " (";
11175112133SCarlos Alberto Enciso   if (!Data.empty()) {
11275112133SCarlos Alberto Enciso     OS << "\n";
11375112133SCarlos Alberto Enciso     OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,
11475112133SCarlos Alberto Enciso                                   CurrentIndent + IndentSpaces, true);
11575112133SCarlos Alberto Enciso     NewLine();
11675112133SCarlos Alberto Enciso   }
11775112133SCarlos Alberto Enciso   OS << ")";
11875112133SCarlos Alberto Enciso }
11975112133SCarlos Alberto Enciso 
formatBinary(StringRef Label,ArrayRef<uint8_t> Data,uint64_t Base,uint64_t StartOffset)12075112133SCarlos Alberto Enciso void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
12175112133SCarlos Alberto Enciso                                uint64_t Base, uint64_t StartOffset) {
12275112133SCarlos Alberto Enciso   NewLine();
12375112133SCarlos Alberto Enciso   OS << Label << " (";
12475112133SCarlos Alberto Enciso   if (!Data.empty()) {
12575112133SCarlos Alberto Enciso     OS << "\n";
12675112133SCarlos Alberto Enciso     Base += StartOffset;
12775112133SCarlos Alberto Enciso     OS << format_bytes_with_ascii(Data, Base, 32, 4,
12875112133SCarlos Alberto Enciso                                   CurrentIndent + IndentSpaces, true);
12975112133SCarlos Alberto Enciso     NewLine();
13075112133SCarlos Alberto Enciso   }
13175112133SCarlos Alberto Enciso   OS << ")";
13275112133SCarlos Alberto Enciso }
13375112133SCarlos Alberto Enciso 
13475112133SCarlos Alberto Enciso namespace {
13575112133SCarlos Alberto Enciso struct Run {
13675112133SCarlos Alberto Enciso   Run() = default;
Run__anond7d3eec90311::Run13775112133SCarlos Alberto Enciso   explicit Run(uint32_t Block) : Block(Block) {}
13875112133SCarlos Alberto Enciso   uint32_t Block = 0;
13975112133SCarlos Alberto Enciso   uint64_t ByteLen = 0;
14075112133SCarlos Alberto Enciso };
14175112133SCarlos Alberto Enciso } // namespace
14275112133SCarlos Alberto Enciso 
computeBlockRuns(uint32_t BlockSize,const msf::MSFStreamLayout & Layout)14375112133SCarlos Alberto Enciso static std::vector<Run> computeBlockRuns(uint32_t BlockSize,
14475112133SCarlos Alberto Enciso                                          const msf::MSFStreamLayout &Layout) {
14575112133SCarlos Alberto Enciso   std::vector<Run> Runs;
14675112133SCarlos Alberto Enciso   if (Layout.Length == 0)
14775112133SCarlos Alberto Enciso     return Runs;
14875112133SCarlos Alberto Enciso 
14975112133SCarlos Alberto Enciso   ArrayRef<support::ulittle32_t> Blocks = Layout.Blocks;
15075112133SCarlos Alberto Enciso   assert(!Blocks.empty());
15175112133SCarlos Alberto Enciso   uint64_t StreamBytesRemaining = Layout.Length;
15275112133SCarlos Alberto Enciso   uint32_t CurrentBlock = Blocks[0];
15375112133SCarlos Alberto Enciso   Runs.emplace_back(CurrentBlock);
15475112133SCarlos Alberto Enciso   while (!Blocks.empty()) {
15575112133SCarlos Alberto Enciso     Run *CurrentRun = &Runs.back();
15675112133SCarlos Alberto Enciso     uint32_t NextBlock = Blocks.front();
15775112133SCarlos Alberto Enciso     if (NextBlock < CurrentBlock || (NextBlock - CurrentBlock > 1)) {
15875112133SCarlos Alberto Enciso       Runs.emplace_back(NextBlock);
15975112133SCarlos Alberto Enciso       CurrentRun = &Runs.back();
16075112133SCarlos Alberto Enciso     }
16175112133SCarlos Alberto Enciso     uint64_t Used =
16275112133SCarlos Alberto Enciso         std::min(static_cast<uint64_t>(BlockSize), StreamBytesRemaining);
16375112133SCarlos Alberto Enciso     CurrentRun->ByteLen += Used;
16475112133SCarlos Alberto Enciso     StreamBytesRemaining -= Used;
16575112133SCarlos Alberto Enciso     CurrentBlock = NextBlock;
16675112133SCarlos Alberto Enciso     Blocks = Blocks.drop_front();
16775112133SCarlos Alberto Enciso   }
16875112133SCarlos Alberto Enciso   return Runs;
16975112133SCarlos Alberto Enciso }
17075112133SCarlos Alberto Enciso 
findRun(uint64_t Offset,ArrayRef<Run> Runs)17175112133SCarlos Alberto Enciso static std::pair<Run, uint64_t> findRun(uint64_t Offset, ArrayRef<Run> Runs) {
17275112133SCarlos Alberto Enciso   for (const auto &R : Runs) {
17375112133SCarlos Alberto Enciso     if (Offset < R.ByteLen)
17475112133SCarlos Alberto Enciso       return std::make_pair(R, Offset);
17575112133SCarlos Alberto Enciso     Offset -= R.ByteLen;
17675112133SCarlos Alberto Enciso   }
17775112133SCarlos Alberto Enciso   llvm_unreachable("Invalid offset!");
17875112133SCarlos Alberto Enciso }
17975112133SCarlos Alberto Enciso 
formatMsfStreamData(StringRef Label,PDBFile & File,uint32_t StreamIdx,StringRef StreamPurpose,uint64_t Offset,uint64_t Size)18075112133SCarlos Alberto Enciso void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,
18175112133SCarlos Alberto Enciso                                       uint32_t StreamIdx,
18275112133SCarlos Alberto Enciso                                       StringRef StreamPurpose, uint64_t Offset,
18375112133SCarlos Alberto Enciso                                       uint64_t Size) {
18475112133SCarlos Alberto Enciso   if (StreamIdx >= File.getNumStreams()) {
18575112133SCarlos Alberto Enciso     formatLine("Stream {0}: Not present", StreamIdx);
18675112133SCarlos Alberto Enciso     return;
18775112133SCarlos Alberto Enciso   }
18875112133SCarlos Alberto Enciso   if (Size + Offset > File.getStreamByteSize(StreamIdx)) {
18975112133SCarlos Alberto Enciso     formatLine(
19075112133SCarlos Alberto Enciso         "Stream {0}: Invalid offset and size, range out of stream bounds",
19175112133SCarlos Alberto Enciso         StreamIdx);
19275112133SCarlos Alberto Enciso     return;
19375112133SCarlos Alberto Enciso   }
19475112133SCarlos Alberto Enciso 
19575112133SCarlos Alberto Enciso   auto S = File.createIndexedStream(StreamIdx);
19675112133SCarlos Alberto Enciso   if (!S) {
19775112133SCarlos Alberto Enciso     NewLine();
19875112133SCarlos Alberto Enciso     formatLine("Stream {0}: Not present", StreamIdx);
19975112133SCarlos Alberto Enciso     return;
20075112133SCarlos Alberto Enciso   }
20175112133SCarlos Alberto Enciso 
20275112133SCarlos Alberto Enciso   uint64_t End =
20375112133SCarlos Alberto Enciso       (Size == 0) ? S->getLength() : std::min(Offset + Size, S->getLength());
20475112133SCarlos Alberto Enciso   Size = End - Offset;
20575112133SCarlos Alberto Enciso 
20675112133SCarlos Alberto Enciso   formatLine("Stream {0}: {1} (dumping {2:N} / {3:N} bytes)", StreamIdx,
20775112133SCarlos Alberto Enciso              StreamPurpose, Size, S->getLength());
20875112133SCarlos Alberto Enciso   AutoIndent Indent(*this);
20975112133SCarlos Alberto Enciso   BinaryStreamRef Slice(*S);
21075112133SCarlos Alberto Enciso   BinarySubstreamRef Substream;
21175112133SCarlos Alberto Enciso   Substream.Offset = Offset;
21275112133SCarlos Alberto Enciso   Substream.StreamData = Slice.drop_front(Offset).keep_front(Size);
21375112133SCarlos Alberto Enciso 
21475112133SCarlos Alberto Enciso   auto Layout = File.getStreamLayout(StreamIdx);
21575112133SCarlos Alberto Enciso   formatMsfStreamData(Label, File, Layout, Substream);
21675112133SCarlos Alberto Enciso }
21775112133SCarlos Alberto Enciso 
formatMsfStreamData(StringRef Label,PDBFile & File,const msf::MSFStreamLayout & Stream,BinarySubstreamRef Substream)21875112133SCarlos Alberto Enciso void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,
21975112133SCarlos Alberto Enciso                                       const msf::MSFStreamLayout &Stream,
22075112133SCarlos Alberto Enciso                                       BinarySubstreamRef Substream) {
22175112133SCarlos Alberto Enciso   BinaryStreamReader Reader(Substream.StreamData);
22275112133SCarlos Alberto Enciso 
22375112133SCarlos Alberto Enciso   auto Runs = computeBlockRuns(File.getBlockSize(), Stream);
22475112133SCarlos Alberto Enciso 
22575112133SCarlos Alberto Enciso   NewLine();
22675112133SCarlos Alberto Enciso   OS << Label << " (";
22775112133SCarlos Alberto Enciso   while (Reader.bytesRemaining() > 0) {
22875112133SCarlos Alberto Enciso     OS << "\n";
22975112133SCarlos Alberto Enciso 
23075112133SCarlos Alberto Enciso     Run FoundRun;
23175112133SCarlos Alberto Enciso     uint64_t RunOffset;
23275112133SCarlos Alberto Enciso     std::tie(FoundRun, RunOffset) = findRun(Substream.Offset, Runs);
23375112133SCarlos Alberto Enciso     assert(FoundRun.ByteLen >= RunOffset);
23475112133SCarlos Alberto Enciso     uint64_t Len = FoundRun.ByteLen - RunOffset;
23575112133SCarlos Alberto Enciso     Len = std::min(Len, Reader.bytesRemaining());
23675112133SCarlos Alberto Enciso     uint64_t Base = FoundRun.Block * File.getBlockSize() + RunOffset;
23775112133SCarlos Alberto Enciso     ArrayRef<uint8_t> Data;
23875112133SCarlos Alberto Enciso     consumeError(Reader.readBytes(Data, Len));
23975112133SCarlos Alberto Enciso     OS << format_bytes_with_ascii(Data, Base, 32, 4,
24075112133SCarlos Alberto Enciso                                   CurrentIndent + IndentSpaces, true);
24175112133SCarlos Alberto Enciso     if (Reader.bytesRemaining() > 0) {
24275112133SCarlos Alberto Enciso       NewLine();
24375112133SCarlos Alberto Enciso       OS << formatv("  {0}",
24475112133SCarlos Alberto Enciso                     fmt_align("<discontinuity>", AlignStyle::Center, 114, '-'));
24575112133SCarlos Alberto Enciso     }
24675112133SCarlos Alberto Enciso     Substream.Offset += Len;
24775112133SCarlos Alberto Enciso   }
24875112133SCarlos Alberto Enciso   NewLine();
24975112133SCarlos Alberto Enciso   OS << ")";
25075112133SCarlos Alberto Enciso }
25175112133SCarlos Alberto Enciso 
formatMsfStreamBlocks(PDBFile & File,const msf::MSFStreamLayout & StreamLayout)25275112133SCarlos Alberto Enciso void LinePrinter::formatMsfStreamBlocks(
25375112133SCarlos Alberto Enciso     PDBFile &File, const msf::MSFStreamLayout &StreamLayout) {
25475112133SCarlos Alberto Enciso   auto Blocks = makeArrayRef(StreamLayout.Blocks);
25575112133SCarlos Alberto Enciso   uint64_t L = StreamLayout.Length;
25675112133SCarlos Alberto Enciso 
25775112133SCarlos Alberto Enciso   while (L > 0) {
25875112133SCarlos Alberto Enciso     NewLine();
25975112133SCarlos Alberto Enciso     assert(!Blocks.empty());
26075112133SCarlos Alberto Enciso     OS << formatv("Block {0} (\n", uint32_t(Blocks.front()));
26175112133SCarlos Alberto Enciso     uint64_t UsedBytes =
26275112133SCarlos Alberto Enciso         std::min(L, static_cast<uint64_t>(File.getBlockSize()));
26375112133SCarlos Alberto Enciso     ArrayRef<uint8_t> BlockData =
26475112133SCarlos Alberto Enciso         cantFail(File.getBlockData(Blocks.front(), File.getBlockSize()));
26575112133SCarlos Alberto Enciso     uint64_t BaseOffset = Blocks.front();
26675112133SCarlos Alberto Enciso     BaseOffset *= File.getBlockSize();
26775112133SCarlos Alberto Enciso     OS << format_bytes_with_ascii(BlockData, BaseOffset, 32, 4,
26875112133SCarlos Alberto Enciso                                   CurrentIndent + IndentSpaces, true);
26975112133SCarlos Alberto Enciso     NewLine();
27075112133SCarlos Alberto Enciso     OS << ")";
27175112133SCarlos Alberto Enciso     NewLine();
27275112133SCarlos Alberto Enciso     L -= UsedBytes;
27375112133SCarlos Alberto Enciso     Blocks = Blocks.drop_front();
27475112133SCarlos Alberto Enciso   }
27575112133SCarlos Alberto Enciso }
27675112133SCarlos Alberto Enciso 
IsTypeExcluded(llvm::StringRef TypeName,uint64_t Size)27775112133SCarlos Alberto Enciso bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint64_t Size) {
27875112133SCarlos Alberto Enciso   if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
27975112133SCarlos Alberto Enciso     return true;
28075112133SCarlos Alberto Enciso   if (Size < Filters.SizeThreshold)
28175112133SCarlos Alberto Enciso     return true;
28275112133SCarlos Alberto Enciso   return false;
28375112133SCarlos Alberto Enciso }
28475112133SCarlos Alberto Enciso 
IsSymbolExcluded(llvm::StringRef SymbolName)28575112133SCarlos Alberto Enciso bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {
28675112133SCarlos Alberto Enciso   return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);
28775112133SCarlos Alberto Enciso }
28875112133SCarlos Alberto Enciso 
IsCompilandExcluded(llvm::StringRef CompilandName)28975112133SCarlos Alberto Enciso bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {
29075112133SCarlos Alberto Enciso   return IsItemExcluded(CompilandName, IncludeCompilandFilters,
29175112133SCarlos Alberto Enciso                         ExcludeCompilandFilters);
29275112133SCarlos Alberto Enciso }
29375112133SCarlos Alberto Enciso 
WithColor(LinePrinter & P,PDB_ColorItem C)29475112133SCarlos Alberto Enciso WithColor::WithColor(LinePrinter &P, PDB_ColorItem C)
29575112133SCarlos Alberto Enciso     : OS(P.OS), UseColor(P.hasColor()) {
29675112133SCarlos Alberto Enciso   if (UseColor)
29775112133SCarlos Alberto Enciso     applyColor(C);
29875112133SCarlos Alberto Enciso }
29975112133SCarlos Alberto Enciso 
~WithColor()30075112133SCarlos Alberto Enciso WithColor::~WithColor() {
30175112133SCarlos Alberto Enciso   if (UseColor)
30275112133SCarlos Alberto Enciso     OS.resetColor();
30375112133SCarlos Alberto Enciso }
30475112133SCarlos Alberto Enciso 
applyColor(PDB_ColorItem C)30575112133SCarlos Alberto Enciso void WithColor::applyColor(PDB_ColorItem C) {
30675112133SCarlos Alberto Enciso   switch (C) {
30775112133SCarlos Alberto Enciso   case PDB_ColorItem::None:
30875112133SCarlos Alberto Enciso     OS.resetColor();
30975112133SCarlos Alberto Enciso     return;
31075112133SCarlos Alberto Enciso   case PDB_ColorItem::Comment:
31175112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::GREEN, false);
31275112133SCarlos Alberto Enciso     return;
31375112133SCarlos Alberto Enciso   case PDB_ColorItem::Address:
31475112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);
31575112133SCarlos Alberto Enciso     return;
31675112133SCarlos Alberto Enciso   case PDB_ColorItem::Keyword:
31775112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::MAGENTA, true);
31875112133SCarlos Alberto Enciso     return;
31975112133SCarlos Alberto Enciso   case PDB_ColorItem::Register:
32075112133SCarlos Alberto Enciso   case PDB_ColorItem::Offset:
32175112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::YELLOW, false);
32275112133SCarlos Alberto Enciso     return;
32375112133SCarlos Alberto Enciso   case PDB_ColorItem::Type:
32475112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::CYAN, true);
32575112133SCarlos Alberto Enciso     return;
32675112133SCarlos Alberto Enciso   case PDB_ColorItem::Identifier:
32775112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::CYAN, false);
32875112133SCarlos Alberto Enciso     return;
32975112133SCarlos Alberto Enciso   case PDB_ColorItem::Path:
33075112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::CYAN, false);
33175112133SCarlos Alberto Enciso     return;
33275112133SCarlos Alberto Enciso   case PDB_ColorItem::Padding:
33375112133SCarlos Alberto Enciso   case PDB_ColorItem::SectionHeader:
33475112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::RED, true);
33575112133SCarlos Alberto Enciso     return;
33675112133SCarlos Alberto Enciso   case PDB_ColorItem::LiteralValue:
33775112133SCarlos Alberto Enciso     OS.changeColor(raw_ostream::GREEN, true);
33875112133SCarlos Alberto Enciso     return;
33975112133SCarlos Alberto Enciso   }
34075112133SCarlos Alberto Enciso }
341