xref: /llvm-project/lldb/include/lldb/Target/StackFrameRecognizer.h (revision b852fb1ec5fa15f0b913cc4988cbd09239b19904)
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