1 //===-- StackFrameRecognizer.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 #ifndef LLDB_TARGET_STACKFRAMERECOGNIZER_H 10 #define LLDB_TARGET_STACKFRAMERECOGNIZER_H 11 12 #include "lldb/Symbol/VariableList.h" 13 #include "lldb/Target/StopInfo.h" 14 #include "lldb/Utility/StructuredData.h" 15 #include "lldb/ValueObject/ValueObject.h" 16 #include "lldb/ValueObject/ValueObjectList.h" 17 #include "lldb/lldb-private-forward.h" 18 #include "lldb/lldb-public.h" 19 20 #include <cstdint> 21 #include <deque> 22 #include <optional> 23 #include <vector> 24 25 namespace lldb_private { 26 27 /// \class RecognizedStackFrame 28 /// 29 /// This class provides extra information about a stack frame that was 30 /// provided by a specific stack frame recognizer. Right now, this class only 31 /// holds recognized arguments (via GetRecognizedArguments). 32 class RecognizedStackFrame 33 : public std::enable_shared_from_this<RecognizedStackFrame> { 34 public: 35 virtual ~RecognizedStackFrame() = default; 36 37 virtual lldb::ValueObjectListSP GetRecognizedArguments() { 38 return m_arguments; 39 } 40 virtual lldb::ValueObjectSP GetExceptionObject() { 41 return lldb::ValueObjectSP(); 42 } 43 virtual lldb::StackFrameSP GetMostRelevantFrame() { return nullptr; } 44 45 std::string GetStopDescription() { return m_stop_desc; } 46 /// Controls whether this frame should be filtered out when 47 /// displaying backtraces, for example. 48 virtual bool ShouldHide() { return false; } 49 50 protected: 51 lldb::ValueObjectListSP m_arguments; 52 std::string m_stop_desc; 53 }; 54 55 /// \class StackFrameRecognizer 56 /// 57 /// A base class for frame recognizers. Subclasses (actual frame recognizers) 58 /// should implement RecognizeFrame to provide a RecognizedStackFrame for a 59 /// given stack frame. 60 class StackFrameRecognizer 61 : public std::enable_shared_from_this<StackFrameRecognizer> { 62 public: 63 virtual lldb::RecognizedStackFrameSP RecognizeFrame( 64 lldb::StackFrameSP frame) { 65 return lldb::RecognizedStackFrameSP(); 66 }; 67 virtual std::string GetName() { 68 return ""; 69 } 70 71 virtual ~StackFrameRecognizer() = default; 72 }; 73 74 /// \class ScriptedStackFrameRecognizer 75 /// 76 /// Python implementation for frame recognizers. An instance of this class 77 /// tracks a particular Python classobject, which will be asked to recognize 78 /// stack frames. 79 class ScriptedStackFrameRecognizer : public StackFrameRecognizer { 80 lldb_private::ScriptInterpreter *m_interpreter; 81 lldb_private::StructuredData::ObjectSP m_python_object_sp; 82 83 std::string m_python_class; 84 85 public: 86 ScriptedStackFrameRecognizer(lldb_private::ScriptInterpreter *interpreter, 87 const char *pclass); 88 ~ScriptedStackFrameRecognizer() override = default; 89 90 std::string GetName() override { 91 return GetPythonClassName(); 92 } 93 94 const char *GetPythonClassName() { return m_python_class.c_str(); } 95 96 lldb::RecognizedStackFrameSP RecognizeFrame( 97 lldb::StackFrameSP frame) override; 98 99 private: 100 ScriptedStackFrameRecognizer(const ScriptedStackFrameRecognizer &) = delete; 101 const ScriptedStackFrameRecognizer & 102 operator=(const ScriptedStackFrameRecognizer &) = delete; 103 }; 104 105 /// Class that provides a registry of known stack frame recognizers. 106 class StackFrameRecognizerManager { 107 public: 108 /// Add a new recognizer that triggers on a given symbol name. 109 /// 110 /// \param symbol_mangling controls whether the symbol name should be 111 /// compared to the mangled or demangled name. 112 void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, 113 ConstString module, llvm::ArrayRef<ConstString> symbols, 114 Mangled::NamePreference symbol_mangling, 115 bool first_instruction_only = true); 116 117 /// Add a new recognizer that triggers on a symbol regex. 118 /// 119 /// \param symbol_mangling controls whether the regex should apply 120 /// to the mangled or demangled name. 121 void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, 122 lldb::RegularExpressionSP module, 123 lldb::RegularExpressionSP symbol, 124 Mangled::NamePreference symbol_mangling, 125 bool first_instruction_only = true); 126 127 void 128 ForEach(std::function<void(uint32_t recognizer_id, bool enabled, 129 std::string recognizer_name, std::string module, 130 llvm::ArrayRef<ConstString> symbols, 131 Mangled::NamePreference name_preference, 132 bool regexp)> const &callback); 133 134 bool SetEnabledForID(uint32_t recognizer_id, bool enabled); 135 bool RemoveRecognizerWithID(uint32_t recognizer_id); 136 137 void RemoveAllRecognizers(); 138 139 lldb::StackFrameRecognizerSP GetRecognizerForFrame(lldb::StackFrameSP frame); 140 141 lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame); 142 /// Returns a number that changes whenever the list of recognizers 143 /// has been modified. 144 uint16_t GetGeneration() const { return m_generation; } 145 146 private: 147 /// Increase the generation counter. 148 void BumpGeneration(); 149 150 struct RegisteredEntry { 151 uint32_t recognizer_id; 152 lldb::StackFrameRecognizerSP recognizer; 153 bool is_regexp; 154 ConstString module; 155 lldb::RegularExpressionSP module_regexp; 156 std::vector<ConstString> symbols; 157 lldb::RegularExpressionSP symbol_regexp; 158 Mangled::NamePreference symbol_mangling; 159 bool first_instruction_only; 160 bool enabled; 161 }; 162 163 std::deque<RegisteredEntry> m_recognizers; 164 uint16_t m_generation = 0; 165 }; 166 167 /// \class ValueObjectRecognizerSynthesizedValue 168 /// 169 /// ValueObject subclass that presents the passed ValueObject as a recognized 170 /// value with the specified ValueType. Frame recognizers should return 171 /// instances of this class as the returned objects in GetRecognizedArguments(). 172 class ValueObjectRecognizerSynthesizedValue : public ValueObject { 173 public: 174 static lldb::ValueObjectSP Create(ValueObject &parent, lldb::ValueType type) { 175 return (new ValueObjectRecognizerSynthesizedValue(parent, type))->GetSP(); 176 } 177 ValueObjectRecognizerSynthesizedValue(ValueObject &parent, 178 lldb::ValueType type) 179 : ValueObject(parent), m_type(type) { 180 SetName(parent.GetName()); 181 } 182 183 std::optional<uint64_t> GetByteSize() override { 184 return m_parent->GetByteSize(); 185 } 186 lldb::ValueType GetValueType() const override { return m_type; } 187 bool UpdateValue() override { 188 if (!m_parent->UpdateValueIfNeeded()) return false; 189 m_value = m_parent->GetValue(); 190 return true; 191 } 192 llvm::Expected<uint32_t> 193 CalculateNumChildren(uint32_t max = UINT32_MAX) override { 194 return m_parent->GetNumChildren(max); 195 } 196 CompilerType GetCompilerTypeImpl() override { 197 return m_parent->GetCompilerType(); 198 } 199 bool IsSynthetic() override { return true; } 200 201 private: 202 lldb::ValueType m_type; 203 }; 204 205 } // namespace lldb_private 206 207 #endif // LLDB_TARGET_STACKFRAMERECOGNIZER_H 208