1 //===-- StackFrameRecognizer.cpp ------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <vector> 10 #include "lldb/Core/Module.h" 11 #include "lldb/Interpreter/ScriptInterpreter.h" 12 #include "lldb/Symbol/Symbol.h" 13 #include "lldb/Target/StackFrame.h" 14 #include "lldb/Target/StackFrameRecognizer.h" 15 #include "lldb/Utility/RegularExpression.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 class ScriptedRecognizedStackFrame : public RecognizedStackFrame { 21 public: 22 ScriptedRecognizedStackFrame(ValueObjectListSP args) { 23 m_arguments = args; 24 } 25 }; 26 27 ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer( 28 ScriptInterpreter *interpreter, const char *pclass) 29 : m_interpreter(interpreter), m_python_class(pclass) { 30 m_python_object_sp = 31 m_interpreter->CreateFrameRecognizer(m_python_class.c_str()); 32 } 33 34 RecognizedStackFrameSP 35 ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) { 36 if (!m_python_object_sp || !m_interpreter) 37 return RecognizedStackFrameSP(); 38 39 ValueObjectListSP args = 40 m_interpreter->GetRecognizedArguments(m_python_object_sp, frame); 41 auto args_synthesized = ValueObjectListSP(new ValueObjectList()); 42 for (const auto &o : args->GetObjects()) { 43 args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create( 44 *o, eValueTypeVariableArgument)); 45 } 46 47 return RecognizedStackFrameSP( 48 new ScriptedRecognizedStackFrame(args_synthesized)); 49 } 50 51 class StackFrameRecognizerManagerImpl { 52 public: 53 void AddRecognizer(StackFrameRecognizerSP recognizer, ConstString module, 54 ConstString symbol, ConstString alternate_symbol, 55 bool first_instruction_only) { 56 m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, 57 false, module, RegularExpressionSP(), symbol, 58 alternate_symbol, RegularExpressionSP(), 59 first_instruction_only}); 60 } 61 62 void AddRecognizer(StackFrameRecognizerSP recognizer, 63 RegularExpressionSP module, RegularExpressionSP symbol, 64 bool first_instruction_only) { 65 m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, 66 true, ConstString(), module, ConstString(), 67 ConstString(), symbol, first_instruction_only}); 68 } 69 70 void ForEach( 71 std::function<void(uint32_t recognized_id, std::string recognizer_name, 72 std::string module, std::string symbol, 73 std::string alternate_symbol, bool regexp)> const 74 &callback) { 75 for (auto entry : m_recognizers) { 76 if (entry.is_regexp) { 77 std::string module_name; 78 std::string symbol_name; 79 80 if (entry.module_regexp) 81 module_name = entry.module_regexp->GetText().str(); 82 if (entry.symbol_regexp) 83 symbol_name = entry.symbol_regexp->GetText().str(); 84 85 callback(entry.recognizer_id, entry.recognizer->GetName(), module_name, 86 symbol_name, {}, true); 87 88 } else { 89 callback(entry.recognizer_id, entry.recognizer->GetName(), 90 entry.module.GetCString(), entry.symbol.GetCString(), 91 entry.alternate_symbol.GetCString(), false); 92 } 93 } 94 } 95 96 bool RemoveRecognizerWithID(uint32_t recognizer_id) { 97 if (recognizer_id >= m_recognizers.size()) return false; 98 if (m_recognizers[recognizer_id].deleted) return false; 99 m_recognizers[recognizer_id].deleted = true; 100 return true; 101 } 102 103 void RemoveAllRecognizers() { 104 m_recognizers.clear(); 105 } 106 107 StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) { 108 const SymbolContext &symctx = frame->GetSymbolContext( 109 eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol); 110 ConstString function_name = symctx.GetFunctionName(); 111 ModuleSP module_sp = symctx.module_sp; 112 if (!module_sp) return StackFrameRecognizerSP(); 113 ConstString module_name = module_sp->GetFileSpec().GetFilename(); 114 Symbol *symbol = symctx.symbol; 115 if (!symbol) return StackFrameRecognizerSP(); 116 Address start_addr = symbol->GetAddress(); 117 Address current_addr = frame->GetFrameCodeAddress(); 118 119 for (auto entry : m_recognizers) { 120 if (entry.deleted) continue; 121 if (entry.module) 122 if (entry.module != module_name) continue; 123 124 if (entry.module_regexp) 125 if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue; 126 127 if (entry.symbol) 128 if (entry.symbol != function_name && 129 (!entry.alternate_symbol || 130 entry.alternate_symbol != function_name)) 131 continue; 132 133 if (entry.symbol_regexp) 134 if (!entry.symbol_regexp->Execute(function_name.GetStringRef())) 135 continue; 136 137 if (entry.first_instruction_only) 138 if (start_addr != current_addr) continue; 139 140 return entry.recognizer; 141 } 142 return StackFrameRecognizerSP(); 143 } 144 145 RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) { 146 auto recognizer = GetRecognizerForFrame(frame); 147 if (!recognizer) return RecognizedStackFrameSP(); 148 return recognizer->RecognizeFrame(frame); 149 } 150 151 private: 152 struct RegisteredEntry { 153 uint32_t recognizer_id; 154 bool deleted; 155 StackFrameRecognizerSP recognizer; 156 bool is_regexp; 157 ConstString module; 158 RegularExpressionSP module_regexp; 159 ConstString symbol; 160 ConstString alternate_symbol; 161 RegularExpressionSP symbol_regexp; 162 bool first_instruction_only; 163 }; 164 165 std::deque<RegisteredEntry> m_recognizers; 166 }; 167 168 StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() { 169 static StackFrameRecognizerManagerImpl instance = 170 StackFrameRecognizerManagerImpl(); 171 return instance; 172 } 173 174 void StackFrameRecognizerManager::AddRecognizer( 175 StackFrameRecognizerSP recognizer, ConstString module, ConstString symbol, 176 ConstString alternate_symbol, bool first_instruction_only) { 177 GetStackFrameRecognizerManagerImpl().AddRecognizer( 178 recognizer, module, symbol, alternate_symbol, first_instruction_only); 179 } 180 181 void StackFrameRecognizerManager::AddRecognizer( 182 StackFrameRecognizerSP recognizer, RegularExpressionSP module, 183 RegularExpressionSP symbol, bool first_instruction_only) { 184 GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol, 185 first_instruction_only); 186 } 187 188 void StackFrameRecognizerManager::ForEach( 189 std::function<void(uint32_t recognized_id, std::string recognizer_name, 190 std::string module, std::string symbol, 191 std::string alternate_symbol, bool regexp)> const 192 &callback) { 193 GetStackFrameRecognizerManagerImpl().ForEach(callback); 194 } 195 196 void StackFrameRecognizerManager::RemoveAllRecognizers() { 197 GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers(); 198 } 199 200 bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) { 201 return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id); 202 } 203 204 RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame( 205 StackFrameSP frame) { 206 return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame); 207 } 208 209 StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame( 210 lldb::StackFrameSP frame) { 211 return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame); 212 } 213