15ffd83dbSDimitry Andric //===-- StackFrameRecognizer.cpp ------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
9*af732203SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h"
100b57cec5SDimitry Andric #include "lldb/Core/Module.h"
110b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
120b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h"
130b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
140b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h"
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric using namespace lldb;
170b57cec5SDimitry Andric using namespace lldb_private;
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric class ScriptedRecognizedStackFrame : public RecognizedStackFrame {
200b57cec5SDimitry Andric public:
ScriptedRecognizedStackFrame(ValueObjectListSP args)210b57cec5SDimitry Andric ScriptedRecognizedStackFrame(ValueObjectListSP args) {
220b57cec5SDimitry Andric m_arguments = args;
230b57cec5SDimitry Andric }
240b57cec5SDimitry Andric };
250b57cec5SDimitry Andric
ScriptedStackFrameRecognizer(ScriptInterpreter * interpreter,const char * pclass)260b57cec5SDimitry Andric ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
270b57cec5SDimitry Andric ScriptInterpreter *interpreter, const char *pclass)
280b57cec5SDimitry Andric : m_interpreter(interpreter), m_python_class(pclass) {
290b57cec5SDimitry Andric m_python_object_sp =
300b57cec5SDimitry Andric m_interpreter->CreateFrameRecognizer(m_python_class.c_str());
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric RecognizedStackFrameSP
RecognizeFrame(lldb::StackFrameSP frame)340b57cec5SDimitry Andric ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
350b57cec5SDimitry Andric if (!m_python_object_sp || !m_interpreter)
360b57cec5SDimitry Andric return RecognizedStackFrameSP();
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric ValueObjectListSP args =
390b57cec5SDimitry Andric m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
400b57cec5SDimitry Andric auto args_synthesized = ValueObjectListSP(new ValueObjectList());
41480093f4SDimitry Andric for (const auto &o : args->GetObjects()) {
420b57cec5SDimitry Andric args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(
430b57cec5SDimitry Andric *o, eValueTypeVariableArgument));
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric return RecognizedStackFrameSP(
470b57cec5SDimitry Andric new ScriptedRecognizedStackFrame(args_synthesized));
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric
AddRecognizer(StackFrameRecognizerSP recognizer,ConstString module,llvm::ArrayRef<ConstString> symbols,bool first_instruction_only)50*af732203SDimitry Andric void StackFrameRecognizerManager::AddRecognizer(
51*af732203SDimitry Andric StackFrameRecognizerSP recognizer, ConstString module,
52*af732203SDimitry Andric llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
53*af732203SDimitry Andric m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
54*af732203SDimitry Andric module, RegularExpressionSP(), symbols,
555ffd83dbSDimitry Andric RegularExpressionSP(), first_instruction_only});
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
AddRecognizer(StackFrameRecognizerSP recognizer,RegularExpressionSP module,RegularExpressionSP symbol,bool first_instruction_only)58*af732203SDimitry Andric void StackFrameRecognizerManager::AddRecognizer(
59*af732203SDimitry Andric StackFrameRecognizerSP recognizer, RegularExpressionSP module,
60*af732203SDimitry Andric RegularExpressionSP symbol, bool first_instruction_only) {
61*af732203SDimitry Andric m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
62*af732203SDimitry Andric ConstString(), module, std::vector<ConstString>(),
63*af732203SDimitry Andric symbol, first_instruction_only});
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric
ForEach(const std::function<void (uint32_t,std::string,std::string,llvm::ArrayRef<ConstString>,bool)> & callback)66*af732203SDimitry Andric void StackFrameRecognizerManager::ForEach(
67*af732203SDimitry Andric const std::function<void(uint32_t, std::string, std::string,
68*af732203SDimitry Andric llvm::ArrayRef<ConstString>, bool)> &callback) {
690b57cec5SDimitry Andric for (auto entry : m_recognizers) {
700b57cec5SDimitry Andric if (entry.is_regexp) {
715ffd83dbSDimitry Andric std::string module_name;
725ffd83dbSDimitry Andric std::string symbol_name;
735ffd83dbSDimitry Andric
745ffd83dbSDimitry Andric if (entry.module_regexp)
755ffd83dbSDimitry Andric module_name = entry.module_regexp->GetText().str();
765ffd83dbSDimitry Andric if (entry.symbol_regexp)
775ffd83dbSDimitry Andric symbol_name = entry.symbol_regexp->GetText().str();
785ffd83dbSDimitry Andric
795ffd83dbSDimitry Andric callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
805ffd83dbSDimitry Andric llvm::makeArrayRef(ConstString(symbol_name)), true);
815ffd83dbSDimitry Andric
820b57cec5SDimitry Andric } else {
835ffd83dbSDimitry Andric callback(entry.recognizer_id, entry.recognizer->GetName(),
845ffd83dbSDimitry Andric entry.module.GetCString(), entry.symbols, false);
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
RemoveRecognizerWithID(uint32_t recognizer_id)89*af732203SDimitry Andric bool StackFrameRecognizerManager::RemoveRecognizerWithID(
90*af732203SDimitry Andric uint32_t recognizer_id) {
91*af732203SDimitry Andric if (recognizer_id >= m_recognizers.size())
92*af732203SDimitry Andric return false;
93*af732203SDimitry Andric auto found =
94*af732203SDimitry Andric llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) {
95*af732203SDimitry Andric return e.recognizer_id == recognizer_id;
96*af732203SDimitry Andric });
97*af732203SDimitry Andric if (found == m_recognizers.end())
98*af732203SDimitry Andric return false;
99*af732203SDimitry Andric m_recognizers.erase(found);
1000b57cec5SDimitry Andric return true;
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
RemoveAllRecognizers()103*af732203SDimitry Andric void StackFrameRecognizerManager::RemoveAllRecognizers() {
1040b57cec5SDimitry Andric m_recognizers.clear();
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric
107*af732203SDimitry Andric StackFrameRecognizerSP
GetRecognizerForFrame(StackFrameSP frame)108*af732203SDimitry Andric StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
1095ffd83dbSDimitry Andric const SymbolContext &symctx = frame->GetSymbolContext(
1105ffd83dbSDimitry Andric eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
1110b57cec5SDimitry Andric ConstString function_name = symctx.GetFunctionName();
1120b57cec5SDimitry Andric ModuleSP module_sp = symctx.module_sp;
113*af732203SDimitry Andric if (!module_sp)
114*af732203SDimitry Andric return StackFrameRecognizerSP();
1150b57cec5SDimitry Andric ConstString module_name = module_sp->GetFileSpec().GetFilename();
1160b57cec5SDimitry Andric Symbol *symbol = symctx.symbol;
117*af732203SDimitry Andric if (!symbol)
118*af732203SDimitry Andric return StackFrameRecognizerSP();
1190b57cec5SDimitry Andric Address start_addr = symbol->GetAddress();
1200b57cec5SDimitry Andric Address current_addr = frame->GetFrameCodeAddress();
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric for (auto entry : m_recognizers) {
1230b57cec5SDimitry Andric if (entry.module)
124*af732203SDimitry Andric if (entry.module != module_name)
125*af732203SDimitry Andric continue;
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric if (entry.module_regexp)
128*af732203SDimitry Andric if (!entry.module_regexp->Execute(module_name.GetStringRef()))
129*af732203SDimitry Andric continue;
1300b57cec5SDimitry Andric
1315ffd83dbSDimitry Andric if (!entry.symbols.empty())
1325ffd83dbSDimitry Andric if (!llvm::is_contained(entry.symbols, function_name))
1335ffd83dbSDimitry Andric continue;
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric if (entry.symbol_regexp)
1360b57cec5SDimitry Andric if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
1370b57cec5SDimitry Andric continue;
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric if (entry.first_instruction_only)
140*af732203SDimitry Andric if (start_addr != current_addr)
141*af732203SDimitry Andric continue;
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric return entry.recognizer;
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric return StackFrameRecognizerSP();
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric
148*af732203SDimitry Andric RecognizedStackFrameSP
RecognizeFrame(StackFrameSP frame)149*af732203SDimitry Andric StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) {
1500b57cec5SDimitry Andric auto recognizer = GetRecognizerForFrame(frame);
151*af732203SDimitry Andric if (!recognizer)
152*af732203SDimitry Andric return RecognizedStackFrameSP();
1530b57cec5SDimitry Andric return recognizer->RecognizeFrame(frame);
1540b57cec5SDimitry Andric }
155