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 25 namespace llvm { 26 namespace symbolize { 27 28 class LLVMSymbolizer; 29 30 /// Filter to convert parsed log symbolizer markup elements into human-readable 31 /// text. 32 class MarkupFilter { 33 public: 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(StringRef Line); 43 44 /// Records that the input stream has ended and writes any deferred output. 45 void finish(); 46 47 private: 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 StringRef 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