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