blob: aae8809be631b9aec7cfd8a3b593ea2fe5a69059 [file] [log] [blame]
Zachary Turner2d11c202015-02-27 09:15:59 +00001//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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-exception
Zachary Turner2d11c202015-02-27 09:15:59 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "LinePrinter.h"
10
Zachary Turnerbd336e42017-06-09 20:46:17 +000011#include "llvm-pdbutil.h"
Zachary Turner7797c722015-03-02 04:39:56 +000012
Sanjoy Dasff3b8b42015-12-01 07:49:23 +000013#include "llvm/ADT/STLExtras.h"
Zachary Turner0b36c3e2017-06-23 18:52:13 +000014#include "llvm/DebugInfo/MSF/MSFCommon.h"
Zachary Turner0b36c3e2017-06-23 18:52:13 +000015#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
16#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
Zachary Turner4dc4f012017-04-13 21:11:00 +000017#include "llvm/DebugInfo/PDB/UDTLayout.h"
Zachary Turner0b36c3e2017-06-23 18:52:13 +000018#include "llvm/Support/BinaryStreamReader.h"
Zachary Turner63055452017-06-15 22:24:24 +000019#include "llvm/Support/Format.h"
Zachary Turner0b36c3e2017-06-23 18:52:13 +000020#include "llvm/Support/FormatAdapters.h"
21#include "llvm/Support/FormatVariadic.h"
Zachary Turnerf5abda22015-03-01 06:49:49 +000022#include "llvm/Support/Regex.h"
23
Zachary Turner2d11c202015-02-27 09:15:59 +000024#include <algorithm>
25
Zachary Turnerec28fc32016-05-04 20:32:13 +000026using namespace llvm;
Zachary Turner0b36c3e2017-06-23 18:52:13 +000027using namespace llvm::msf;
Zachary Turnerec28fc32016-05-04 20:32:13 +000028using namespace llvm::pdb;
29
Zachary Turner4dddcc62015-09-29 19:49:06 +000030namespace {
Zachary Turner4dddcc62015-09-29 19:49:06 +000031bool IsItemExcluded(llvm::StringRef Item,
32 std::list<llvm::Regex> &IncludeFilters,
33 std::list<llvm::Regex> &ExcludeFilters) {
34 if (Item.empty())
35 return false;
36
37 auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };
38
39 // Include takes priority over exclude. If the user specified include
40 // filters, and none of them include this item, them item is gone.
Sanjoy Dasff3b8b42015-12-01 07:49:23 +000041 if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))
Zachary Turner4dddcc62015-09-29 19:49:06 +000042 return true;
43
Sanjoy Dasff3b8b42015-12-01 07:49:23 +000044 if (any_of(ExcludeFilters, match_pred))
Zachary Turner4dddcc62015-09-29 19:49:06 +000045 return true;
46
47 return false;
48}
49}
50
Zachary Turner2d11c202015-02-27 09:15:59 +000051using namespace llvm;
52
Adrian McCarthy1aa207d2017-03-23 15:28:15 +000053LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream)
54 : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor) {
Zachary Turnera30bd1a2016-06-30 17:42:48 +000055 SetFilters(ExcludeTypeFilters, opts::pretty::ExcludeTypes.begin(),
56 opts::pretty::ExcludeTypes.end());
57 SetFilters(ExcludeSymbolFilters, opts::pretty::ExcludeSymbols.begin(),
58 opts::pretty::ExcludeSymbols.end());
59 SetFilters(ExcludeCompilandFilters, opts::pretty::ExcludeCompilands.begin(),
60 opts::pretty::ExcludeCompilands.end());
Zachary Turner4dddcc62015-09-29 19:49:06 +000061
Zachary Turnera30bd1a2016-06-30 17:42:48 +000062 SetFilters(IncludeTypeFilters, opts::pretty::IncludeTypes.begin(),
63 opts::pretty::IncludeTypes.end());
64 SetFilters(IncludeSymbolFilters, opts::pretty::IncludeSymbols.begin(),
65 opts::pretty::IncludeSymbols.end());
66 SetFilters(IncludeCompilandFilters, opts::pretty::IncludeCompilands.begin(),
67 opts::pretty::IncludeCompilands.end());
Zachary Turner7797c722015-03-02 04:39:56 +000068}
Zachary Turner2d11c202015-02-27 09:15:59 +000069
Zachary Turner63055452017-06-15 22:24:24 +000070void LinePrinter::Indent(uint32_t Amount) {
71 if (Amount == 0)
72 Amount = IndentSpaces;
73 CurrentIndent += Amount;
74}
Zachary Turner2d11c202015-02-27 09:15:59 +000075
Zachary Turner63055452017-06-15 22:24:24 +000076void LinePrinter::Unindent(uint32_t Amount) {
77 if (Amount == 0)
78 Amount = IndentSpaces;
79 CurrentIndent = std::max<int>(0, CurrentIndent - Amount);
Zachary Turner2d11c202015-02-27 09:15:59 +000080}
81
82void LinePrinter::NewLine() {
83 OS << "\n";
84 OS.indent(CurrentIndent);
85}
86
Zachary Turner63055452017-06-15 22:24:24 +000087void LinePrinter::print(const Twine &T) { OS << T; }
88
89void LinePrinter::printLine(const Twine &T) {
90 NewLine();
91 OS << T;
92}
93
Zachary Turner4dc4f012017-04-13 21:11:00 +000094bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
Zachary Turner16901642017-04-24 17:47:24 +000095 if (IsTypeExcluded(Class.getName(), Class.getSize()))
Zachary Turner4dc4f012017-04-13 21:11:00 +000096 return true;
97 if (Class.deepPaddingSize() < opts::pretty::PaddingThreshold)
98 return true;
99 return false;
100}
101
Zachary Turner63055452017-06-15 22:24:24 +0000102void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
103 uint32_t StartOffset) {
104 NewLine();
105 OS << Label << " (";
106 if (!Data.empty()) {
107 OS << "\n";
108 OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,
109 CurrentIndent + IndentSpaces, true);
110 NewLine();
111 }
112 OS << ")";
113}
114
Zachary Turner99402032017-06-22 20:58:11 +0000115void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
116 uint64_t Base, uint32_t StartOffset) {
117 NewLine();
118 OS << Label << " (";
119 if (!Data.empty()) {
120 OS << "\n";
121 Base += StartOffset;
122 OS << format_bytes_with_ascii(Data, Base, 32, 4,
123 CurrentIndent + IndentSpaces, true);
124 NewLine();
125 }
126 OS << ")";
127}
128
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000129namespace {
130struct Run {
131 Run() = default;
132 explicit Run(uint32_t Block) : Block(Block) {}
133 uint32_t Block = 0;
134 uint32_t ByteLen = 0;
135};
136} // namespace
137
138static std::vector<Run> computeBlockRuns(uint32_t BlockSize,
139 const msf::MSFStreamLayout &Layout) {
140 std::vector<Run> Runs;
141 if (Layout.Length == 0)
142 return Runs;
143
144 ArrayRef<support::ulittle32_t> Blocks = Layout.Blocks;
145 assert(!Blocks.empty());
146 uint32_t StreamBytesRemaining = Layout.Length;
Zachary Turnerdd739682017-06-23 21:11:54 +0000147 uint32_t CurrentBlock = Blocks[0];
148 Runs.emplace_back(CurrentBlock);
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000149 while (!Blocks.empty()) {
150 Run *CurrentRun = &Runs.back();
151 uint32_t NextBlock = Blocks.front();
Zachary Turnerdd739682017-06-23 21:11:54 +0000152 if (NextBlock < CurrentBlock || (NextBlock - CurrentBlock > 1)) {
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000153 Runs.emplace_back(NextBlock);
154 CurrentRun = &Runs.back();
155 }
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000156 uint32_t Used = std::min(BlockSize, StreamBytesRemaining);
157 CurrentRun->ByteLen += Used;
158 StreamBytesRemaining -= Used;
Zachary Turnerdd739682017-06-23 21:11:54 +0000159 CurrentBlock = NextBlock;
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000160 Blocks = Blocks.drop_front();
161 }
162 return Runs;
163}
164
165static std::pair<Run, uint32_t> findRun(uint32_t Offset, ArrayRef<Run> Runs) {
166 for (const auto &R : Runs) {
167 if (Offset < R.ByteLen)
168 return std::make_pair(R, Offset);
169 Offset -= R.ByteLen;
170 }
171 llvm_unreachable("Invalid offset!");
172}
173
174void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,
175 uint32_t StreamIdx,
176 StringRef StreamPurpose, uint32_t Offset,
177 uint32_t Size) {
178 if (StreamIdx >= File.getNumStreams()) {
179 formatLine("Stream {0}: Not present", StreamIdx);
180 return;
181 }
182 if (Size + Offset > File.getStreamByteSize(StreamIdx)) {
183 formatLine(
184 "Stream {0}: Invalid offset and size, range out of stream bounds",
185 StreamIdx);
186 return;
187 }
188
189 auto S = MappedBlockStream::createIndexedStream(
190 File.getMsfLayout(), File.getMsfBuffer(), StreamIdx, File.getAllocator());
191 if (!S) {
192 NewLine();
193 formatLine("Stream {0}: Not present", StreamIdx);
194 return;
195 }
196
197 uint32_t End =
198 (Size == 0) ? S->getLength() : std::min(Offset + Size, S->getLength());
199 Size = End - Offset;
200
201 formatLine("Stream {0}: {1} (dumping {2:N} / {3:N} bytes)", StreamIdx,
202 StreamPurpose, Size, S->getLength());
203 AutoIndent Indent(*this);
204 BinaryStreamRef Slice(*S);
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000205 BinarySubstreamRef Substream;
206 Substream.Offset = Offset;
207 Substream.StreamData = Slice.drop_front(Offset).keep_front(Size);
208
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000209 auto Layout = File.getStreamLayout(StreamIdx);
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000210 formatMsfStreamData(Label, File, Layout, Substream);
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000211}
212
213void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File,
214 const msf::MSFStreamLayout &Stream,
215 BinarySubstreamRef Substream) {
216 BinaryStreamReader Reader(Substream.StreamData);
217
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000218 auto Runs = computeBlockRuns(File.getBlockSize(), Stream);
219
220 NewLine();
221 OS << Label << " (";
222 while (Reader.bytesRemaining() > 0) {
223 OS << "\n";
224
225 Run FoundRun;
226 uint32_t RunOffset;
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000227 std::tie(FoundRun, RunOffset) = findRun(Substream.Offset, Runs);
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000228 assert(FoundRun.ByteLen >= RunOffset);
229 uint32_t Len = FoundRun.ByteLen - RunOffset;
230 Len = std::min(Len, Reader.bytesRemaining());
231 uint64_t Base = FoundRun.Block * File.getBlockSize() + RunOffset;
232 ArrayRef<uint8_t> Data;
233 consumeError(Reader.readBytes(Data, Len));
234 OS << format_bytes_with_ascii(Data, Base, 32, 4,
235 CurrentIndent + IndentSpaces, true);
236 if (Reader.bytesRemaining() > 0) {
237 NewLine();
238 OS << formatv(" {0}",
239 fmt_align("<discontinuity>", AlignStyle::Center, 114, '-'));
240 }
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000241 Substream.Offset += Len;
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000242 }
243 NewLine();
244 OS << ")";
245}
246
Zachary Turnerc3d8eec2017-08-02 22:25:52 +0000247void LinePrinter::formatMsfStreamBlocks(
248 PDBFile &File, const msf::MSFStreamLayout &StreamLayout) {
249 auto Blocks = makeArrayRef(StreamLayout.Blocks);
250 uint32_t L = StreamLayout.Length;
251
252 while (L > 0) {
253 NewLine();
254 assert(!Blocks.empty());
255 OS << formatv("Block {0} (\n", uint32_t(Blocks.front()));
256 uint32_t UsedBytes = std::min(L, File.getBlockSize());
257 ArrayRef<uint8_t> BlockData =
258 cantFail(File.getBlockData(Blocks.front(), File.getBlockSize()));
259 uint64_t BaseOffset = Blocks.front();
260 BaseOffset *= File.getBlockSize();
261 OS << format_bytes_with_ascii(BlockData, BaseOffset, 32, 4,
262 CurrentIndent + IndentSpaces, true);
263 NewLine();
264 OS << ")";
265 NewLine();
266 L -= UsedBytes;
267 Blocks = Blocks.drop_front();
268 }
269}
270
Zachary Turner4dc4f012017-04-13 21:11:00 +0000271bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) {
272 if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
273 return true;
274 if (Size < opts::pretty::SizeThreshold)
275 return true;
276 return false;
Zachary Turnerf5abda22015-03-01 06:49:49 +0000277}
278
279bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {
Zachary Turner4dddcc62015-09-29 19:49:06 +0000280 return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);
Zachary Turnerf5abda22015-03-01 06:49:49 +0000281}
282
283bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {
Zachary Turner4dddcc62015-09-29 19:49:06 +0000284 return IsItemExcluded(CompilandName, IncludeCompilandFilters,
285 ExcludeCompilandFilters);
Zachary Turnerf5abda22015-03-01 06:49:49 +0000286}
287
Adrian McCarthy5fcfc2c2017-03-29 17:11:27 +0000288WithColor::WithColor(LinePrinter &P, PDB_ColorItem C)
289 : OS(P.OS), UseColor(P.hasColor()) {
290 if (UseColor)
Adrian McCarthy1aa207d2017-03-23 15:28:15 +0000291 applyColor(C);
Zachary Turner2d11c202015-02-27 09:15:59 +0000292}
293
Adrian McCarthy5fcfc2c2017-03-29 17:11:27 +0000294WithColor::~WithColor() {
295 if (UseColor)
296 OS.resetColor();
297}
Zachary Turner2d11c202015-02-27 09:15:59 +0000298
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000299void WithColor::applyColor(PDB_ColorItem C) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000300 switch (C) {
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000301 case PDB_ColorItem::None:
302 OS.resetColor();
303 return;
Zachary Turner0c990bbe2017-04-10 19:33:29 +0000304 case PDB_ColorItem::Comment:
305 OS.changeColor(raw_ostream::GREEN, false);
306 return;
Zachary Turner2d11c202015-02-27 09:15:59 +0000307 case PDB_ColorItem::Address:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000308 OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000309 return;
310 case PDB_ColorItem::Keyword:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000311 OS.changeColor(raw_ostream::MAGENTA, true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000312 return;
Zachary Turner7797c722015-03-02 04:39:56 +0000313 case PDB_ColorItem::Register:
Zachary Turner2d11c202015-02-27 09:15:59 +0000314 case PDB_ColorItem::Offset:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000315 OS.changeColor(raw_ostream::YELLOW, false);
Zachary Turner2d11c202015-02-27 09:15:59 +0000316 return;
317 case PDB_ColorItem::Type:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000318 OS.changeColor(raw_ostream::CYAN, true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000319 return;
320 case PDB_ColorItem::Identifier:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000321 OS.changeColor(raw_ostream::CYAN, false);
Zachary Turner2d11c202015-02-27 09:15:59 +0000322 return;
323 case PDB_ColorItem::Path:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000324 OS.changeColor(raw_ostream::CYAN, false);
Zachary Turner2d11c202015-02-27 09:15:59 +0000325 return;
Zachary Turner0c990bbe2017-04-10 19:33:29 +0000326 case PDB_ColorItem::Padding:
Zachary Turner2d11c202015-02-27 09:15:59 +0000327 case PDB_ColorItem::SectionHeader:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000328 OS.changeColor(raw_ostream::RED, true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000329 return;
330 case PDB_ColorItem::LiteralValue:
Rui Ueyamafa05aac2015-11-03 01:04:44 +0000331 OS.changeColor(raw_ostream::GREEN, true);
Zachary Turner2d11c202015-02-27 09:15:59 +0000332 return;
333 }
334}