
Summary: Frame recognizers are stored alongside a flag that indicates whether they were deleted by the user. If the flag is set, they are supposed to be ignored by the rest of the frame recognizer code. 'frame recognizer delete' is supposed to set that flag. 'frame recognizer clear' however actually deletes all frame recognizers (so, it doesn't set the flag but directly deletes them from the list). The current implementation of this concept is pretty broken. `frame recognizer delete` sets the flag, but it somehow thinks that the recognizer id is an index in the recognizer list. That's not true as it's actually just a member of each recognizer entry. So it actually just sets the `deleted` flag for a random other recognizer. The tests for the recognizer still pass as `frame recognizer list` is also broken and just completely ignored the `deleted` flag and lists all recognizers. Also `frame recognizer delete` just ignores if it can't actually delete a recognizer if the id is invalid. I think we can simplify this whole thing by just actually deleting recognizers instead of making sure all code is actually respecting the `deleted` flag. I assume the intention of this was to make sure that all recognizers are getting unique ids over the course of an LLDB session, but as `clear` is actually deleting them and we keep recycling ids, that didn't really work to begin with. This patch deletes the `deleted` flag and just actually deletes the stored recognizer. Also adds the missing error message in case it find a recognizer with a given id. Reviewers: mib Reviewed By: mib Subscribers: abidh, JDevlieghere Differential Revision: https://reviews.llvm.org/D84404
155 lines
5.2 KiB
C++
155 lines
5.2 KiB
C++
//===-- StackFrameRecognizer.cpp ------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Target/StackFrameRecognizer.h"
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Interpreter/ScriptInterpreter.h"
|
|
#include "lldb/Symbol/Symbol.h"
|
|
#include "lldb/Target/StackFrame.h"
|
|
#include "lldb/Utility/RegularExpression.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
class ScriptedRecognizedStackFrame : public RecognizedStackFrame {
|
|
public:
|
|
ScriptedRecognizedStackFrame(ValueObjectListSP args) {
|
|
m_arguments = args;
|
|
}
|
|
};
|
|
|
|
ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
|
|
ScriptInterpreter *interpreter, const char *pclass)
|
|
: m_interpreter(interpreter), m_python_class(pclass) {
|
|
m_python_object_sp =
|
|
m_interpreter->CreateFrameRecognizer(m_python_class.c_str());
|
|
}
|
|
|
|
RecognizedStackFrameSP
|
|
ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
|
|
if (!m_python_object_sp || !m_interpreter)
|
|
return RecognizedStackFrameSP();
|
|
|
|
ValueObjectListSP args =
|
|
m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
|
|
auto args_synthesized = ValueObjectListSP(new ValueObjectList());
|
|
for (const auto &o : args->GetObjects()) {
|
|
args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(
|
|
*o, eValueTypeVariableArgument));
|
|
}
|
|
|
|
return RecognizedStackFrameSP(
|
|
new ScriptedRecognizedStackFrame(args_synthesized));
|
|
}
|
|
|
|
void StackFrameRecognizerManager::AddRecognizer(
|
|
StackFrameRecognizerSP recognizer, ConstString module,
|
|
llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
|
|
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
|
|
module, RegularExpressionSP(), symbols,
|
|
RegularExpressionSP(), first_instruction_only});
|
|
}
|
|
|
|
void StackFrameRecognizerManager::AddRecognizer(
|
|
StackFrameRecognizerSP recognizer, RegularExpressionSP module,
|
|
RegularExpressionSP symbol, bool first_instruction_only) {
|
|
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
|
|
ConstString(), module, std::vector<ConstString>(),
|
|
symbol, first_instruction_only});
|
|
}
|
|
|
|
void StackFrameRecognizerManager::ForEach(
|
|
const std::function<void(uint32_t, std::string, std::string,
|
|
llvm::ArrayRef<ConstString>, bool)> &callback) {
|
|
for (auto entry : m_recognizers) {
|
|
if (entry.is_regexp) {
|
|
std::string module_name;
|
|
std::string symbol_name;
|
|
|
|
if (entry.module_regexp)
|
|
module_name = entry.module_regexp->GetText().str();
|
|
if (entry.symbol_regexp)
|
|
symbol_name = entry.symbol_regexp->GetText().str();
|
|
|
|
callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
|
|
llvm::makeArrayRef(ConstString(symbol_name)), true);
|
|
|
|
} else {
|
|
callback(entry.recognizer_id, entry.recognizer->GetName(),
|
|
entry.module.GetCString(), entry.symbols, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool StackFrameRecognizerManager::RemoveRecognizerWithID(
|
|
uint32_t recognizer_id) {
|
|
if (recognizer_id >= m_recognizers.size())
|
|
return false;
|
|
auto found =
|
|
llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) {
|
|
return e.recognizer_id == recognizer_id;
|
|
});
|
|
if (found == m_recognizers.end())
|
|
return false;
|
|
m_recognizers.erase(found);
|
|
return true;
|
|
}
|
|
|
|
void StackFrameRecognizerManager::RemoveAllRecognizers() {
|
|
m_recognizers.clear();
|
|
}
|
|
|
|
StackFrameRecognizerSP
|
|
StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
|
|
const SymbolContext &symctx = frame->GetSymbolContext(
|
|
eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
|
|
ConstString function_name = symctx.GetFunctionName();
|
|
ModuleSP module_sp = symctx.module_sp;
|
|
if (!module_sp)
|
|
return StackFrameRecognizerSP();
|
|
ConstString module_name = module_sp->GetFileSpec().GetFilename();
|
|
Symbol *symbol = symctx.symbol;
|
|
if (!symbol)
|
|
return StackFrameRecognizerSP();
|
|
Address start_addr = symbol->GetAddress();
|
|
Address current_addr = frame->GetFrameCodeAddress();
|
|
|
|
for (auto entry : m_recognizers) {
|
|
if (entry.module)
|
|
if (entry.module != module_name)
|
|
continue;
|
|
|
|
if (entry.module_regexp)
|
|
if (!entry.module_regexp->Execute(module_name.GetStringRef()))
|
|
continue;
|
|
|
|
if (!entry.symbols.empty())
|
|
if (!llvm::is_contained(entry.symbols, function_name))
|
|
continue;
|
|
|
|
if (entry.symbol_regexp)
|
|
if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
|
|
continue;
|
|
|
|
if (entry.first_instruction_only)
|
|
if (start_addr != current_addr)
|
|
continue;
|
|
|
|
return entry.recognizer;
|
|
}
|
|
return StackFrameRecognizerSP();
|
|
}
|
|
|
|
RecognizedStackFrameSP
|
|
StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) {
|
|
auto recognizer = GetRecognizerForFrame(frame);
|
|
if (!recognizer)
|
|
return RecognizedStackFrameSP();
|
|
return recognizer->RecognizeFrame(frame);
|
|
}
|