180814287SRaphael Isemann //===-- StackFrameRecognizer.cpp ------------------------------------------===// 241ae8e74SKuba Mracek // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 641ae8e74SKuba Mracek // 741ae8e74SKuba Mracek //===----------------------------------------------------------------------===// 841ae8e74SKuba Mracek 9*1b7c9eaeSRaphael Isemann #include "lldb/Target/StackFrameRecognizer.h" 1041ae8e74SKuba Mracek #include "lldb/Core/Module.h" 1141ae8e74SKuba Mracek #include "lldb/Interpreter/ScriptInterpreter.h" 1241ae8e74SKuba Mracek #include "lldb/Symbol/Symbol.h" 1341ae8e74SKuba Mracek #include "lldb/Target/StackFrame.h" 1441ae8e74SKuba Mracek #include "lldb/Utility/RegularExpression.h" 1541ae8e74SKuba Mracek 1641ae8e74SKuba Mracek using namespace lldb; 1741ae8e74SKuba Mracek using namespace lldb_private; 1841ae8e74SKuba Mracek 1941ae8e74SKuba Mracek class ScriptedRecognizedStackFrame : public RecognizedStackFrame { 2041ae8e74SKuba Mracek public: 2141ae8e74SKuba Mracek ScriptedRecognizedStackFrame(ValueObjectListSP args) { 2241ae8e74SKuba Mracek m_arguments = args; 2341ae8e74SKuba Mracek } 2441ae8e74SKuba Mracek }; 2541ae8e74SKuba Mracek 2641ae8e74SKuba Mracek ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer( 2741ae8e74SKuba Mracek ScriptInterpreter *interpreter, const char *pclass) 2841ae8e74SKuba Mracek : m_interpreter(interpreter), m_python_class(pclass) { 2941ae8e74SKuba Mracek m_python_object_sp = 3041ae8e74SKuba Mracek m_interpreter->CreateFrameRecognizer(m_python_class.c_str()); 3141ae8e74SKuba Mracek } 3241ae8e74SKuba Mracek 3341ae8e74SKuba Mracek RecognizedStackFrameSP 3441ae8e74SKuba Mracek ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) { 3541ae8e74SKuba Mracek if (!m_python_object_sp || !m_interpreter) 3641ae8e74SKuba Mracek return RecognizedStackFrameSP(); 3741ae8e74SKuba Mracek 3841ae8e74SKuba Mracek ValueObjectListSP args = 3941ae8e74SKuba Mracek m_interpreter->GetRecognizedArguments(m_python_object_sp, frame); 4092369dcfSKuba Mracek auto args_synthesized = ValueObjectListSP(new ValueObjectList()); 418dc7b982SMark de Wever for (const auto &o : args->GetObjects()) { 4292369dcfSKuba Mracek args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create( 4392369dcfSKuba Mracek *o, eValueTypeVariableArgument)); 4492369dcfSKuba Mracek } 4541ae8e74SKuba Mracek 4692369dcfSKuba Mracek return RecognizedStackFrameSP( 4792369dcfSKuba Mracek new ScriptedRecognizedStackFrame(args_synthesized)); 4841ae8e74SKuba Mracek } 4941ae8e74SKuba Mracek 50*1b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::AddRecognizer( 51*1b7c9eaeSRaphael Isemann StackFrameRecognizerSP recognizer, ConstString module, 52*1b7c9eaeSRaphael Isemann llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) { 53cb0c4ee3SMed Ismail Bennani m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, 54db31e2e1SMed Ismail Bennani false, module, RegularExpressionSP(), symbols, 55db31e2e1SMed Ismail Bennani RegularExpressionSP(), first_instruction_only}); 5641ae8e74SKuba Mracek } 5741ae8e74SKuba Mracek 58*1b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::AddRecognizer( 59*1b7c9eaeSRaphael Isemann StackFrameRecognizerSP recognizer, RegularExpressionSP module, 60*1b7c9eaeSRaphael Isemann RegularExpressionSP symbol, bool first_instruction_only) { 61db31e2e1SMed Ismail Bennani m_recognizers.push_front( 62db31e2e1SMed Ismail Bennani {(uint32_t)m_recognizers.size(), false, recognizer, true, ConstString(), 63db31e2e1SMed Ismail Bennani module, std::vector<ConstString>(), symbol, first_instruction_only}); 6441ae8e74SKuba Mracek } 6541ae8e74SKuba Mracek 66*1b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::ForEach( 67*1b7c9eaeSRaphael Isemann const std::function<void(uint32_t, std::string, std::string, 68*1b7c9eaeSRaphael Isemann llvm::ArrayRef<ConstString>, bool)> &callback) { 6941ae8e74SKuba Mracek for (auto entry : m_recognizers) { 7041ae8e74SKuba Mracek if (entry.is_regexp) { 71047c4b03SMed Ismail Bennani std::string module_name; 72047c4b03SMed Ismail Bennani std::string symbol_name; 73047c4b03SMed Ismail Bennani 74047c4b03SMed Ismail Bennani if (entry.module_regexp) 75047c4b03SMed Ismail Bennani module_name = entry.module_regexp->GetText().str(); 76047c4b03SMed Ismail Bennani if (entry.symbol_regexp) 77047c4b03SMed Ismail Bennani symbol_name = entry.symbol_regexp->GetText().str(); 78047c4b03SMed Ismail Bennani 79047c4b03SMed Ismail Bennani callback(entry.recognizer_id, entry.recognizer->GetName(), module_name, 80db31e2e1SMed Ismail Bennani llvm::makeArrayRef(ConstString(symbol_name)), true); 81047c4b03SMed Ismail Bennani 8241ae8e74SKuba Mracek } else { 83cb0c4ee3SMed Ismail Bennani callback(entry.recognizer_id, entry.recognizer->GetName(), 84db31e2e1SMed Ismail Bennani entry.module.GetCString(), entry.symbols, false); 8541ae8e74SKuba Mracek } 8641ae8e74SKuba Mracek } 8741ae8e74SKuba Mracek } 8841ae8e74SKuba Mracek 89*1b7c9eaeSRaphael Isemann bool StackFrameRecognizerManager::RemoveRecognizerWithID( 90*1b7c9eaeSRaphael Isemann uint32_t recognizer_id) { 91*1b7c9eaeSRaphael Isemann if (recognizer_id >= m_recognizers.size()) 92*1b7c9eaeSRaphael Isemann return false; 93*1b7c9eaeSRaphael Isemann if (m_recognizers[recognizer_id].deleted) 94*1b7c9eaeSRaphael Isemann return false; 9541ae8e74SKuba Mracek m_recognizers[recognizer_id].deleted = true; 9641ae8e74SKuba Mracek return true; 9741ae8e74SKuba Mracek } 9841ae8e74SKuba Mracek 99*1b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::RemoveAllRecognizers() { 10041ae8e74SKuba Mracek m_recognizers.clear(); 10141ae8e74SKuba Mracek } 10241ae8e74SKuba Mracek 103*1b7c9eaeSRaphael Isemann StackFrameRecognizerSP 104*1b7c9eaeSRaphael Isemann StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) { 1057ebe9cc4SMed Ismail Bennani const SymbolContext &symctx = frame->GetSymbolContext( 1067ebe9cc4SMed Ismail Bennani eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol); 10741ae8e74SKuba Mracek ConstString function_name = symctx.GetFunctionName(); 10841ae8e74SKuba Mracek ModuleSP module_sp = symctx.module_sp; 109*1b7c9eaeSRaphael Isemann if (!module_sp) 110*1b7c9eaeSRaphael Isemann return StackFrameRecognizerSP(); 11141ae8e74SKuba Mracek ConstString module_name = module_sp->GetFileSpec().GetFilename(); 11241ae8e74SKuba Mracek Symbol *symbol = symctx.symbol; 113*1b7c9eaeSRaphael Isemann if (!symbol) 114*1b7c9eaeSRaphael Isemann return StackFrameRecognizerSP(); 11541ae8e74SKuba Mracek Address start_addr = symbol->GetAddress(); 11641ae8e74SKuba Mracek Address current_addr = frame->GetFrameCodeAddress(); 11741ae8e74SKuba Mracek 11841ae8e74SKuba Mracek for (auto entry : m_recognizers) { 119*1b7c9eaeSRaphael Isemann if (entry.deleted) 120*1b7c9eaeSRaphael Isemann continue; 12141ae8e74SKuba Mracek if (entry.module) 122*1b7c9eaeSRaphael Isemann if (entry.module != module_name) 123*1b7c9eaeSRaphael Isemann continue; 12441ae8e74SKuba Mracek 12541ae8e74SKuba Mracek if (entry.module_regexp) 126*1b7c9eaeSRaphael Isemann if (!entry.module_regexp->Execute(module_name.GetStringRef())) 127*1b7c9eaeSRaphael Isemann continue; 12841ae8e74SKuba Mracek 129db31e2e1SMed Ismail Bennani if (!entry.symbols.empty()) 130db31e2e1SMed Ismail Bennani if (!llvm::is_contained(entry.symbols, function_name)) 131cb0c4ee3SMed Ismail Bennani continue; 13241ae8e74SKuba Mracek 13341ae8e74SKuba Mracek if (entry.symbol_regexp) 13441ae8e74SKuba Mracek if (!entry.symbol_regexp->Execute(function_name.GetStringRef())) 13541ae8e74SKuba Mracek continue; 13641ae8e74SKuba Mracek 13741ae8e74SKuba Mracek if (entry.first_instruction_only) 138*1b7c9eaeSRaphael Isemann if (start_addr != current_addr) 139*1b7c9eaeSRaphael Isemann continue; 14041ae8e74SKuba Mracek 14141ae8e74SKuba Mracek return entry.recognizer; 14241ae8e74SKuba Mracek } 14341ae8e74SKuba Mracek return StackFrameRecognizerSP(); 14441ae8e74SKuba Mracek } 14541ae8e74SKuba Mracek 146*1b7c9eaeSRaphael Isemann RecognizedStackFrameSP 147*1b7c9eaeSRaphael Isemann StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) { 14841ae8e74SKuba Mracek auto recognizer = GetRecognizerForFrame(frame); 149*1b7c9eaeSRaphael Isemann if (!recognizer) 150*1b7c9eaeSRaphael Isemann return RecognizedStackFrameSP(); 15141ae8e74SKuba Mracek return recognizer->RecognizeFrame(frame); 15241ae8e74SKuba Mracek } 153