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