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