193 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/StackFrameRecognizer.h"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/Utility/RegularExpression.h"15 16using namespace lldb;17using namespace lldb_private;18 19class ScriptedRecognizedStackFrame : public RecognizedStackFrame {20 bool m_hidden;21 22public:23 ScriptedRecognizedStackFrame(ValueObjectListSP args, bool hidden)24 : m_hidden(hidden) {25 m_arguments = std::move(args);26 }27 bool ShouldHide() override { return m_hidden; }28};29 30ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(31 ScriptInterpreter *interpreter, const char *pclass)32 : m_interpreter(interpreter), m_python_class(pclass) {33 m_python_object_sp =34 m_interpreter->CreateFrameRecognizer(m_python_class.c_str());35}36 37RecognizedStackFrameSP38ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {39 if (!m_python_object_sp || !m_interpreter)40 return RecognizedStackFrameSP();41 42 ValueObjectListSP args =43 m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);44 auto args_synthesized = std::make_shared<ValueObjectList>();45 if (args) {46 for (const auto &o : args->GetObjects())47 args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(48 *o, eValueTypeVariableArgument));49 }50 51 bool hidden = m_interpreter->ShouldHide(m_python_object_sp, frame);52 53 return RecognizedStackFrameSP(54 new ScriptedRecognizedStackFrame(args_synthesized, hidden));55}56 57void StackFrameRecognizerManager::BumpGeneration() {58 uint32_t n = m_generation;59 n = (n + 1) & ((1 << 16) - 1);60 m_generation = n;61}62 63void StackFrameRecognizerManager::AddRecognizer(64 StackFrameRecognizerSP recognizer, ConstString module,65 llvm::ArrayRef<ConstString> symbols,66 Mangled::NamePreference symbol_mangling, bool first_instruction_only) {67 m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,68 module, RegularExpressionSP(), symbols,69 RegularExpressionSP(), symbol_mangling,70 first_instruction_only, true});71 BumpGeneration();72}73 74void StackFrameRecognizerManager::AddRecognizer(75 StackFrameRecognizerSP recognizer, RegularExpressionSP module,76 RegularExpressionSP symbol, Mangled::NamePreference symbol_mangling,77 bool first_instruction_only) {78 m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,79 ConstString(), module, std::vector<ConstString>(),80 symbol, symbol_mangling, first_instruction_only,81 true});82 BumpGeneration();83}84 85void StackFrameRecognizerManager::ForEach(86 const std::function<void(87 uint32_t, bool, std::string, std::string, llvm::ArrayRef<ConstString>,88 Mangled::NamePreference name_preference, bool)> &callback) {89 for (auto entry : m_recognizers) {90 if (entry.is_regexp) {91 std::string module_name;92 std::string symbol_name;93 94 if (entry.module_regexp)95 module_name = entry.module_regexp->GetText().str();96 if (entry.symbol_regexp)97 symbol_name = entry.symbol_regexp->GetText().str();98 99 callback(entry.recognizer_id, entry.enabled, entry.recognizer->GetName(),100 module_name, llvm::ArrayRef(ConstString(symbol_name)),101 entry.symbol_mangling, true);102 } else {103 callback(entry.recognizer_id, entry.enabled, entry.recognizer->GetName(),104 entry.module.GetCString(), entry.symbols, entry.symbol_mangling,105 false);106 }107 }108}109 110bool StackFrameRecognizerManager::SetEnabledForID(uint32_t recognizer_id,111 bool enabled) {112 auto found =113 llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) {114 return e.recognizer_id == recognizer_id;115 });116 if (found == m_recognizers.end())117 return false;118 found->enabled = enabled;119 BumpGeneration();120 return true;121}122 123bool StackFrameRecognizerManager::RemoveRecognizerWithID(124 uint32_t recognizer_id) {125 auto found =126 llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) {127 return e.recognizer_id == recognizer_id;128 });129 if (found == m_recognizers.end())130 return false;131 m_recognizers.erase(found);132 BumpGeneration();133 return true;134}135 136void StackFrameRecognizerManager::RemoveAllRecognizers() {137 BumpGeneration();138 m_recognizers.clear();139}140 141StackFrameRecognizerSP142StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {143 const SymbolContext &symctx = frame->GetSymbolContext(144 eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);145 ModuleSP module_sp = symctx.module_sp;146 if (!module_sp)147 return StackFrameRecognizerSP();148 ConstString module_name = module_sp->GetFileSpec().GetFilename();149 Symbol *symbol = symctx.symbol;150 if (!symbol)151 return StackFrameRecognizerSP();152 Address start_addr = symbol->GetAddress();153 Address current_addr = frame->GetFrameCodeAddress();154 155 for (const auto &entry : m_recognizers) {156 if (!entry.enabled)157 continue;158 159 if (entry.module)160 if (entry.module != module_name)161 continue;162 163 if (entry.module_regexp)164 if (!entry.module_regexp->Execute(module_name.GetStringRef()))165 continue;166 167 ConstString function_name = symctx.GetFunctionName(entry.symbol_mangling);168 169 if (!entry.symbols.empty())170 if (!llvm::is_contained(entry.symbols, function_name))171 continue;172 173 if (entry.symbol_regexp)174 if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))175 continue;176 177 if (entry.first_instruction_only)178 if (start_addr != current_addr)179 continue;180 181 return entry.recognizer;182 }183 return StackFrameRecognizerSP();184}185 186RecognizedStackFrameSP187StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) {188 auto recognizer = GetRecognizerForFrame(frame);189 if (!recognizer)190 return RecognizedStackFrameSP();191 return recognizer->RecognizeFrame(frame);192}193