181ad6265SDimitry Andric //===- MarkupFilter.h -------------------------------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric ///
981ad6265SDimitry Andric /// \file
1081ad6265SDimitry Andric /// This file declares a filter that replaces symbolizer markup with
1181ad6265SDimitry Andric /// human-readable expressions.
1281ad6265SDimitry Andric ///
1381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1481ad6265SDimitry Andric 
1581ad6265SDimitry Andric #ifndef LLVM_DEBUGINFO_SYMBOLIZE_MARKUPFILTER_H
1681ad6265SDimitry Andric #define LLVM_DEBUGINFO_SYMBOLIZE_MARKUPFILTER_H
1781ad6265SDimitry Andric 
18fcaf7f86SDimitry Andric #include "llvm/ADT/DenseMap.h"
1906c3fb27SDimitry Andric #include "llvm/DebugInfo/Symbolize/Markup.h"
2006c3fb27SDimitry Andric #include "llvm/Object/BuildID.h"
2181ad6265SDimitry Andric #include "llvm/Support/WithColor.h"
2281ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
2306c3fb27SDimitry Andric #include <map>
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric namespace llvm {
2681ad6265SDimitry Andric namespace symbolize {
2781ad6265SDimitry Andric 
28a4a491e2SDimitry Andric class LLVMSymbolizer;
29a4a491e2SDimitry Andric 
3081ad6265SDimitry Andric /// Filter to convert parsed log symbolizer markup elements into human-readable
3181ad6265SDimitry Andric /// text.
3281ad6265SDimitry Andric class MarkupFilter {
3381ad6265SDimitry Andric public:
34a4a491e2SDimitry Andric   MarkupFilter(raw_ostream &OS, LLVMSymbolizer &Symbolizer,
35bdd1243dSDimitry Andric                std::optional<bool> ColorsEnabled = std::nullopt);
3681ad6265SDimitry Andric 
37fcaf7f86SDimitry Andric   /// Filters a line containing symbolizer markup and writes the human-readable
38fcaf7f86SDimitry Andric   /// results to the output stream.
3981ad6265SDimitry Andric   ///
40fcaf7f86SDimitry Andric   /// Invalid or unimplemented markup elements are removed. Some output may be
41fcaf7f86SDimitry Andric   /// deferred until future filter() or finish() call.
42*5f757f3fSDimitry Andric   void filter(std::string &&InputLine);
4381ad6265SDimitry Andric 
44fcaf7f86SDimitry Andric   /// Records that the input stream has ended and writes any deferred output.
45fcaf7f86SDimitry Andric   void finish();
4681ad6265SDimitry Andric 
4781ad6265SDimitry Andric private:
48fcaf7f86SDimitry Andric   struct Module {
49fcaf7f86SDimitry Andric     uint64_t ID;
50fcaf7f86SDimitry Andric     std::string Name;
51fcaf7f86SDimitry Andric     SmallVector<uint8_t> BuildID;
52fcaf7f86SDimitry Andric   };
53fcaf7f86SDimitry Andric 
54fcaf7f86SDimitry Andric   struct MMap {
55fcaf7f86SDimitry Andric     uint64_t Addr;
56fcaf7f86SDimitry Andric     uint64_t Size;
57fcaf7f86SDimitry Andric     const Module *Mod;
58fcaf7f86SDimitry Andric     std::string Mode; // Lowercase
59fcaf7f86SDimitry Andric     uint64_t ModuleRelativeAddr;
60fcaf7f86SDimitry Andric 
61fcaf7f86SDimitry Andric     bool contains(uint64_t Addr) const;
62a4a491e2SDimitry Andric     uint64_t getModuleRelativeAddr(uint64_t Addr) const;
63fcaf7f86SDimitry Andric   };
64fcaf7f86SDimitry Andric 
65fcaf7f86SDimitry Andric   // An informational module line currently being constructed. As many mmap
66fcaf7f86SDimitry Andric   // elements as possible are folded into one ModuleInfo line.
67fcaf7f86SDimitry Andric   struct ModuleInfoLine {
68fcaf7f86SDimitry Andric     const Module *Mod;
69fcaf7f86SDimitry Andric 
70fcaf7f86SDimitry Andric     SmallVector<const MMap *> MMaps = {};
71fcaf7f86SDimitry Andric   };
72fcaf7f86SDimitry Andric 
73a4a491e2SDimitry Andric   // The semantics of a possible program counter value.
74a4a491e2SDimitry Andric   enum class PCType {
75a4a491e2SDimitry Andric     // The address is a return address and must be adjusted to point to the call
76a4a491e2SDimitry Andric     // itself.
77a4a491e2SDimitry Andric     ReturnAddress,
78a4a491e2SDimitry Andric     // The address is the precise location in the code and needs no adjustment.
79a4a491e2SDimitry Andric     PreciseCode,
80a4a491e2SDimitry Andric   };
81a4a491e2SDimitry Andric 
82fcaf7f86SDimitry Andric   bool tryContextualElement(const MarkupNode &Node,
83fcaf7f86SDimitry Andric                             const SmallVector<MarkupNode> &DeferredNodes);
84fcaf7f86SDimitry Andric   bool tryMMap(const MarkupNode &Element,
85fcaf7f86SDimitry Andric                const SmallVector<MarkupNode> &DeferredNodes);
86fcaf7f86SDimitry Andric   bool tryReset(const MarkupNode &Element,
87fcaf7f86SDimitry Andric                 const SmallVector<MarkupNode> &DeferredNodes);
88fcaf7f86SDimitry Andric   bool tryModule(const MarkupNode &Element,
89fcaf7f86SDimitry Andric                  const SmallVector<MarkupNode> &DeferredNodes);
90fcaf7f86SDimitry Andric 
91fcaf7f86SDimitry Andric   void beginModuleInfoLine(const Module *M);
92fcaf7f86SDimitry Andric   void endAnyModuleInfoLine();
93fcaf7f86SDimitry Andric 
94fcaf7f86SDimitry Andric   void filterNode(const MarkupNode &Node);
95fcaf7f86SDimitry Andric 
96fcaf7f86SDimitry Andric   bool tryPresentation(const MarkupNode &Node);
97fcaf7f86SDimitry Andric   bool trySymbol(const MarkupNode &Node);
98a4a491e2SDimitry Andric   bool tryPC(const MarkupNode &Node);
99a4a491e2SDimitry Andric   bool tryBackTrace(const MarkupNode &Node);
100a4a491e2SDimitry Andric   bool tryData(const MarkupNode &Node);
101fcaf7f86SDimitry Andric 
10281ad6265SDimitry Andric   bool trySGR(const MarkupNode &Node);
10381ad6265SDimitry Andric 
10481ad6265SDimitry Andric   void highlight();
105fcaf7f86SDimitry Andric   void highlightValue();
10681ad6265SDimitry Andric   void restoreColor();
10781ad6265SDimitry Andric   void resetColor();
10881ad6265SDimitry Andric 
109a4a491e2SDimitry Andric   void printRawElement(const MarkupNode &Element);
110a4a491e2SDimitry Andric   void printValue(Twine Value);
111a4a491e2SDimitry Andric 
112bdd1243dSDimitry Andric   std::optional<Module> parseModule(const MarkupNode &Element) const;
113bdd1243dSDimitry Andric   std::optional<MMap> parseMMap(const MarkupNode &Element) const;
114fcaf7f86SDimitry Andric 
115bdd1243dSDimitry Andric   std::optional<uint64_t> parseAddr(StringRef Str) const;
116bdd1243dSDimitry Andric   std::optional<uint64_t> parseModuleID(StringRef Str) const;
117bdd1243dSDimitry Andric   std::optional<uint64_t> parseSize(StringRef Str) const;
11806c3fb27SDimitry Andric   object::BuildID parseBuildID(StringRef Str) const;
119bdd1243dSDimitry Andric   std::optional<std::string> parseMode(StringRef Str) const;
120bdd1243dSDimitry Andric   std::optional<PCType> parsePCType(StringRef Str) const;
121bdd1243dSDimitry Andric   std::optional<uint64_t> parseFrameNumber(StringRef Str) const;
122fcaf7f86SDimitry Andric 
12381ad6265SDimitry Andric   bool checkTag(const MarkupNode &Node) const;
124fcaf7f86SDimitry Andric   bool checkNumFields(const MarkupNode &Element, size_t Size) const;
125fcaf7f86SDimitry Andric   bool checkNumFieldsAtLeast(const MarkupNode &Element, size_t Size) const;
12606c3fb27SDimitry Andric   void warnNumFieldsAtMost(const MarkupNode &Element, size_t Size) const;
12781ad6265SDimitry Andric 
12881ad6265SDimitry Andric   void reportTypeError(StringRef Str, StringRef TypeName) const;
12981ad6265SDimitry Andric   void reportLocation(StringRef::iterator Loc) const;
13081ad6265SDimitry Andric 
131a4a491e2SDimitry Andric   const MMap *getOverlappingMMap(const MMap &Map) const;
132a4a491e2SDimitry Andric   const MMap *getContainingMMap(uint64_t Addr) const;
133a4a491e2SDimitry Andric 
134a4a491e2SDimitry Andric   uint64_t adjustAddr(uint64_t Addr, PCType Type) const;
135fcaf7f86SDimitry Andric 
136fcaf7f86SDimitry Andric   StringRef lineEnding() const;
137fcaf7f86SDimitry Andric 
13881ad6265SDimitry Andric   raw_ostream &OS;
139a4a491e2SDimitry Andric   LLVMSymbolizer &Symbolizer;
14081ad6265SDimitry Andric   const bool ColorsEnabled;
14181ad6265SDimitry Andric 
142fcaf7f86SDimitry Andric   MarkupParser Parser;
143fcaf7f86SDimitry Andric 
144fcaf7f86SDimitry Andric   // Current line being filtered.
145*5f757f3fSDimitry Andric   std::string Line;
14681ad6265SDimitry Andric 
147fcaf7f86SDimitry Andric   // A module info line currently being built. This incorporates as much mmap
148fcaf7f86SDimitry Andric   // information as possible before being emitted.
149bdd1243dSDimitry Andric   std::optional<ModuleInfoLine> MIL;
150fcaf7f86SDimitry Andric 
151fcaf7f86SDimitry Andric   // SGR state.
152bdd1243dSDimitry Andric   std::optional<raw_ostream::Colors> Color;
15381ad6265SDimitry Andric   bool Bold = false;
154fcaf7f86SDimitry Andric 
155fcaf7f86SDimitry Andric   // Map from Module ID to Module.
156fcaf7f86SDimitry Andric   DenseMap<uint64_t, std::unique_ptr<Module>> Modules;
157fcaf7f86SDimitry Andric 
158fcaf7f86SDimitry Andric   // Ordered map from starting address to mmap.
159fcaf7f86SDimitry Andric   std::map<uint64_t, MMap> MMaps;
16081ad6265SDimitry Andric };
16181ad6265SDimitry Andric 
16281ad6265SDimitry Andric } // end namespace symbolize
16381ad6265SDimitry Andric } // end namespace llvm
16481ad6265SDimitry Andric 
16581ad6265SDimitry Andric #endif // LLVM_DEBUGINFO_SYMBOLIZE_MARKUPFILTER_H
166