xref: /openbsd-src/gnu/llvm/lldb/source/Target/StackFrameRecognizer.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- StackFrameRecognizer.cpp ------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9be691f3bSpatrick #include "lldb/Target/StackFrameRecognizer.h"
10061da546Spatrick #include "lldb/Core/Module.h"
11061da546Spatrick #include "lldb/Interpreter/ScriptInterpreter.h"
12061da546Spatrick #include "lldb/Symbol/Symbol.h"
13061da546Spatrick #include "lldb/Target/StackFrame.h"
14061da546Spatrick #include "lldb/Utility/RegularExpression.h"
15061da546Spatrick 
16061da546Spatrick using namespace lldb;
17061da546Spatrick using namespace lldb_private;
18061da546Spatrick 
19061da546Spatrick class ScriptedRecognizedStackFrame : public RecognizedStackFrame {
20061da546Spatrick public:
ScriptedRecognizedStackFrame(ValueObjectListSP args)21061da546Spatrick   ScriptedRecognizedStackFrame(ValueObjectListSP args) {
22061da546Spatrick     m_arguments = args;
23061da546Spatrick   }
24061da546Spatrick };
25061da546Spatrick 
ScriptedStackFrameRecognizer(ScriptInterpreter * interpreter,const char * pclass)26061da546Spatrick ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
27061da546Spatrick     ScriptInterpreter *interpreter, const char *pclass)
28061da546Spatrick     : m_interpreter(interpreter), m_python_class(pclass) {
29061da546Spatrick   m_python_object_sp =
30061da546Spatrick       m_interpreter->CreateFrameRecognizer(m_python_class.c_str());
31061da546Spatrick }
32061da546Spatrick 
33061da546Spatrick RecognizedStackFrameSP
RecognizeFrame(lldb::StackFrameSP frame)34061da546Spatrick ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
35061da546Spatrick   if (!m_python_object_sp || !m_interpreter)
36061da546Spatrick     return RecognizedStackFrameSP();
37061da546Spatrick 
38061da546Spatrick   ValueObjectListSP args =
39061da546Spatrick       m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
40061da546Spatrick   auto args_synthesized = ValueObjectListSP(new ValueObjectList());
41061da546Spatrick   for (const auto &o : args->GetObjects()) {
42061da546Spatrick     args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(
43061da546Spatrick         *o, eValueTypeVariableArgument));
44061da546Spatrick   }
45061da546Spatrick 
46061da546Spatrick   return RecognizedStackFrameSP(
47061da546Spatrick       new ScriptedRecognizedStackFrame(args_synthesized));
48061da546Spatrick }
49061da546Spatrick 
AddRecognizer(StackFrameRecognizerSP recognizer,ConstString module,llvm::ArrayRef<ConstString> symbols,bool first_instruction_only)50be691f3bSpatrick void StackFrameRecognizerManager::AddRecognizer(
51be691f3bSpatrick     StackFrameRecognizerSP recognizer, ConstString module,
52be691f3bSpatrick     llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
53be691f3bSpatrick   m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
54be691f3bSpatrick                             module, RegularExpressionSP(), symbols,
55dda28197Spatrick                             RegularExpressionSP(), first_instruction_only});
56061da546Spatrick }
57061da546Spatrick 
AddRecognizer(StackFrameRecognizerSP recognizer,RegularExpressionSP module,RegularExpressionSP symbol,bool first_instruction_only)58be691f3bSpatrick void StackFrameRecognizerManager::AddRecognizer(
59be691f3bSpatrick     StackFrameRecognizerSP recognizer, RegularExpressionSP module,
60be691f3bSpatrick     RegularExpressionSP symbol, bool first_instruction_only) {
61be691f3bSpatrick   m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
62be691f3bSpatrick                             ConstString(), module, std::vector<ConstString>(),
63be691f3bSpatrick                             symbol, first_instruction_only});
64061da546Spatrick }
65061da546Spatrick 
ForEach(const std::function<void (uint32_t,std::string,std::string,llvm::ArrayRef<ConstString>,bool)> & callback)66be691f3bSpatrick void StackFrameRecognizerManager::ForEach(
67be691f3bSpatrick     const std::function<void(uint32_t, std::string, std::string,
68be691f3bSpatrick                              llvm::ArrayRef<ConstString>, bool)> &callback) {
69061da546Spatrick   for (auto entry : m_recognizers) {
70061da546Spatrick     if (entry.is_regexp) {
71dda28197Spatrick       std::string module_name;
72dda28197Spatrick       std::string symbol_name;
73dda28197Spatrick 
74dda28197Spatrick       if (entry.module_regexp)
75dda28197Spatrick         module_name = entry.module_regexp->GetText().str();
76dda28197Spatrick       if (entry.symbol_regexp)
77dda28197Spatrick         symbol_name = entry.symbol_regexp->GetText().str();
78dda28197Spatrick 
79dda28197Spatrick       callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
80*f6aab3d8Srobert                llvm::ArrayRef(ConstString(symbol_name)), true);
81dda28197Spatrick 
82061da546Spatrick     } else {
83dda28197Spatrick       callback(entry.recognizer_id, entry.recognizer->GetName(),
84dda28197Spatrick                entry.module.GetCString(), entry.symbols, false);
85061da546Spatrick     }
86061da546Spatrick   }
87061da546Spatrick }
88061da546Spatrick 
RemoveRecognizerWithID(uint32_t recognizer_id)89be691f3bSpatrick bool StackFrameRecognizerManager::RemoveRecognizerWithID(
90be691f3bSpatrick     uint32_t recognizer_id) {
91be691f3bSpatrick   if (recognizer_id >= m_recognizers.size())
92be691f3bSpatrick     return false;
93be691f3bSpatrick   auto found =
94be691f3bSpatrick       llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) {
95be691f3bSpatrick         return e.recognizer_id == recognizer_id;
96be691f3bSpatrick       });
97be691f3bSpatrick   if (found == m_recognizers.end())
98be691f3bSpatrick     return false;
99be691f3bSpatrick   m_recognizers.erase(found);
100061da546Spatrick   return true;
101061da546Spatrick }
102061da546Spatrick 
RemoveAllRecognizers()103be691f3bSpatrick void StackFrameRecognizerManager::RemoveAllRecognizers() {
104061da546Spatrick   m_recognizers.clear();
105061da546Spatrick }
106061da546Spatrick 
107be691f3bSpatrick StackFrameRecognizerSP
GetRecognizerForFrame(StackFrameSP frame)108be691f3bSpatrick StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
109dda28197Spatrick   const SymbolContext &symctx = frame->GetSymbolContext(
110dda28197Spatrick       eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
111061da546Spatrick   ConstString function_name = symctx.GetFunctionName();
112061da546Spatrick   ModuleSP module_sp = symctx.module_sp;
113be691f3bSpatrick   if (!module_sp)
114be691f3bSpatrick     return StackFrameRecognizerSP();
115061da546Spatrick   ConstString module_name = module_sp->GetFileSpec().GetFilename();
116061da546Spatrick   Symbol *symbol = symctx.symbol;
117be691f3bSpatrick   if (!symbol)
118be691f3bSpatrick     return StackFrameRecognizerSP();
119061da546Spatrick   Address start_addr = symbol->GetAddress();
120061da546Spatrick   Address current_addr = frame->GetFrameCodeAddress();
121061da546Spatrick 
122061da546Spatrick   for (auto entry : m_recognizers) {
123061da546Spatrick     if (entry.module)
124be691f3bSpatrick       if (entry.module != module_name)
125be691f3bSpatrick         continue;
126061da546Spatrick 
127061da546Spatrick     if (entry.module_regexp)
128be691f3bSpatrick       if (!entry.module_regexp->Execute(module_name.GetStringRef()))
129be691f3bSpatrick         continue;
130061da546Spatrick 
131dda28197Spatrick     if (!entry.symbols.empty())
132dda28197Spatrick       if (!llvm::is_contained(entry.symbols, function_name))
133dda28197Spatrick         continue;
134061da546Spatrick 
135061da546Spatrick     if (entry.symbol_regexp)
136061da546Spatrick       if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
137061da546Spatrick         continue;
138061da546Spatrick 
139061da546Spatrick     if (entry.first_instruction_only)
140be691f3bSpatrick       if (start_addr != current_addr)
141be691f3bSpatrick         continue;
142061da546Spatrick 
143061da546Spatrick     return entry.recognizer;
144061da546Spatrick   }
145061da546Spatrick   return StackFrameRecognizerSP();
146061da546Spatrick }
147061da546Spatrick 
148be691f3bSpatrick RecognizedStackFrameSP
RecognizeFrame(StackFrameSP frame)149be691f3bSpatrick StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) {
150061da546Spatrick   auto recognizer = GetRecognizerForFrame(frame);
151be691f3bSpatrick   if (!recognizer)
152be691f3bSpatrick     return RecognizedStackFrameSP();
153061da546Spatrick   return recognizer->RecognizeFrame(frame);
154061da546Spatrick }
155