StackFrameRecognizer.cpp revision 360784
1//===-- StackFrameRecognizer.cpp --------------------------------*- 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#include <vector>
10#include "lldb/Core/Module.h"
11#include "lldb/Interpreter/ScriptInterpreter.h"
12#include "lldb/Symbol/Symbol.h"
13#include "lldb/Target/StackFrame.h"
14#include "lldb/Target/StackFrameRecognizer.h"
15#include "lldb/Utility/RegularExpression.h"
16
17using namespace lldb;
18using namespace lldb_private;
19
20class ScriptedRecognizedStackFrame : public RecognizedStackFrame {
21public:
22  ScriptedRecognizedStackFrame(ValueObjectListSP args) {
23    m_arguments = args;
24  }
25};
26
27ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
28    ScriptInterpreter *interpreter, const char *pclass)
29    : m_interpreter(interpreter), m_python_class(pclass) {
30  m_python_object_sp =
31      m_interpreter->CreateFrameRecognizer(m_python_class.c_str());
32}
33
34RecognizedStackFrameSP
35ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
36  if (!m_python_object_sp || !m_interpreter)
37    return RecognizedStackFrameSP();
38
39  ValueObjectListSP args =
40      m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
41  auto args_synthesized = ValueObjectListSP(new ValueObjectList());
42  for (const auto &o : args->GetObjects()) {
43    args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(
44        *o, eValueTypeVariableArgument));
45  }
46
47  return RecognizedStackFrameSP(
48      new ScriptedRecognizedStackFrame(args_synthesized));
49}
50
51class StackFrameRecognizerManagerImpl {
52public:
53  void AddRecognizer(StackFrameRecognizerSP recognizer,
54                     ConstString module, ConstString symbol,
55                     bool first_instruction_only) {
56    m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, false, module, RegularExpressionSP(),
57                              symbol, RegularExpressionSP(),
58                              first_instruction_only});
59  }
60
61  void AddRecognizer(StackFrameRecognizerSP recognizer,
62                     RegularExpressionSP module, RegularExpressionSP symbol,
63                     bool first_instruction_only) {
64    m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, true, ConstString(), module,
65                              ConstString(), symbol, first_instruction_only});
66  }
67
68  void ForEach(
69      std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module,
70                         std::string symbol, bool regexp)> const &callback) {
71    for (auto entry : m_recognizers) {
72      if (entry.is_regexp) {
73        callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module_regexp->GetText(),
74                 entry.symbol_regexp->GetText(), true);
75      } else {
76        callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module.GetCString(),
77                 entry.symbol.GetCString(), false);
78      }
79    }
80  }
81
82  bool RemoveRecognizerWithID(uint32_t recognizer_id) {
83    if (recognizer_id >= m_recognizers.size()) return false;
84    if (m_recognizers[recognizer_id].deleted) return false;
85    m_recognizers[recognizer_id].deleted = true;
86    return true;
87  }
88
89  void RemoveAllRecognizers() {
90    m_recognizers.clear();
91  }
92
93  StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) {
94    const SymbolContext &symctx =
95        frame->GetSymbolContext(eSymbolContextModule | eSymbolContextFunction);
96    ConstString function_name = symctx.GetFunctionName();
97    ModuleSP module_sp = symctx.module_sp;
98    if (!module_sp) return StackFrameRecognizerSP();
99    ConstString module_name = module_sp->GetFileSpec().GetFilename();
100    Symbol *symbol = symctx.symbol;
101    if (!symbol) return StackFrameRecognizerSP();
102    Address start_addr = symbol->GetAddress();
103    Address current_addr = frame->GetFrameCodeAddress();
104
105    for (auto entry : m_recognizers) {
106      if (entry.deleted) continue;
107      if (entry.module)
108        if (entry.module != module_name) continue;
109
110      if (entry.module_regexp)
111        if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue;
112
113      if (entry.symbol)
114        if (entry.symbol != function_name) continue;
115
116      if (entry.symbol_regexp)
117        if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
118          continue;
119
120      if (entry.first_instruction_only)
121        if (start_addr != current_addr) continue;
122
123      return entry.recognizer;
124    }
125    return StackFrameRecognizerSP();
126  }
127
128  RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) {
129    auto recognizer = GetRecognizerForFrame(frame);
130    if (!recognizer) return RecognizedStackFrameSP();
131    return recognizer->RecognizeFrame(frame);
132  }
133
134 private:
135  struct RegisteredEntry {
136    uint32_t recognizer_id;
137    bool deleted;
138    StackFrameRecognizerSP recognizer;
139    bool is_regexp;
140    ConstString module;
141    RegularExpressionSP module_regexp;
142    ConstString symbol;
143    RegularExpressionSP symbol_regexp;
144    bool first_instruction_only;
145  };
146
147  std::deque<RegisteredEntry> m_recognizers;
148};
149
150StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() {
151  static StackFrameRecognizerManagerImpl instance =
152      StackFrameRecognizerManagerImpl();
153  return instance;
154}
155
156void StackFrameRecognizerManager::AddRecognizer(
157    StackFrameRecognizerSP recognizer, ConstString module,
158    ConstString symbol, bool first_instruction_only) {
159  GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
160                                                     first_instruction_only);
161}
162
163void StackFrameRecognizerManager::AddRecognizer(
164    StackFrameRecognizerSP recognizer, RegularExpressionSP module,
165    RegularExpressionSP symbol, bool first_instruction_only) {
166  GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
167                                                     first_instruction_only);
168}
169
170void StackFrameRecognizerManager::ForEach(
171    std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module,
172                       std::string symbol, bool regexp)> const &callback) {
173  GetStackFrameRecognizerManagerImpl().ForEach(callback);
174}
175
176void StackFrameRecognizerManager::RemoveAllRecognizers() {
177  GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers();
178}
179
180bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) {
181  return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id);
182}
183
184RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame(
185    StackFrameSP frame) {
186  return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame);
187}
188
189StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame(
190    lldb::StackFrameSP frame) {
191  return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame);
192}
193