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

source code of llvm/include/llvm/DebugInfo/Symbolize/MarkupFilter.h