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