
Summary: Currently the frame recognizers are stored in a global list (the list in the StackFrameRecognizersManagerImpl singleton to be precise). All commands and plugins that modify the list are just modifying that global list of recognizers which is shared by all Target and Debugger instances. This is clearly against the idea of LLDB being usable as a library and it also leads to some very obscure errors as now multiple tests are sharing the used frame recognizers. For example D83400 is currently failing as it reorders some test_ functions which permanently changes the frame recognizers of all debuggers/targets. As all frame recognizers are also initialized in a 'once' guard, it's also impossible to every restore back the original frame recognizers once they are deleted in a process. This patch just moves the frame recognizers into the current target. This seems the way everyone assumes the system works as for example the assert frame recognizers is using the current target to find the function/so-name to look for (which only works if the recognizers are stored in the target). Reviewers: jingham, mib Reviewed By: jingham, mib Subscribers: MrHate, JDevlieghere Differential Revision: https://reviews.llvm.org/D83757
153 lines
5.1 KiB
C++
153 lines
5.1 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(), false, 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(), false, 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;
|
|
if (m_recognizers[recognizer_id].deleted)
|
|
return false;
|
|
m_recognizers[recognizer_id].deleted = true;
|
|
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.deleted)
|
|
continue;
|
|
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);
|
|
}
|