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