xref: /src/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1cfca06d7SDimitry Andric //===-- StackFrameRecognizer.cpp ------------------------------------------===//
294994d37SDimitry Andric //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
694994d37SDimitry Andric //
794994d37SDimitry Andric //===----------------------------------------------------------------------===//
894994d37SDimitry Andric 
9b60736ecSDimitry Andric #include "lldb/Target/StackFrameRecognizer.h"
1094994d37SDimitry Andric #include "lldb/Core/Module.h"
1194994d37SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
1294994d37SDimitry Andric #include "lldb/Symbol/Symbol.h"
1394994d37SDimitry Andric #include "lldb/Target/StackFrame.h"
1494994d37SDimitry Andric #include "lldb/Utility/RegularExpression.h"
1594994d37SDimitry Andric 
1694994d37SDimitry Andric using namespace lldb;
1794994d37SDimitry Andric using namespace lldb_private;
1894994d37SDimitry Andric 
1994994d37SDimitry Andric class ScriptedRecognizedStackFrame : public RecognizedStackFrame {
2094994d37SDimitry Andric public:
ScriptedRecognizedStackFrame(ValueObjectListSP args)2194994d37SDimitry Andric   ScriptedRecognizedStackFrame(ValueObjectListSP args) {
2294994d37SDimitry Andric     m_arguments = args;
2394994d37SDimitry Andric   }
2494994d37SDimitry Andric };
2594994d37SDimitry Andric 
ScriptedStackFrameRecognizer(ScriptInterpreter * interpreter,const char * pclass)2694994d37SDimitry Andric ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
2794994d37SDimitry Andric     ScriptInterpreter *interpreter, const char *pclass)
2894994d37SDimitry Andric     : m_interpreter(interpreter), m_python_class(pclass) {
2994994d37SDimitry Andric   m_python_object_sp =
3094994d37SDimitry Andric       m_interpreter->CreateFrameRecognizer(m_python_class.c_str());
3194994d37SDimitry Andric }
3294994d37SDimitry Andric 
3394994d37SDimitry Andric RecognizedStackFrameSP
RecognizeFrame(lldb::StackFrameSP frame)3494994d37SDimitry Andric ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
3594994d37SDimitry Andric   if (!m_python_object_sp || !m_interpreter)
3694994d37SDimitry Andric     return RecognizedStackFrameSP();
3794994d37SDimitry Andric 
3894994d37SDimitry Andric   ValueObjectListSP args =
3994994d37SDimitry Andric       m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
405f29bb8aSDimitry Andric   auto args_synthesized = ValueObjectListSP(new ValueObjectList());
41706b4fc4SDimitry Andric   for (const auto &o : args->GetObjects()) {
425f29bb8aSDimitry Andric     args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(
435f29bb8aSDimitry Andric         *o, eValueTypeVariableArgument));
4494994d37SDimitry Andric   }
4594994d37SDimitry Andric 
465f29bb8aSDimitry Andric   return RecognizedStackFrameSP(
475f29bb8aSDimitry Andric       new ScriptedRecognizedStackFrame(args_synthesized));
485f29bb8aSDimitry Andric }
4994994d37SDimitry Andric 
AddRecognizer(StackFrameRecognizerSP recognizer,ConstString module,llvm::ArrayRef<ConstString> symbols,bool first_instruction_only)50b60736ecSDimitry Andric void StackFrameRecognizerManager::AddRecognizer(
51b60736ecSDimitry Andric     StackFrameRecognizerSP recognizer, ConstString module,
52b60736ecSDimitry Andric     llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
53b60736ecSDimitry Andric   m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
54b60736ecSDimitry Andric                             module, RegularExpressionSP(), symbols,
55cfca06d7SDimitry Andric                             RegularExpressionSP(), first_instruction_only});
5694994d37SDimitry Andric }
5794994d37SDimitry Andric 
AddRecognizer(StackFrameRecognizerSP recognizer,RegularExpressionSP module,RegularExpressionSP symbol,bool first_instruction_only)58b60736ecSDimitry Andric void StackFrameRecognizerManager::AddRecognizer(
59b60736ecSDimitry Andric     StackFrameRecognizerSP recognizer, RegularExpressionSP module,
60b60736ecSDimitry Andric     RegularExpressionSP symbol, bool first_instruction_only) {
61b60736ecSDimitry Andric   m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
62b60736ecSDimitry Andric                             ConstString(), module, std::vector<ConstString>(),
63b60736ecSDimitry Andric                             symbol, first_instruction_only});
6494994d37SDimitry Andric }
6594994d37SDimitry Andric 
ForEach(const std::function<void (uint32_t,std::string,std::string,llvm::ArrayRef<ConstString>,bool)> & callback)66b60736ecSDimitry Andric void StackFrameRecognizerManager::ForEach(
67b60736ecSDimitry Andric     const std::function<void(uint32_t, std::string, std::string,
68b60736ecSDimitry Andric                              llvm::ArrayRef<ConstString>, bool)> &callback) {
6994994d37SDimitry Andric   for (auto entry : m_recognizers) {
7094994d37SDimitry Andric     if (entry.is_regexp) {
71cfca06d7SDimitry Andric       std::string module_name;
72cfca06d7SDimitry Andric       std::string symbol_name;
73cfca06d7SDimitry Andric 
74cfca06d7SDimitry Andric       if (entry.module_regexp)
75cfca06d7SDimitry Andric         module_name = entry.module_regexp->GetText().str();
76cfca06d7SDimitry Andric       if (entry.symbol_regexp)
77cfca06d7SDimitry Andric         symbol_name = entry.symbol_regexp->GetText().str();
78cfca06d7SDimitry Andric 
79cfca06d7SDimitry Andric       callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
80e3b55780SDimitry Andric                llvm::ArrayRef(ConstString(symbol_name)), true);
81cfca06d7SDimitry Andric 
8294994d37SDimitry Andric     } else {
83cfca06d7SDimitry Andric       callback(entry.recognizer_id, entry.recognizer->GetName(),
84cfca06d7SDimitry Andric                entry.module.GetCString(), entry.symbols, false);
8594994d37SDimitry Andric     }
8694994d37SDimitry Andric   }
8794994d37SDimitry Andric }
8894994d37SDimitry Andric 
RemoveRecognizerWithID(uint32_t recognizer_id)89b60736ecSDimitry Andric bool StackFrameRecognizerManager::RemoveRecognizerWithID(
90b60736ecSDimitry Andric     uint32_t recognizer_id) {
91b60736ecSDimitry Andric   if (recognizer_id >= m_recognizers.size())
92b60736ecSDimitry Andric     return false;
93b60736ecSDimitry Andric   auto found =
94b60736ecSDimitry Andric       llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) {
95b60736ecSDimitry Andric         return e.recognizer_id == recognizer_id;
96b60736ecSDimitry Andric       });
97b60736ecSDimitry Andric   if (found == m_recognizers.end())
98b60736ecSDimitry Andric     return false;
99b60736ecSDimitry Andric   m_recognizers.erase(found);
10094994d37SDimitry Andric   return true;
10194994d37SDimitry Andric }
10294994d37SDimitry Andric 
RemoveAllRecognizers()103b60736ecSDimitry Andric void StackFrameRecognizerManager::RemoveAllRecognizers() {
10494994d37SDimitry Andric   m_recognizers.clear();
10594994d37SDimitry Andric }
10694994d37SDimitry Andric 
107b60736ecSDimitry Andric StackFrameRecognizerSP
GetRecognizerForFrame(StackFrameSP frame)108b60736ecSDimitry Andric StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
109cfca06d7SDimitry Andric   const SymbolContext &symctx = frame->GetSymbolContext(
110cfca06d7SDimitry Andric       eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
11194994d37SDimitry Andric   ConstString function_name = symctx.GetFunctionName();
11294994d37SDimitry Andric   ModuleSP module_sp = symctx.module_sp;
113b60736ecSDimitry Andric   if (!module_sp)
114b60736ecSDimitry Andric     return StackFrameRecognizerSP();
11594994d37SDimitry Andric   ConstString module_name = module_sp->GetFileSpec().GetFilename();
11694994d37SDimitry Andric   Symbol *symbol = symctx.symbol;
117b60736ecSDimitry Andric   if (!symbol)
118b60736ecSDimitry Andric     return StackFrameRecognizerSP();
11994994d37SDimitry Andric   Address start_addr = symbol->GetAddress();
12094994d37SDimitry Andric   Address current_addr = frame->GetFrameCodeAddress();
12194994d37SDimitry Andric 
12294994d37SDimitry Andric   for (auto entry : m_recognizers) {
12394994d37SDimitry Andric     if (entry.module)
124b60736ecSDimitry Andric       if (entry.module != module_name)
125b60736ecSDimitry Andric         continue;
12694994d37SDimitry Andric 
12794994d37SDimitry Andric     if (entry.module_regexp)
128b60736ecSDimitry Andric       if (!entry.module_regexp->Execute(module_name.GetStringRef()))
129b60736ecSDimitry Andric         continue;
13094994d37SDimitry Andric 
131cfca06d7SDimitry Andric     if (!entry.symbols.empty())
132cfca06d7SDimitry Andric       if (!llvm::is_contained(entry.symbols, function_name))
133cfca06d7SDimitry Andric         continue;
13494994d37SDimitry Andric 
13594994d37SDimitry Andric     if (entry.symbol_regexp)
13694994d37SDimitry Andric       if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
13794994d37SDimitry Andric         continue;
13894994d37SDimitry Andric 
13994994d37SDimitry Andric     if (entry.first_instruction_only)
140b60736ecSDimitry Andric       if (start_addr != current_addr)
141b60736ecSDimitry Andric         continue;
14294994d37SDimitry Andric 
14394994d37SDimitry Andric     return entry.recognizer;
14494994d37SDimitry Andric   }
14594994d37SDimitry Andric   return StackFrameRecognizerSP();
14694994d37SDimitry Andric }
14794994d37SDimitry Andric 
148b60736ecSDimitry Andric RecognizedStackFrameSP
RecognizeFrame(StackFrameSP frame)149b60736ecSDimitry Andric StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) {
15094994d37SDimitry Andric   auto recognizer = GetRecognizerForFrame(frame);
151b60736ecSDimitry Andric   if (!recognizer)
152b60736ecSDimitry Andric     return RecognizedStackFrameSP();
15394994d37SDimitry Andric   return recognizer->RecognizeFrame(frame);
15494994d37SDimitry Andric }
155