1343181Sdim//===-- StackFrameRecognizer.cpp --------------------------------*- C++ -*-===// 2343181Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6343181Sdim// 7343181Sdim//===----------------------------------------------------------------------===// 8343181Sdim 9343181Sdim#include <vector> 10343181Sdim#include "lldb/Core/Module.h" 11343181Sdim#include "lldb/Interpreter/ScriptInterpreter.h" 12343181Sdim#include "lldb/Symbol/Symbol.h" 13343181Sdim#include "lldb/Target/StackFrame.h" 14343181Sdim#include "lldb/Target/StackFrameRecognizer.h" 15343181Sdim#include "lldb/Utility/RegularExpression.h" 16343181Sdim 17343181Sdimusing namespace lldb; 18343181Sdimusing namespace lldb_private; 19343181Sdim 20343181Sdimclass ScriptedRecognizedStackFrame : public RecognizedStackFrame { 21343181Sdimpublic: 22343181Sdim ScriptedRecognizedStackFrame(ValueObjectListSP args) { 23343181Sdim m_arguments = args; 24343181Sdim } 25343181Sdim}; 26343181Sdim 27343181SdimScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer( 28343181Sdim ScriptInterpreter *interpreter, const char *pclass) 29343181Sdim : m_interpreter(interpreter), m_python_class(pclass) { 30343181Sdim m_python_object_sp = 31343181Sdim m_interpreter->CreateFrameRecognizer(m_python_class.c_str()); 32343181Sdim} 33343181Sdim 34343181SdimRecognizedStackFrameSP 35343181SdimScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) { 36343181Sdim if (!m_python_object_sp || !m_interpreter) 37343181Sdim return RecognizedStackFrameSP(); 38343181Sdim 39343181Sdim ValueObjectListSP args = 40343181Sdim m_interpreter->GetRecognizedArguments(m_python_object_sp, frame); 41353358Sdim auto args_synthesized = ValueObjectListSP(new ValueObjectList()); 42360784Sdim for (const auto &o : args->GetObjects()) { 43353358Sdim args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create( 44353358Sdim *o, eValueTypeVariableArgument)); 45353358Sdim } 46343181Sdim 47353358Sdim return RecognizedStackFrameSP( 48353358Sdim new ScriptedRecognizedStackFrame(args_synthesized)); 49343181Sdim} 50343181Sdim 51343181Sdimclass StackFrameRecognizerManagerImpl { 52343181Sdimpublic: 53343181Sdim void AddRecognizer(StackFrameRecognizerSP recognizer, 54353358Sdim ConstString module, ConstString symbol, 55343181Sdim bool first_instruction_only) { 56343181Sdim m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, false, module, RegularExpressionSP(), 57343181Sdim symbol, RegularExpressionSP(), 58343181Sdim first_instruction_only}); 59343181Sdim } 60343181Sdim 61343181Sdim void AddRecognizer(StackFrameRecognizerSP recognizer, 62343181Sdim RegularExpressionSP module, RegularExpressionSP symbol, 63343181Sdim bool first_instruction_only) { 64343181Sdim m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, true, ConstString(), module, 65343181Sdim ConstString(), symbol, first_instruction_only}); 66343181Sdim } 67343181Sdim 68343181Sdim void ForEach( 69343181Sdim std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module, 70343181Sdim std::string symbol, bool regexp)> const &callback) { 71343181Sdim for (auto entry : m_recognizers) { 72343181Sdim if (entry.is_regexp) { 73343181Sdim callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module_regexp->GetText(), 74343181Sdim entry.symbol_regexp->GetText(), true); 75343181Sdim } else { 76343181Sdim callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module.GetCString(), 77343181Sdim entry.symbol.GetCString(), false); 78343181Sdim } 79343181Sdim } 80343181Sdim } 81343181Sdim 82343181Sdim bool RemoveRecognizerWithID(uint32_t recognizer_id) { 83343181Sdim if (recognizer_id >= m_recognizers.size()) return false; 84343181Sdim if (m_recognizers[recognizer_id].deleted) return false; 85343181Sdim m_recognizers[recognizer_id].deleted = true; 86343181Sdim return true; 87343181Sdim } 88343181Sdim 89343181Sdim void RemoveAllRecognizers() { 90343181Sdim m_recognizers.clear(); 91343181Sdim } 92343181Sdim 93343181Sdim StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) { 94343181Sdim const SymbolContext &symctx = 95343181Sdim frame->GetSymbolContext(eSymbolContextModule | eSymbolContextFunction); 96343181Sdim ConstString function_name = symctx.GetFunctionName(); 97343181Sdim ModuleSP module_sp = symctx.module_sp; 98343181Sdim if (!module_sp) return StackFrameRecognizerSP(); 99343181Sdim ConstString module_name = module_sp->GetFileSpec().GetFilename(); 100343181Sdim Symbol *symbol = symctx.symbol; 101343181Sdim if (!symbol) return StackFrameRecognizerSP(); 102343181Sdim Address start_addr = symbol->GetAddress(); 103343181Sdim Address current_addr = frame->GetFrameCodeAddress(); 104343181Sdim 105343181Sdim for (auto entry : m_recognizers) { 106343181Sdim if (entry.deleted) continue; 107343181Sdim if (entry.module) 108343181Sdim if (entry.module != module_name) continue; 109343181Sdim 110343181Sdim if (entry.module_regexp) 111343181Sdim if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue; 112343181Sdim 113343181Sdim if (entry.symbol) 114343181Sdim if (entry.symbol != function_name) continue; 115343181Sdim 116343181Sdim if (entry.symbol_regexp) 117343181Sdim if (!entry.symbol_regexp->Execute(function_name.GetStringRef())) 118343181Sdim continue; 119343181Sdim 120343181Sdim if (entry.first_instruction_only) 121343181Sdim if (start_addr != current_addr) continue; 122343181Sdim 123343181Sdim return entry.recognizer; 124343181Sdim } 125343181Sdim return StackFrameRecognizerSP(); 126343181Sdim } 127343181Sdim 128343181Sdim RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) { 129343181Sdim auto recognizer = GetRecognizerForFrame(frame); 130343181Sdim if (!recognizer) return RecognizedStackFrameSP(); 131343181Sdim return recognizer->RecognizeFrame(frame); 132343181Sdim } 133343181Sdim 134343181Sdim private: 135343181Sdim struct RegisteredEntry { 136343181Sdim uint32_t recognizer_id; 137343181Sdim bool deleted; 138343181Sdim StackFrameRecognizerSP recognizer; 139343181Sdim bool is_regexp; 140343181Sdim ConstString module; 141343181Sdim RegularExpressionSP module_regexp; 142343181Sdim ConstString symbol; 143343181Sdim RegularExpressionSP symbol_regexp; 144343181Sdim bool first_instruction_only; 145343181Sdim }; 146343181Sdim 147343181Sdim std::deque<RegisteredEntry> m_recognizers; 148343181Sdim}; 149343181Sdim 150343181SdimStackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() { 151343181Sdim static StackFrameRecognizerManagerImpl instance = 152343181Sdim StackFrameRecognizerManagerImpl(); 153343181Sdim return instance; 154343181Sdim} 155343181Sdim 156343181Sdimvoid StackFrameRecognizerManager::AddRecognizer( 157353358Sdim StackFrameRecognizerSP recognizer, ConstString module, 158353358Sdim ConstString symbol, bool first_instruction_only) { 159343181Sdim GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, 160343181Sdim first_instruction_only); 161343181Sdim} 162343181Sdim 163343181Sdimvoid StackFrameRecognizerManager::AddRecognizer( 164343181Sdim StackFrameRecognizerSP recognizer, RegularExpressionSP module, 165343181Sdim RegularExpressionSP symbol, bool first_instruction_only) { 166343181Sdim GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, 167343181Sdim first_instruction_only); 168343181Sdim} 169343181Sdim 170343181Sdimvoid StackFrameRecognizerManager::ForEach( 171343181Sdim std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module, 172343181Sdim std::string symbol, bool regexp)> const &callback) { 173343181Sdim GetStackFrameRecognizerManagerImpl().ForEach(callback); 174343181Sdim} 175343181Sdim 176343181Sdimvoid StackFrameRecognizerManager::RemoveAllRecognizers() { 177343181Sdim GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers(); 178343181Sdim} 179343181Sdim 180343181Sdimbool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) { 181343181Sdim return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id); 182343181Sdim} 183343181Sdim 184343181SdimRecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame( 185343181Sdim StackFrameSP frame) { 186343181Sdim return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame); 187343181Sdim} 188343181Sdim 189343181SdimStackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame( 190343181Sdim lldb::StackFrameSP frame) { 191343181Sdim return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame); 192343181Sdim} 193