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 941ae8e74SKuba Mracek #include <vector> 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/Target/StackFrameRecognizer.h" 1541ae8e74SKuba Mracek #include "lldb/Utility/RegularExpression.h" 1641ae8e74SKuba Mracek 1741ae8e74SKuba Mracek using namespace lldb; 1841ae8e74SKuba Mracek using namespace lldb_private; 1941ae8e74SKuba Mracek 2041ae8e74SKuba Mracek class ScriptedRecognizedStackFrame : public RecognizedStackFrame { 2141ae8e74SKuba Mracek public: 2241ae8e74SKuba Mracek ScriptedRecognizedStackFrame(ValueObjectListSP args) { 2341ae8e74SKuba Mracek m_arguments = args; 2441ae8e74SKuba Mracek } 2541ae8e74SKuba Mracek }; 2641ae8e74SKuba Mracek 2741ae8e74SKuba Mracek ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer( 2841ae8e74SKuba Mracek ScriptInterpreter *interpreter, const char *pclass) 2941ae8e74SKuba Mracek : m_interpreter(interpreter), m_python_class(pclass) { 3041ae8e74SKuba Mracek m_python_object_sp = 3141ae8e74SKuba Mracek m_interpreter->CreateFrameRecognizer(m_python_class.c_str()); 3241ae8e74SKuba Mracek } 3341ae8e74SKuba Mracek 3441ae8e74SKuba Mracek RecognizedStackFrameSP 3541ae8e74SKuba Mracek ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) { 3641ae8e74SKuba Mracek if (!m_python_object_sp || !m_interpreter) 3741ae8e74SKuba Mracek return RecognizedStackFrameSP(); 3841ae8e74SKuba Mracek 3941ae8e74SKuba Mracek ValueObjectListSP args = 4041ae8e74SKuba Mracek m_interpreter->GetRecognizedArguments(m_python_object_sp, frame); 4192369dcfSKuba Mracek auto args_synthesized = ValueObjectListSP(new ValueObjectList()); 428dc7b982SMark de Wever for (const auto &o : args->GetObjects()) { 4392369dcfSKuba Mracek args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create( 4492369dcfSKuba Mracek *o, eValueTypeVariableArgument)); 4592369dcfSKuba Mracek } 4641ae8e74SKuba Mracek 4792369dcfSKuba Mracek return RecognizedStackFrameSP( 4892369dcfSKuba Mracek new ScriptedRecognizedStackFrame(args_synthesized)); 4941ae8e74SKuba Mracek } 5041ae8e74SKuba Mracek 5141ae8e74SKuba Mracek class StackFrameRecognizerManagerImpl { 5241ae8e74SKuba Mracek public: 53*cb0c4ee3SMed Ismail Bennani void AddRecognizer(StackFrameRecognizerSP recognizer, ConstString module, 54*cb0c4ee3SMed Ismail Bennani ConstString symbol, ConstString alternate_symbol, 55e60bc53bSKuba Mracek bool first_instruction_only) { 56*cb0c4ee3SMed Ismail Bennani m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, 57*cb0c4ee3SMed Ismail Bennani false, module, RegularExpressionSP(), symbol, 58*cb0c4ee3SMed Ismail Bennani alternate_symbol, RegularExpressionSP(), 5941ae8e74SKuba Mracek first_instruction_only}); 6041ae8e74SKuba Mracek } 6141ae8e74SKuba Mracek 6241ae8e74SKuba Mracek void AddRecognizer(StackFrameRecognizerSP recognizer, 6341ae8e74SKuba Mracek RegularExpressionSP module, RegularExpressionSP symbol, 6441ae8e74SKuba Mracek bool first_instruction_only) { 65*cb0c4ee3SMed Ismail Bennani m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, 66*cb0c4ee3SMed Ismail Bennani true, ConstString(), module, ConstString(), 6741ae8e74SKuba Mracek ConstString(), symbol, first_instruction_only}); 6841ae8e74SKuba Mracek } 6941ae8e74SKuba Mracek 7041ae8e74SKuba Mracek void ForEach( 71*cb0c4ee3SMed Ismail Bennani std::function<void(uint32_t recognized_id, std::string recognizer_name, 72*cb0c4ee3SMed Ismail Bennani std::string module, std::string symbol, 73*cb0c4ee3SMed Ismail Bennani std::string alternate_symbol, bool regexp)> const 74*cb0c4ee3SMed Ismail Bennani &callback) { 7541ae8e74SKuba Mracek for (auto entry : m_recognizers) { 7641ae8e74SKuba Mracek if (entry.is_regexp) { 77047c4b03SMed Ismail Bennani std::string module_name; 78047c4b03SMed Ismail Bennani std::string symbol_name; 79047c4b03SMed Ismail Bennani 80047c4b03SMed Ismail Bennani if (entry.module_regexp) 81047c4b03SMed Ismail Bennani module_name = entry.module_regexp->GetText().str(); 82047c4b03SMed Ismail Bennani if (entry.symbol_regexp) 83047c4b03SMed Ismail Bennani symbol_name = entry.symbol_regexp->GetText().str(); 84047c4b03SMed Ismail Bennani 85047c4b03SMed Ismail Bennani callback(entry.recognizer_id, entry.recognizer->GetName(), module_name, 86*cb0c4ee3SMed Ismail Bennani symbol_name, {}, true); 87047c4b03SMed Ismail Bennani 8841ae8e74SKuba Mracek } else { 89*cb0c4ee3SMed Ismail Bennani std::string alternate_symbol; 90*cb0c4ee3SMed Ismail Bennani if (!entry.alternate_symbol.IsEmpty()) 91*cb0c4ee3SMed Ismail Bennani alternate_symbol.append(entry.alternate_symbol.GetCString()); 92*cb0c4ee3SMed Ismail Bennani 93*cb0c4ee3SMed Ismail Bennani callback(entry.recognizer_id, entry.recognizer->GetName(), 94*cb0c4ee3SMed Ismail Bennani entry.module.GetCString(), entry.symbol.GetCString(), 95*cb0c4ee3SMed Ismail Bennani alternate_symbol, false); 9641ae8e74SKuba Mracek } 9741ae8e74SKuba Mracek } 9841ae8e74SKuba Mracek } 9941ae8e74SKuba Mracek 10041ae8e74SKuba Mracek bool RemoveRecognizerWithID(uint32_t recognizer_id) { 10141ae8e74SKuba Mracek if (recognizer_id >= m_recognizers.size()) return false; 10241ae8e74SKuba Mracek if (m_recognizers[recognizer_id].deleted) return false; 10341ae8e74SKuba Mracek m_recognizers[recognizer_id].deleted = true; 10441ae8e74SKuba Mracek return true; 10541ae8e74SKuba Mracek } 10641ae8e74SKuba Mracek 10741ae8e74SKuba Mracek void RemoveAllRecognizers() { 10841ae8e74SKuba Mracek m_recognizers.clear(); 10941ae8e74SKuba Mracek } 11041ae8e74SKuba Mracek 11141ae8e74SKuba Mracek StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) { 1127ebe9cc4SMed Ismail Bennani const SymbolContext &symctx = frame->GetSymbolContext( 1137ebe9cc4SMed Ismail Bennani eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol); 11441ae8e74SKuba Mracek ConstString function_name = symctx.GetFunctionName(); 11541ae8e74SKuba Mracek ModuleSP module_sp = symctx.module_sp; 11641ae8e74SKuba Mracek if (!module_sp) return StackFrameRecognizerSP(); 11741ae8e74SKuba Mracek ConstString module_name = module_sp->GetFileSpec().GetFilename(); 11841ae8e74SKuba Mracek Symbol *symbol = symctx.symbol; 11941ae8e74SKuba Mracek if (!symbol) return StackFrameRecognizerSP(); 12041ae8e74SKuba Mracek Address start_addr = symbol->GetAddress(); 12141ae8e74SKuba Mracek Address current_addr = frame->GetFrameCodeAddress(); 12241ae8e74SKuba Mracek 12341ae8e74SKuba Mracek for (auto entry : m_recognizers) { 12441ae8e74SKuba Mracek if (entry.deleted) continue; 12541ae8e74SKuba Mracek if (entry.module) 12641ae8e74SKuba Mracek if (entry.module != module_name) continue; 12741ae8e74SKuba Mracek 12841ae8e74SKuba Mracek if (entry.module_regexp) 12941ae8e74SKuba Mracek if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue; 13041ae8e74SKuba Mracek 13141ae8e74SKuba Mracek if (entry.symbol) 132*cb0c4ee3SMed Ismail Bennani if (entry.symbol != function_name && 133*cb0c4ee3SMed Ismail Bennani (!entry.alternate_symbol || 134*cb0c4ee3SMed Ismail Bennani entry.alternate_symbol != function_name)) 135*cb0c4ee3SMed Ismail Bennani continue; 13641ae8e74SKuba Mracek 13741ae8e74SKuba Mracek if (entry.symbol_regexp) 13841ae8e74SKuba Mracek if (!entry.symbol_regexp->Execute(function_name.GetStringRef())) 13941ae8e74SKuba Mracek continue; 14041ae8e74SKuba Mracek 14141ae8e74SKuba Mracek if (entry.first_instruction_only) 14241ae8e74SKuba Mracek if (start_addr != current_addr) continue; 14341ae8e74SKuba Mracek 14441ae8e74SKuba Mracek return entry.recognizer; 14541ae8e74SKuba Mracek } 14641ae8e74SKuba Mracek return StackFrameRecognizerSP(); 14741ae8e74SKuba Mracek } 14841ae8e74SKuba Mracek 14941ae8e74SKuba Mracek RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) { 15041ae8e74SKuba Mracek auto recognizer = GetRecognizerForFrame(frame); 15141ae8e74SKuba Mracek if (!recognizer) return RecognizedStackFrameSP(); 15241ae8e74SKuba Mracek return recognizer->RecognizeFrame(frame); 15341ae8e74SKuba Mracek } 15441ae8e74SKuba Mracek 15541ae8e74SKuba Mracek private: 15641ae8e74SKuba Mracek struct RegisteredEntry { 15741ae8e74SKuba Mracek uint32_t recognizer_id; 15841ae8e74SKuba Mracek bool deleted; 15941ae8e74SKuba Mracek StackFrameRecognizerSP recognizer; 16041ae8e74SKuba Mracek bool is_regexp; 16141ae8e74SKuba Mracek ConstString module; 16241ae8e74SKuba Mracek RegularExpressionSP module_regexp; 16341ae8e74SKuba Mracek ConstString symbol; 164*cb0c4ee3SMed Ismail Bennani ConstString alternate_symbol; 16541ae8e74SKuba Mracek RegularExpressionSP symbol_regexp; 16641ae8e74SKuba Mracek bool first_instruction_only; 16741ae8e74SKuba Mracek }; 16841ae8e74SKuba Mracek 16941ae8e74SKuba Mracek std::deque<RegisteredEntry> m_recognizers; 17041ae8e74SKuba Mracek }; 17141ae8e74SKuba Mracek 17241ae8e74SKuba Mracek StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() { 17341ae8e74SKuba Mracek static StackFrameRecognizerManagerImpl instance = 17441ae8e74SKuba Mracek StackFrameRecognizerManagerImpl(); 17541ae8e74SKuba Mracek return instance; 17641ae8e74SKuba Mracek } 17741ae8e74SKuba Mracek 17841ae8e74SKuba Mracek void StackFrameRecognizerManager::AddRecognizer( 179*cb0c4ee3SMed Ismail Bennani StackFrameRecognizerSP recognizer, ConstString module, ConstString symbol, 180*cb0c4ee3SMed Ismail Bennani ConstString alternate_symbol, bool first_instruction_only) { 181*cb0c4ee3SMed Ismail Bennani GetStackFrameRecognizerManagerImpl().AddRecognizer( 182*cb0c4ee3SMed Ismail Bennani recognizer, module, symbol, alternate_symbol, first_instruction_only); 18341ae8e74SKuba Mracek } 18441ae8e74SKuba Mracek 18541ae8e74SKuba Mracek void StackFrameRecognizerManager::AddRecognizer( 18641ae8e74SKuba Mracek StackFrameRecognizerSP recognizer, RegularExpressionSP module, 18741ae8e74SKuba Mracek RegularExpressionSP symbol, bool first_instruction_only) { 18841ae8e74SKuba Mracek GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, 18941ae8e74SKuba Mracek first_instruction_only); 19041ae8e74SKuba Mracek } 19141ae8e74SKuba Mracek 19241ae8e74SKuba Mracek void StackFrameRecognizerManager::ForEach( 193*cb0c4ee3SMed Ismail Bennani std::function<void(uint32_t recognized_id, std::string recognizer_name, 194*cb0c4ee3SMed Ismail Bennani std::string module, std::string symbol, 195*cb0c4ee3SMed Ismail Bennani std::string alternate_symbol, bool regexp)> const 196*cb0c4ee3SMed Ismail Bennani &callback) { 19741ae8e74SKuba Mracek GetStackFrameRecognizerManagerImpl().ForEach(callback); 19841ae8e74SKuba Mracek } 19941ae8e74SKuba Mracek 20041ae8e74SKuba Mracek void StackFrameRecognizerManager::RemoveAllRecognizers() { 20141ae8e74SKuba Mracek GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers(); 20241ae8e74SKuba Mracek } 20341ae8e74SKuba Mracek 20441ae8e74SKuba Mracek bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) { 20541ae8e74SKuba Mracek return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id); 20641ae8e74SKuba Mracek } 20741ae8e74SKuba Mracek 20841ae8e74SKuba Mracek RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame( 20941ae8e74SKuba Mracek StackFrameSP frame) { 21041ae8e74SKuba Mracek return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame); 21141ae8e74SKuba Mracek } 21241ae8e74SKuba Mracek 21341ae8e74SKuba Mracek StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame( 21441ae8e74SKuba Mracek lldb::StackFrameSP frame) { 21541ae8e74SKuba Mracek return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame); 21641ae8e74SKuba Mracek } 217