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 91b7c9eaeSRaphael 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 { 203c0fba4fSAdrian Prantl bool m_hidden; 213c0fba4fSAdrian Prantl 2241ae8e74SKuba Mracek public: 233c0fba4fSAdrian Prantl ScriptedRecognizedStackFrame(ValueObjectListSP args, bool hidden) 243c0fba4fSAdrian Prantl : m_hidden(hidden) { 253c0fba4fSAdrian Prantl m_arguments = std::move(args); 2641ae8e74SKuba Mracek } 273c0fba4fSAdrian Prantl bool ShouldHide() override { return m_hidden; } 2841ae8e74SKuba Mracek }; 2941ae8e74SKuba Mracek 3041ae8e74SKuba Mracek ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer( 3141ae8e74SKuba Mracek ScriptInterpreter *interpreter, const char *pclass) 3241ae8e74SKuba Mracek : m_interpreter(interpreter), m_python_class(pclass) { 3341ae8e74SKuba Mracek m_python_object_sp = 3441ae8e74SKuba Mracek m_interpreter->CreateFrameRecognizer(m_python_class.c_str()); 3541ae8e74SKuba Mracek } 3641ae8e74SKuba Mracek 3741ae8e74SKuba Mracek RecognizedStackFrameSP 3841ae8e74SKuba Mracek ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) { 3941ae8e74SKuba Mracek if (!m_python_object_sp || !m_interpreter) 4041ae8e74SKuba Mracek return RecognizedStackFrameSP(); 4141ae8e74SKuba Mracek 4241ae8e74SKuba Mracek ValueObjectListSP args = 4341ae8e74SKuba Mracek m_interpreter->GetRecognizedArguments(m_python_object_sp, frame); 4492369dcfSKuba Mracek auto args_synthesized = ValueObjectListSP(new ValueObjectList()); 453c0fba4fSAdrian Prantl if (args) { 463c0fba4fSAdrian Prantl for (const auto &o : args->GetObjects()) 4792369dcfSKuba Mracek args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create( 4892369dcfSKuba Mracek *o, eValueTypeVariableArgument)); 4992369dcfSKuba Mracek } 5041ae8e74SKuba Mracek 513c0fba4fSAdrian Prantl bool hidden = m_interpreter->ShouldHide(m_python_object_sp, frame); 523c0fba4fSAdrian Prantl 5392369dcfSKuba Mracek return RecognizedStackFrameSP( 543c0fba4fSAdrian Prantl new ScriptedRecognizedStackFrame(args_synthesized, hidden)); 553c0fba4fSAdrian Prantl } 563c0fba4fSAdrian Prantl 573c0fba4fSAdrian Prantl void StackFrameRecognizerManager::BumpGeneration() { 583c0fba4fSAdrian Prantl uint32_t n = m_generation; 593c0fba4fSAdrian Prantl n = (n + 1) & ((1 << 16) - 1); 603c0fba4fSAdrian Prantl m_generation = n; 6141ae8e74SKuba Mracek } 6241ae8e74SKuba Mracek 631b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::AddRecognizer( 641b7c9eaeSRaphael Isemann StackFrameRecognizerSP recognizer, ConstString module, 65dd060bdeSAdrian Vogelsgesang llvm::ArrayRef<ConstString> symbols, 66dd060bdeSAdrian Vogelsgesang Mangled::NamePreference symbol_mangling, bool first_instruction_only) { 675477fbc2SRaphael Isemann m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false, 685477fbc2SRaphael Isemann module, RegularExpressionSP(), symbols, 69dd060bdeSAdrian Vogelsgesang RegularExpressionSP(), symbol_mangling, 70*d8d252feSAdrian Vogelsgesang first_instruction_only, true}); 713c0fba4fSAdrian Prantl BumpGeneration(); 7241ae8e74SKuba Mracek } 7341ae8e74SKuba Mracek 741b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::AddRecognizer( 751b7c9eaeSRaphael Isemann StackFrameRecognizerSP recognizer, RegularExpressionSP module, 76dd060bdeSAdrian Vogelsgesang RegularExpressionSP symbol, Mangled::NamePreference symbol_mangling, 77dd060bdeSAdrian Vogelsgesang bool first_instruction_only) { 785477fbc2SRaphael Isemann m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true, 795477fbc2SRaphael Isemann ConstString(), module, std::vector<ConstString>(), 80*d8d252feSAdrian Vogelsgesang symbol, symbol_mangling, first_instruction_only, 81*d8d252feSAdrian Vogelsgesang true}); 823c0fba4fSAdrian Prantl BumpGeneration(); 8341ae8e74SKuba Mracek } 8441ae8e74SKuba Mracek 851b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::ForEach( 86*d8d252feSAdrian Vogelsgesang const std::function<void( 87*d8d252feSAdrian Vogelsgesang uint32_t, bool, std::string, std::string, llvm::ArrayRef<ConstString>, 88*d8d252feSAdrian Vogelsgesang Mangled::NamePreference name_preference, bool)> &callback) { 8941ae8e74SKuba Mracek for (auto entry : m_recognizers) { 9041ae8e74SKuba Mracek if (entry.is_regexp) { 91047c4b03SMed Ismail Bennani std::string module_name; 92047c4b03SMed Ismail Bennani std::string symbol_name; 93047c4b03SMed Ismail Bennani 94047c4b03SMed Ismail Bennani if (entry.module_regexp) 95047c4b03SMed Ismail Bennani module_name = entry.module_regexp->GetText().str(); 96047c4b03SMed Ismail Bennani if (entry.symbol_regexp) 97047c4b03SMed Ismail Bennani symbol_name = entry.symbol_regexp->GetText().str(); 98047c4b03SMed Ismail Bennani 99*d8d252feSAdrian Vogelsgesang callback(entry.recognizer_id, entry.enabled, entry.recognizer->GetName(), 100*d8d252feSAdrian Vogelsgesang module_name, llvm::ArrayRef(ConstString(symbol_name)), 101*d8d252feSAdrian Vogelsgesang entry.symbol_mangling, true); 10241ae8e74SKuba Mracek } else { 103*d8d252feSAdrian Vogelsgesang callback(entry.recognizer_id, entry.enabled, entry.recognizer->GetName(), 104dd060bdeSAdrian Vogelsgesang entry.module.GetCString(), entry.symbols, entry.symbol_mangling, 105dd060bdeSAdrian Vogelsgesang false); 10641ae8e74SKuba Mracek } 10741ae8e74SKuba Mracek } 10841ae8e74SKuba Mracek } 10941ae8e74SKuba Mracek 110*d8d252feSAdrian Vogelsgesang bool StackFrameRecognizerManager::SetEnabledForID(uint32_t recognizer_id, 111*d8d252feSAdrian Vogelsgesang bool enabled) { 112*d8d252feSAdrian Vogelsgesang auto found = 113*d8d252feSAdrian Vogelsgesang llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) { 114*d8d252feSAdrian Vogelsgesang return e.recognizer_id == recognizer_id; 115*d8d252feSAdrian Vogelsgesang }); 116*d8d252feSAdrian Vogelsgesang if (found == m_recognizers.end()) 117*d8d252feSAdrian Vogelsgesang return false; 118*d8d252feSAdrian Vogelsgesang found->enabled = enabled; 119*d8d252feSAdrian Vogelsgesang BumpGeneration(); 120*d8d252feSAdrian Vogelsgesang return true; 121*d8d252feSAdrian Vogelsgesang } 122*d8d252feSAdrian Vogelsgesang 1231b7c9eaeSRaphael Isemann bool StackFrameRecognizerManager::RemoveRecognizerWithID( 1241b7c9eaeSRaphael Isemann uint32_t recognizer_id) { 1255477fbc2SRaphael Isemann auto found = 1265477fbc2SRaphael Isemann llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) { 1275477fbc2SRaphael Isemann return e.recognizer_id == recognizer_id; 1285477fbc2SRaphael Isemann }); 1295477fbc2SRaphael Isemann if (found == m_recognizers.end()) 1301b7c9eaeSRaphael Isemann return false; 1315477fbc2SRaphael Isemann m_recognizers.erase(found); 1323c0fba4fSAdrian Prantl BumpGeneration(); 13341ae8e74SKuba Mracek return true; 13441ae8e74SKuba Mracek } 13541ae8e74SKuba Mracek 1361b7c9eaeSRaphael Isemann void StackFrameRecognizerManager::RemoveAllRecognizers() { 1373c0fba4fSAdrian Prantl BumpGeneration(); 13841ae8e74SKuba Mracek m_recognizers.clear(); 13941ae8e74SKuba Mracek } 14041ae8e74SKuba Mracek 1411b7c9eaeSRaphael Isemann StackFrameRecognizerSP 1421b7c9eaeSRaphael Isemann StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) { 1437ebe9cc4SMed Ismail Bennani const SymbolContext &symctx = frame->GetSymbolContext( 1447ebe9cc4SMed Ismail Bennani eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol); 14541ae8e74SKuba Mracek ModuleSP module_sp = symctx.module_sp; 1461b7c9eaeSRaphael Isemann if (!module_sp) 1471b7c9eaeSRaphael Isemann return StackFrameRecognizerSP(); 14841ae8e74SKuba Mracek ConstString module_name = module_sp->GetFileSpec().GetFilename(); 14941ae8e74SKuba Mracek Symbol *symbol = symctx.symbol; 1501b7c9eaeSRaphael Isemann if (!symbol) 1511b7c9eaeSRaphael Isemann return StackFrameRecognizerSP(); 15241ae8e74SKuba Mracek Address start_addr = symbol->GetAddress(); 15341ae8e74SKuba Mracek Address current_addr = frame->GetFrameCodeAddress(); 15441ae8e74SKuba Mracek 15541ae8e74SKuba Mracek for (auto entry : m_recognizers) { 156*d8d252feSAdrian Vogelsgesang if (!entry.enabled) 157*d8d252feSAdrian Vogelsgesang continue; 158*d8d252feSAdrian Vogelsgesang 15941ae8e74SKuba Mracek if (entry.module) 1601b7c9eaeSRaphael Isemann if (entry.module != module_name) 1611b7c9eaeSRaphael Isemann continue; 16241ae8e74SKuba Mracek 16341ae8e74SKuba Mracek if (entry.module_regexp) 1641b7c9eaeSRaphael Isemann if (!entry.module_regexp->Execute(module_name.GetStringRef())) 1651b7c9eaeSRaphael Isemann continue; 16641ae8e74SKuba Mracek 167dd060bdeSAdrian Vogelsgesang ConstString function_name = symctx.GetFunctionName(entry.symbol_mangling); 168dd060bdeSAdrian Vogelsgesang 169db31e2e1SMed Ismail Bennani if (!entry.symbols.empty()) 170db31e2e1SMed Ismail Bennani if (!llvm::is_contained(entry.symbols, function_name)) 171cb0c4ee3SMed Ismail Bennani continue; 17241ae8e74SKuba Mracek 17341ae8e74SKuba Mracek if (entry.symbol_regexp) 17441ae8e74SKuba Mracek if (!entry.symbol_regexp->Execute(function_name.GetStringRef())) 17541ae8e74SKuba Mracek continue; 17641ae8e74SKuba Mracek 17741ae8e74SKuba Mracek if (entry.first_instruction_only) 1781b7c9eaeSRaphael Isemann if (start_addr != current_addr) 1791b7c9eaeSRaphael Isemann continue; 18041ae8e74SKuba Mracek 18141ae8e74SKuba Mracek return entry.recognizer; 18241ae8e74SKuba Mracek } 18341ae8e74SKuba Mracek return StackFrameRecognizerSP(); 18441ae8e74SKuba Mracek } 18541ae8e74SKuba Mracek 1861b7c9eaeSRaphael Isemann RecognizedStackFrameSP 1871b7c9eaeSRaphael Isemann StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) { 18841ae8e74SKuba Mracek auto recognizer = GetRecognizerForFrame(frame); 1891b7c9eaeSRaphael Isemann if (!recognizer) 1901b7c9eaeSRaphael Isemann return RecognizedStackFrameSP(); 19141ae8e74SKuba Mracek return recognizer->RecognizeFrame(frame); 19241ae8e74SKuba Mracek } 193