141ae8e74SKuba Mracek //===-- StackFrameRecognizer.cpp --------------------------------*- C++ -*-===// 241ae8e74SKuba Mracek // 341ae8e74SKuba Mracek // The LLVM Compiler Infrastructure 441ae8e74SKuba Mracek // 541ae8e74SKuba Mracek // This file is distributed under the University of Illinois Open Source 641ae8e74SKuba Mracek // License. See LICENSE.TXT for details. 741ae8e74SKuba Mracek // 841ae8e74SKuba Mracek //===----------------------------------------------------------------------===// 941ae8e74SKuba Mracek 1041ae8e74SKuba Mracek // C Includes 1141ae8e74SKuba Mracek // C++ Includes 1241ae8e74SKuba Mracek #include <vector> 1341ae8e74SKuba Mracek // Other libraries and framework includes 1441ae8e74SKuba Mracek // Project includes 1541ae8e74SKuba Mracek #include "lldb/Core/Module.h" 1641ae8e74SKuba Mracek #include "lldb/Interpreter/ScriptInterpreter.h" 1741ae8e74SKuba Mracek #include "lldb/Symbol/Symbol.h" 1841ae8e74SKuba Mracek #include "lldb/Target/StackFrame.h" 1941ae8e74SKuba Mracek #include "lldb/Target/StackFrameRecognizer.h" 2041ae8e74SKuba Mracek #include "lldb/Utility/RegularExpression.h" 2141ae8e74SKuba Mracek 2241ae8e74SKuba Mracek using namespace lldb; 2341ae8e74SKuba Mracek using namespace lldb_private; 2441ae8e74SKuba Mracek 25*f80d2655SKuba Mracek #ifndef LLDB_DISABLE_PYTHON 26*f80d2655SKuba Mracek 2741ae8e74SKuba Mracek class ScriptedRecognizedStackFrame : public RecognizedStackFrame { 2841ae8e74SKuba Mracek public: 2941ae8e74SKuba Mracek ScriptedRecognizedStackFrame(ValueObjectListSP args) { 3041ae8e74SKuba Mracek m_arguments = args; 3141ae8e74SKuba Mracek } 3241ae8e74SKuba Mracek }; 3341ae8e74SKuba Mracek 3441ae8e74SKuba Mracek ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer( 3541ae8e74SKuba Mracek ScriptInterpreter *interpreter, const char *pclass) 3641ae8e74SKuba Mracek : m_interpreter(interpreter), m_python_class(pclass) { 3741ae8e74SKuba Mracek m_python_object_sp = 3841ae8e74SKuba Mracek m_interpreter->CreateFrameRecognizer(m_python_class.c_str()); 3941ae8e74SKuba Mracek } 4041ae8e74SKuba Mracek 4141ae8e74SKuba Mracek RecognizedStackFrameSP 4241ae8e74SKuba Mracek ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) { 4341ae8e74SKuba Mracek if (!m_python_object_sp || !m_interpreter) 4441ae8e74SKuba Mracek return RecognizedStackFrameSP(); 4541ae8e74SKuba Mracek 4641ae8e74SKuba Mracek ValueObjectListSP args = 4741ae8e74SKuba Mracek m_interpreter->GetRecognizedArguments(m_python_object_sp, frame); 4841ae8e74SKuba Mracek 4941ae8e74SKuba Mracek return RecognizedStackFrameSP(new ScriptedRecognizedStackFrame(args)); 5041ae8e74SKuba Mracek } 5141ae8e74SKuba Mracek 52*f80d2655SKuba Mracek #endif 53*f80d2655SKuba Mracek 5441ae8e74SKuba Mracek class StackFrameRecognizerManagerImpl { 5541ae8e74SKuba Mracek public: 5641ae8e74SKuba Mracek void AddRecognizer(StackFrameRecognizerSP recognizer, ConstString &module, 5741ae8e74SKuba Mracek ConstString &symbol, bool first_instruction_only) { 5841ae8e74SKuba Mracek m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, false, module, RegularExpressionSP(), 5941ae8e74SKuba Mracek symbol, RegularExpressionSP(), 6041ae8e74SKuba Mracek first_instruction_only}); 6141ae8e74SKuba Mracek } 6241ae8e74SKuba Mracek 6341ae8e74SKuba Mracek void AddRecognizer(StackFrameRecognizerSP recognizer, 6441ae8e74SKuba Mracek RegularExpressionSP module, RegularExpressionSP symbol, 6541ae8e74SKuba Mracek bool first_instruction_only) { 6641ae8e74SKuba Mracek m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, true, ConstString(), module, 6741ae8e74SKuba Mracek ConstString(), symbol, first_instruction_only}); 6841ae8e74SKuba Mracek } 6941ae8e74SKuba Mracek 7041ae8e74SKuba Mracek void ForEach( 7141ae8e74SKuba Mracek std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module, 7241ae8e74SKuba Mracek std::string symbol, bool regexp)> const &callback) { 7341ae8e74SKuba Mracek for (auto entry : m_recognizers) { 7441ae8e74SKuba Mracek if (entry.is_regexp) { 7541ae8e74SKuba Mracek callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module_regexp->GetText(), 7641ae8e74SKuba Mracek entry.symbol_regexp->GetText(), true); 7741ae8e74SKuba Mracek } else { 7841ae8e74SKuba Mracek callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module.GetCString(), 7941ae8e74SKuba Mracek entry.symbol.GetCString(), false); 8041ae8e74SKuba Mracek } 8141ae8e74SKuba Mracek } 8241ae8e74SKuba Mracek } 8341ae8e74SKuba Mracek 8441ae8e74SKuba Mracek bool RemoveRecognizerWithID(uint32_t recognizer_id) { 8541ae8e74SKuba Mracek if (recognizer_id >= m_recognizers.size()) return false; 8641ae8e74SKuba Mracek if (m_recognizers[recognizer_id].deleted) return false; 8741ae8e74SKuba Mracek m_recognizers[recognizer_id].deleted = true; 8841ae8e74SKuba Mracek return true; 8941ae8e74SKuba Mracek } 9041ae8e74SKuba Mracek 9141ae8e74SKuba Mracek void RemoveAllRecognizers() { 9241ae8e74SKuba Mracek m_recognizers.clear(); 9341ae8e74SKuba Mracek } 9441ae8e74SKuba Mracek 9541ae8e74SKuba Mracek StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) { 9641ae8e74SKuba Mracek const SymbolContext &symctx = 9741ae8e74SKuba Mracek frame->GetSymbolContext(eSymbolContextModule | eSymbolContextFunction); 9841ae8e74SKuba Mracek ConstString function_name = symctx.GetFunctionName(); 9941ae8e74SKuba Mracek ModuleSP module_sp = symctx.module_sp; 10041ae8e74SKuba Mracek if (!module_sp) return StackFrameRecognizerSP(); 10141ae8e74SKuba Mracek ConstString module_name = module_sp->GetFileSpec().GetFilename(); 10241ae8e74SKuba Mracek Symbol *symbol = symctx.symbol; 10341ae8e74SKuba Mracek if (!symbol) return StackFrameRecognizerSP(); 10441ae8e74SKuba Mracek Address start_addr = symbol->GetAddress(); 10541ae8e74SKuba Mracek Address current_addr = frame->GetFrameCodeAddress(); 10641ae8e74SKuba Mracek 10741ae8e74SKuba Mracek for (auto entry : m_recognizers) { 10841ae8e74SKuba Mracek if (entry.deleted) continue; 10941ae8e74SKuba Mracek if (entry.module) 11041ae8e74SKuba Mracek if (entry.module != module_name) continue; 11141ae8e74SKuba Mracek 11241ae8e74SKuba Mracek if (entry.module_regexp) 11341ae8e74SKuba Mracek if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue; 11441ae8e74SKuba Mracek 11541ae8e74SKuba Mracek if (entry.symbol) 11641ae8e74SKuba Mracek if (entry.symbol != function_name) continue; 11741ae8e74SKuba Mracek 11841ae8e74SKuba Mracek if (entry.symbol_regexp) 11941ae8e74SKuba Mracek if (!entry.symbol_regexp->Execute(function_name.GetStringRef())) 12041ae8e74SKuba Mracek continue; 12141ae8e74SKuba Mracek 12241ae8e74SKuba Mracek if (entry.first_instruction_only) 12341ae8e74SKuba Mracek if (start_addr != current_addr) continue; 12441ae8e74SKuba Mracek 12541ae8e74SKuba Mracek return entry.recognizer; 12641ae8e74SKuba Mracek } 12741ae8e74SKuba Mracek return StackFrameRecognizerSP(); 12841ae8e74SKuba Mracek } 12941ae8e74SKuba Mracek 13041ae8e74SKuba Mracek RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) { 13141ae8e74SKuba Mracek auto recognizer = GetRecognizerForFrame(frame); 13241ae8e74SKuba Mracek if (!recognizer) return RecognizedStackFrameSP(); 13341ae8e74SKuba Mracek return recognizer->RecognizeFrame(frame); 13441ae8e74SKuba Mracek } 13541ae8e74SKuba Mracek 13641ae8e74SKuba Mracek private: 13741ae8e74SKuba Mracek struct RegisteredEntry { 13841ae8e74SKuba Mracek uint32_t recognizer_id; 13941ae8e74SKuba Mracek bool deleted; 14041ae8e74SKuba Mracek StackFrameRecognizerSP recognizer; 14141ae8e74SKuba Mracek bool is_regexp; 14241ae8e74SKuba Mracek ConstString module; 14341ae8e74SKuba Mracek RegularExpressionSP module_regexp; 14441ae8e74SKuba Mracek ConstString symbol; 14541ae8e74SKuba Mracek RegularExpressionSP symbol_regexp; 14641ae8e74SKuba Mracek bool first_instruction_only; 14741ae8e74SKuba Mracek }; 14841ae8e74SKuba Mracek 14941ae8e74SKuba Mracek std::deque<RegisteredEntry> m_recognizers; 15041ae8e74SKuba Mracek }; 15141ae8e74SKuba Mracek 15241ae8e74SKuba Mracek StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() { 15341ae8e74SKuba Mracek static StackFrameRecognizerManagerImpl instance = 15441ae8e74SKuba Mracek StackFrameRecognizerManagerImpl(); 15541ae8e74SKuba Mracek return instance; 15641ae8e74SKuba Mracek } 15741ae8e74SKuba Mracek 15841ae8e74SKuba Mracek void StackFrameRecognizerManager::AddRecognizer( 15941ae8e74SKuba Mracek StackFrameRecognizerSP recognizer, ConstString &module, ConstString &symbol, 16041ae8e74SKuba Mracek bool first_instruction_only) { 16141ae8e74SKuba Mracek GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, 16241ae8e74SKuba Mracek first_instruction_only); 16341ae8e74SKuba Mracek } 16441ae8e74SKuba Mracek 16541ae8e74SKuba Mracek void StackFrameRecognizerManager::AddRecognizer( 16641ae8e74SKuba Mracek StackFrameRecognizerSP recognizer, RegularExpressionSP module, 16741ae8e74SKuba Mracek RegularExpressionSP symbol, bool first_instruction_only) { 16841ae8e74SKuba Mracek GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, 16941ae8e74SKuba Mracek first_instruction_only); 17041ae8e74SKuba Mracek } 17141ae8e74SKuba Mracek 17241ae8e74SKuba Mracek void StackFrameRecognizerManager::ForEach( 17341ae8e74SKuba Mracek std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module, 17441ae8e74SKuba Mracek std::string symbol, bool regexp)> const &callback) { 17541ae8e74SKuba Mracek GetStackFrameRecognizerManagerImpl().ForEach(callback); 17641ae8e74SKuba Mracek } 17741ae8e74SKuba Mracek 17841ae8e74SKuba Mracek void StackFrameRecognizerManager::RemoveAllRecognizers() { 17941ae8e74SKuba Mracek GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers(); 18041ae8e74SKuba Mracek } 18141ae8e74SKuba Mracek 18241ae8e74SKuba Mracek bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) { 18341ae8e74SKuba Mracek return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id); 18441ae8e74SKuba Mracek } 18541ae8e74SKuba Mracek 18641ae8e74SKuba Mracek RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame( 18741ae8e74SKuba Mracek StackFrameSP frame) { 18841ae8e74SKuba Mracek return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame); 18941ae8e74SKuba Mracek } 19041ae8e74SKuba Mracek 19141ae8e74SKuba Mracek StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame( 19241ae8e74SKuba Mracek lldb::StackFrameSP frame) { 19341ae8e74SKuba Mracek return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame); 19441ae8e74SKuba Mracek } 195