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
23namespace 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
31class RecognizedStackFrame
32    : public std::enable_shared_from_this<RecognizedStackFrame> {
33public:
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
45protected:
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
56class StackFrameRecognizer
57    : public std::enable_shared_from_this<StackFrameRecognizer> {
58public:
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
76class 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
81public:
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
95private:
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.
102class StackFrameRecognizerManager {
103public:
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
126private:
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
147class 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