LLVM 24.0.0git
LinePrinter.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "llvm/ADT/STLExtras.h"
18#include "llvm/Object/COFF.h"
20#include "llvm/Support/Format.h"
23#include "llvm/Support/Regex.h"
24
25#include <algorithm>
26
27using namespace llvm;
28using namespace llvm::msf;
29using namespace llvm::pdb;
30
31namespace {
32bool IsItemExcluded(llvm::StringRef Item,
33 std::list<llvm::Regex> &IncludeFilters,
34 std::list<llvm::Regex> &ExcludeFilters) {
35 if (Item.empty())
36 return false;
37
38 auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };
39
40 // Include takes priority over exclude. If the user specified include
41 // filters, and none of them include this item, them item is gone.
42 if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))
43 return true;
44
45 if (any_of(ExcludeFilters, match_pred))
46 return true;
47
48 return false;
49}
50} // namespace
51
52using namespace llvm;
53
55 const FilterOptions &Filters)
56 : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor),
57 Filters(Filters) {
58 SetFilters(ExcludeTypeFilters, Filters.ExcludeTypes.begin(),
59 Filters.ExcludeTypes.end());
60 SetFilters(ExcludeSymbolFilters, Filters.ExcludeSymbols.begin(),
61 Filters.ExcludeSymbols.end());
62 SetFilters(ExcludeCompilandFilters, Filters.ExcludeCompilands.begin(),
63 Filters.ExcludeCompilands.end());
64
65 SetFilters(IncludeTypeFilters, Filters.IncludeTypes.begin(),
66 Filters.IncludeTypes.end());
67 SetFilters(IncludeSymbolFilters, Filters.IncludeSymbols.begin(),
68 Filters.IncludeSymbols.end());
69 SetFilters(IncludeCompilandFilters, Filters.IncludeCompilands.begin(),
70 Filters.IncludeCompilands.end());
71}
72
74 if (Amount == 0)
75 Amount = IndentSpaces;
76 CurrentIndent += Amount;
77}
78
80 if (Amount == 0)
81 Amount = IndentSpaces;
82 CurrentIndent = std::max<int>(0, CurrentIndent - Amount);
83}
84
86 OS << "\n";
87 OS.indent(CurrentIndent);
88}
89
90void LinePrinter::print(const Twine &T) { OS << T; }
91
93 NewLine();
94 OS << T;
95}
96
98 if (IsTypeExcluded(Class.getName(), Class.getSize()))
99 return true;
100 if (Class.deepPaddingSize() < Filters.PaddingThreshold)
101 return true;
102 return false;
103}
104
106 uint64_t StartOffset) {
107 NewLine();
108 OS << Label << " (";
109 if (!Data.empty()) {
110 OS << "\n";
111 OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,
112 CurrentIndent + IndentSpaces, true);
113 NewLine();
114 }
115 OS << ")";
116}
117
119 uint64_t Base, uint64_t StartOffset) {
120 NewLine();
121 OS << Label << " (";
122 if (!Data.empty()) {
123 OS << "\n";
124 Base += StartOffset;
125 OS << format_bytes_with_ascii(Data, Base, 32, 4,
126 CurrentIndent + IndentSpaces, true);
127 NewLine();
128 }
129 OS << ")";
130}
131
132namespace {
133struct Run {
134 Run() = default;
135 explicit Run(uint32_t Block) : Block(Block) {}
136 uint32_t Block = 0;
137 uint64_t ByteLen = 0;
138};
139} // namespace
140
141static std::vector<Run> computeBlockRuns(uint32_t BlockSize,
142 const msf::MSFStreamLayout &Layout) {
143 std::vector<Run> Runs;
144 if (Layout.Length == 0)
145 return Runs;
146
148 assert(!Blocks.empty());
149 uint64_t StreamBytesRemaining = Layout.Length;
150 uint32_t CurrentBlock = Blocks[0];
151 Runs.emplace_back(CurrentBlock);
152 while (!Blocks.empty()) {
153 Run *CurrentRun = &Runs.back();
154 uint32_t NextBlock = Blocks.front();
155 if (NextBlock < CurrentBlock || (NextBlock - CurrentBlock > 1)) {
156 Runs.emplace_back(NextBlock);
157 CurrentRun = &Runs.back();
158 }
159 uint64_t Used =
160 std::min(static_cast<uint64_t>(BlockSize), StreamBytesRemaining);
161 CurrentRun->ByteLen += Used;
162 StreamBytesRemaining -= Used;
163 CurrentBlock = NextBlock;
164 Blocks = Blocks.drop_front();
165 }
166 return Runs;
167}
168
169static std::pair<Run, uint64_t> findRun(uint64_t Offset, ArrayRef<Run> Runs) {
170 for (const auto &R : Runs) {
171 if (Offset < R.ByteLen)
172 return std::make_pair(R, Offset);
173 Offset -= R.ByteLen;
174 }
175 llvm_unreachable("Invalid offset!");
176}
177
179 uint32_t StreamIdx,
180 StringRef StreamPurpose, uint64_t Offset,
181 uint64_t Size) {
182 if (StreamIdx >= File.getNumStreams()) {
183 formatLine("Stream {0}: Not present", StreamIdx);
184 return;
185 }
186 if (Size + Offset > File.getStreamByteSize(StreamIdx)) {
188 "Stream {0}: Invalid offset and size, range out of stream bounds",
189 StreamIdx);
190 return;
191 }
192
193 auto S = File.createIndexedStream(StreamIdx);
194 if (!S) {
195 NewLine();
196 formatLine("Stream {0}: Not present", StreamIdx);
197 return;
198 }
199
200 uint64_t End =
201 (Size == 0) ? S->getLength() : std::min(Offset + Size, S->getLength());
202 Size = End - Offset;
203
204 formatLine("Stream {0}: {1} (dumping {2:N} / {3:N} bytes)", StreamIdx,
205 StreamPurpose, Size, S->getLength());
206 AutoIndent Indent(*this);
207 BinaryStreamRef Slice(*S);
208 BinarySubstreamRef Substream;
209 Substream.Offset = Offset;
210 Substream.StreamData = Slice.drop_front(Offset).keep_front(Size);
211
212 auto Layout = File.getStreamLayout(StreamIdx);
213 formatMsfStreamData(Label, File, Layout, Substream);
214}
215
217 const msf::MSFStreamLayout &Stream,
218 BinarySubstreamRef Substream) {
219 BinaryStreamReader Reader(Substream.StreamData);
220
221 auto Runs = computeBlockRuns(File.getBlockSize(), Stream);
222
223 NewLine();
224 OS << Label << " (";
225 while (Reader.bytesRemaining() > 0) {
226 OS << "\n";
227
228 Run FoundRun;
229 uint64_t RunOffset;
230 std::tie(FoundRun, RunOffset) = findRun(Substream.Offset, Runs);
231 assert(FoundRun.ByteLen >= RunOffset);
232 uint64_t Len = FoundRun.ByteLen - RunOffset;
233 Len = std::min(Len, Reader.bytesRemaining());
234 uint64_t Base = FoundRun.Block * File.getBlockSize() + RunOffset;
236 consumeError(Reader.readBytes(Data, Len));
237 OS << format_bytes_with_ascii(Data, Base, 32, 4,
238 CurrentIndent + IndentSpaces, true);
239 if (Reader.bytesRemaining() > 0) {
240 NewLine();
241 OS << formatv(" {0}",
242 fmt_align("<discontinuity>", AlignStyle::Center, 114, '-'));
243 }
244 Substream.Offset += Len;
245 }
246 NewLine();
247 OS << ")";
248}
249
251 PDBFile &File, const msf::MSFStreamLayout &StreamLayout) {
252 auto Blocks = ArrayRef(StreamLayout.Blocks);
253 uint64_t L = StreamLayout.Length;
254
255 while (L > 0) {
256 NewLine();
257 assert(!Blocks.empty());
258 OS << formatv("Block {0} (\n", uint32_t(Blocks.front()));
259 uint64_t UsedBytes =
260 std::min(L, static_cast<uint64_t>(File.getBlockSize()));
261 ArrayRef<uint8_t> BlockData =
262 cantFail(File.getBlockData(Blocks.front(), File.getBlockSize()));
263 uint64_t BaseOffset = Blocks.front();
264 BaseOffset *= File.getBlockSize();
265 OS << format_bytes_with_ascii(BlockData, BaseOffset, 32, 4,
266 CurrentIndent + IndentSpaces, true);
267 NewLine();
268 OS << ")";
269 NewLine();
270 L -= UsedBytes;
271 Blocks = Blocks.drop_front();
272 }
273}
274
276 if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
277 return true;
278 if (Size < Filters.SizeThreshold)
279 return true;
280 return false;
281}
282
284 return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);
285}
286
288 return IsItemExcluded(CompilandName, IncludeCompilandFilters,
289 ExcludeCompilandFilters);
290}
291
293 : OS(P.OS), UseColor(P.hasColor()) {
294 if (UseColor)
295 applyColor(C);
296}
297
299 if (UseColor)
300 OS.resetColor();
301}
302
303void WithColor::applyColor(PDB_ColorItem C) {
304 switch (C) {
306 OS.resetColor();
307 return;
310 return;
312 OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);
313 return;
316 return;
320 return;
323 return;
326 return;
329 return;
333 return;
336 return;
337 }
338}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static std::pair< Run, uint64_t > findRun(uint64_t Offset, ArrayRef< Run > Runs)
static std::vector< Run > computeBlockRuns(uint32_t BlockSize, const msf::MSFStreamLayout &Layout)
#define T
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
static const int BlockSize
Definition TarWriter.cpp:33
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:194
const T & front() const
Get the first element.
Definition ArrayRef.h:144
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
Provides read only access to a subclass of BinaryStream.
LLVM_ABI Error readBytes(ArrayRef< uint8_t > &Buffer, uint32_t Size)
Read Size bytes from the underlying stream at the current offset and and set Buffer to the resulting ...
RefType drop_front(uint64_t N) const
Return a new BinaryStreamRef with the first N elements removed.
RefType keep_front(uint64_t N) const
Return a new BinaryStreamRef with only the first N elements remaining.
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
Describes the layout of a stream in an MSF layout.
Definition MSFCommon.h:78
std::vector< support::ulittle32_t > Blocks
Definition MSFCommon.h:81
LLVM_ABI void print(const Twine &T)
LLVM_ABI void printLine(const Twine &T)
LLVM_ABI void Unindent(uint32_t Amount=0)
LLVM_ABI void NewLine()
LLVM_ABI void formatMsfStreamData(StringRef Label, PDBFile &File, uint32_t StreamIdx, StringRef StreamPurpose, uint64_t Offset, uint64_t Size)
LLVM_ABI bool IsSymbolExcluded(llvm::StringRef SymbolName)
LLVM_ABI LinePrinter(int Indent, bool UseColor, raw_ostream &Stream, const FilterOptions &Filters)
LLVM_ABI void formatMsfStreamBlocks(PDBFile &File, const msf::MSFStreamLayout &Stream)
void formatLine(const char *Fmt, Ts &&...Items)
Definition LinePrinter.h:65
LLVM_ABI void formatBinary(StringRef Label, ArrayRef< uint8_t > Data, uint64_t StartOffset)
LLVM_ABI bool IsTypeExcluded(llvm::StringRef TypeName, uint64_t Size)
LLVM_ABI bool IsClassExcluded(const ClassLayout &Class)
LLVM_ABI bool IsCompilandExcluded(llvm::StringRef CompilandName)
LLVM_ABI void Indent(uint32_t Amount=0)
LLVM_ABI WithColor(LinePrinter &P, PDB_ColorItem C)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
virtual raw_ostream & changeColor(enum Colors Color, bool Bold=false, bool BG=false)
Changes the foreground color of text that will be output from this point forward.
virtual raw_ostream & resetColor()
Resets the colors to terminal defaults.
static constexpr Colors GREEN
static constexpr Colors RED
static constexpr Colors MAGENTA
static constexpr Colors YELLOW
static constexpr Colors CYAN
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
FormattedBytes format_bytes_with_ascii(ArrayRef< uint8_t > Bytes, std::optional< uint64_t > FirstByteOffset=std::nullopt, uint32_t NumPerLine=16, uint8_t ByteGroupSize=4, uint32_t IndentLevel=0, bool Upper=false)
Definition Format.h:227
ArrayRef(const T &OneElt) -> ArrayRef< T >
support::detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106