1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
//===- MarkupFilter.h -------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares a filter that replaces symbolizer markup with
/// human-readable expressions.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_SYMBOLIZE_MARKUPFILTER_H
#define LLVM_DEBUGINFO_SYMBOLIZE_MARKUPFILTER_H
#include "Markup.h"
#include <map>
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace symbolize {
class LLVMSymbolizer;
/// Filter to convert parsed log symbolizer markup elements into human-readable
/// text.
class MarkupFilter {
public:
MarkupFilter(raw_ostream &OS, LLVMSymbolizer &Symbolizer,
Optional<bool> ColorsEnabled = llvm::None);
/// Filters a line containing symbolizer markup and writes the human-readable
/// results to the output stream.
///
/// Invalid or unimplemented markup elements are removed. Some output may be
/// deferred until future filter() or finish() call.
void filter(StringRef Line);
/// Records that the input stream has ended and writes any deferred output.
void finish();
private:
struct Module {
uint64_t ID;
std::string Name;
SmallVector<uint8_t> BuildID;
};
struct MMap {
uint64_t Addr;
uint64_t Size;
const Module *Mod;
std::string Mode; // Lowercase
uint64_t ModuleRelativeAddr;
bool contains(uint64_t Addr) const;
uint64_t getModuleRelativeAddr(uint64_t Addr) const;
};
// An informational module line currently being constructed. As many mmap
// elements as possible are folded into one ModuleInfo line.
struct ModuleInfoLine {
const Module *Mod;
SmallVector<const MMap *> MMaps = {};
};
// The semantics of a possible program counter value.
enum class PCType {
// The address is a return address and must be adjusted to point to the call
// itself.
ReturnAddress,
// The address is the precise location in the code and needs no adjustment.
PreciseCode,
};
bool tryContextualElement(const MarkupNode &Node,
const SmallVector<MarkupNode> &DeferredNodes);
bool tryMMap(const MarkupNode &Element,
const SmallVector<MarkupNode> &DeferredNodes);
bool tryReset(const MarkupNode &Element,
const SmallVector<MarkupNode> &DeferredNodes);
bool tryModule(const MarkupNode &Element,
const SmallVector<MarkupNode> &DeferredNodes);
void beginModuleInfoLine(const Module *M);
void endAnyModuleInfoLine();
void filterNode(const MarkupNode &Node);
bool tryPresentation(const MarkupNode &Node);
bool trySymbol(const MarkupNode &Node);
bool tryPC(const MarkupNode &Node);
bool tryBackTrace(const MarkupNode &Node);
bool tryData(const MarkupNode &Node);
bool trySGR(const MarkupNode &Node);
void highlight();
void highlightValue();
void restoreColor();
void resetColor();
void printRawElement(const MarkupNode &Element);
void printValue(Twine Value);
Optional<Module> parseModule(const MarkupNode &Element) const;
Optional<MMap> parseMMap(const MarkupNode &Element) const;
Optional<uint64_t> parseAddr(StringRef Str) const;
Optional<uint64_t> parseModuleID(StringRef Str) const;
Optional<uint64_t> parseSize(StringRef Str) const;
Optional<SmallVector<uint8_t>> parseBuildID(StringRef Str) const;
Optional<std::string> parseMode(StringRef Str) const;
Optional<PCType> parsePCType(StringRef Str) const;
Optional<uint64_t> parseFrameNumber(StringRef Str) const;
bool checkTag(const MarkupNode &Node) const;
bool checkNumFields(const MarkupNode &Element, size_t Size) const;
bool checkNumFieldsAtLeast(const MarkupNode &Element, size_t Size) const;
bool checkNumFieldsAtMost(const MarkupNode &Element, size_t Size) const;
void reportTypeError(StringRef Str, StringRef TypeName) const;
void reportLocation(StringRef::iterator Loc) const;
const MMap *getOverlappingMMap(const MMap &Map) const;
const MMap *getContainingMMap(uint64_t Addr) const;
uint64_t adjustAddr(uint64_t Addr, PCType Type) const;
StringRef lineEnding() const;
raw_ostream &OS;
LLVMSymbolizer &Symbolizer;
const bool ColorsEnabled;
MarkupParser Parser;
// Current line being filtered.
StringRef Line;
// A module info line currently being built. This incorporates as much mmap
// information as possible before being emitted.
Optional<ModuleInfoLine> MIL;
// SGR state.
Optional<raw_ostream::Colors> Color;
bool Bold = false;
// Map from Module ID to Module.
DenseMap<uint64_t, std::unique_ptr<Module>> Modules;
// Ordered map from starting address to mmap.
std::map<uint64_t, MMap> MMaps;
};
} // end namespace symbolize
} // end namespace llvm
#endif // LLVM_DEBUGINFO_SYMBOLIZE_MARKUPFILTER_H
|