Skip to content

[lldb] Add support for disabling frame recognizers #109219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions lldb/include/lldb/Target/StackFrameRecognizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,14 @@ class StackFrameRecognizerManager {
Mangled::NamePreference symbol_mangling,
bool first_instruction_only = true);

void ForEach(std::function<
void(uint32_t recognizer_id, std::string recognizer_name,
std::string module, llvm::ArrayRef<ConstString> symbols,
Mangled::NamePreference name_reference, bool regexp)> const
&callback);

void
ForEach(std::function<void(uint32_t recognizer_id, bool enabled,
std::string recognizer_name, std::string module,
llvm::ArrayRef<ConstString> symbols,
Mangled::NamePreference name_preference,
bool regexp)> const &callback);

bool SetEnabledForID(uint32_t recognizer_id, bool enabled);
bool RemoveRecognizerWithID(uint32_t recognizer_id);

void RemoveAllRecognizers();
Expand All @@ -155,6 +157,7 @@ class StackFrameRecognizerManager {
lldb::RegularExpressionSP symbol_regexp;
Mangled::NamePreference symbol_mangling;
bool first_instruction_only;
bool enabled;
};

std::deque<RegisteredEntry> m_recognizers;
Expand Down
147 changes: 105 additions & 42 deletions lldb/source/Commands/CommandObjectFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,10 +930,13 @@ class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
};

static void
PrintRecognizerDetails(Stream &strm, const std::string &name,
PrintRecognizerDetails(Stream &strm, const std::string &name, bool enabled,
const std::string &module,
llvm::ArrayRef<lldb_private::ConstString> symbols,
Mangled::NamePreference symbol_mangling, bool regexp) {
if (!enabled)
strm << "[disabled] ";

strm << name << ", ";

if (!module.empty())
Expand All @@ -957,70 +960,124 @@ PrintRecognizerDetails(Stream &strm, const std::string &name,
llvm::interleaveComma(symbols, strm);
}

class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
// Base class for commands which accept a single frame recognizer as an argument
class CommandObjectWithFrameRecognizerArg : public CommandObjectParsed {
public:
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "frame recognizer delete",
"Delete an existing frame recognizer by id.",
nullptr) {
CommandObjectWithFrameRecognizerArg(CommandInterpreter &interpreter,
const char *name,
const char *help = nullptr,
const char *syntax = nullptr,
uint32_t flags = 0)
: CommandObjectParsed(interpreter, name, help, syntax, flags) {
AddSimpleArgumentList(eArgTypeRecognizerID);
}

~CommandObjectFrameRecognizerDelete() override = default;

void
HandleArgumentCompletion(CompletionRequest &request,
OptionElementVector &opt_element_vector) override {
if (request.GetCursorIndex() != 0)
return;

GetTarget().GetFrameRecognizerManager().ForEach(
[&request](uint32_t rid, std::string rname, std::string module,
[&request](uint32_t rid, bool enabled, std::string rname,
std::string module,
llvm::ArrayRef<lldb_private::ConstString> symbols,
Mangled::NamePreference symbol_mangling, bool regexp) {
StreamString strm;
if (rname.empty())
rname = "(internal)";

PrintRecognizerDetails(strm, rname, module, symbols, symbol_mangling,
regexp);
PrintRecognizerDetails(strm, rname, enabled, module, symbols,
symbol_mangling, regexp);

request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
});
}

protected:
void DoExecute(Args &command, CommandReturnObject &result) override {
if (command.GetArgumentCount() == 0) {
if (!m_interpreter.Confirm(
"About to delete all frame recognizers, do you want to do that?",
true)) {
result.AppendMessage("Operation cancelled...");
return;
}
virtual void DoExecuteWithId(CommandReturnObject &result,
uint32_t recognizer_id) = 0;

GetTarget().GetFrameRecognizerManager().RemoveAllRecognizers();
result.SetStatus(eReturnStatusSuccessFinishResult);
void DoExecute(Args &command, CommandReturnObject &result) override {
uint32_t recognizer_id;
if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
command.GetArgumentAtIndex(0));
return;
}

if (command.GetArgumentCount() != 1) {
result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
m_cmd_name.c_str());
DoExecuteWithId(result, recognizer_id);
}
};

class CommandObjectFrameRecognizerEnable
: public CommandObjectWithFrameRecognizerArg {
public:
CommandObjectFrameRecognizerEnable(CommandInterpreter &interpreter)
: CommandObjectWithFrameRecognizerArg(
interpreter, "frame recognizer enable",
"Enable a frame recognizer by id.", nullptr) {
AddSimpleArgumentList(eArgTypeRecognizerID);
}

~CommandObjectFrameRecognizerEnable() override = default;

protected:
void DoExecuteWithId(CommandReturnObject &result,
uint32_t recognizer_id) override {
auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
if (!recognizer_mgr.SetEnabledForID(recognizer_id, true)) {
result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
recognizer_id);
return;
}
result.SetStatus(eReturnStatusSuccessFinishResult);
}
};

uint32_t recognizer_id;
if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
command.GetArgumentAtIndex(0));
class CommandObjectFrameRecognizerDisable
: public CommandObjectWithFrameRecognizerArg {
public:
CommandObjectFrameRecognizerDisable(CommandInterpreter &interpreter)
: CommandObjectWithFrameRecognizerArg(
interpreter, "frame recognizer disable",
"Disable a frame recognizer by id.", nullptr) {
AddSimpleArgumentList(eArgTypeRecognizerID);
}

~CommandObjectFrameRecognizerDisable() override = default;

protected:
void DoExecuteWithId(CommandReturnObject &result,
uint32_t recognizer_id) override {
auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
if (!recognizer_mgr.SetEnabledForID(recognizer_id, false)) {
result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
recognizer_id);
return;
}
result.SetStatus(eReturnStatusSuccessFinishResult);
}
};

if (!GetTarget().GetFrameRecognizerManager().RemoveRecognizerWithID(
recognizer_id)) {
result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
command.GetArgumentAtIndex(0));
class CommandObjectFrameRecognizerDelete
: public CommandObjectWithFrameRecognizerArg {
public:
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
: CommandObjectWithFrameRecognizerArg(
interpreter, "frame recognizer delete",
"Delete an existing frame recognizer by id.", nullptr) {
AddSimpleArgumentList(eArgTypeRecognizerID);
}

~CommandObjectFrameRecognizerDelete() override = default;

protected:
void DoExecuteWithId(CommandReturnObject &result,
uint32_t recognizer_id) override {
auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
if (!recognizer_mgr.RemoveRecognizerWithID(recognizer_id)) {
result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
recognizer_id);
return;
}
result.SetStatus(eReturnStatusSuccessFinishResult);
Expand All @@ -1041,7 +1098,7 @@ class CommandObjectFrameRecognizerList : public CommandObjectParsed {
bool any_printed = false;
GetTarget().GetFrameRecognizerManager().ForEach(
[&result,
&any_printed](uint32_t recognizer_id, std::string name,
&any_printed](uint32_t recognizer_id, bool enabled, std::string name,
std::string module, llvm::ArrayRef<ConstString> symbols,
Mangled::NamePreference symbol_mangling, bool regexp) {
Stream &stream = result.GetOutputStream();
Expand All @@ -1050,8 +1107,8 @@ class CommandObjectFrameRecognizerList : public CommandObjectParsed {
name = "(internal)";

stream << std::to_string(recognizer_id) << ": ";
PrintRecognizerDetails(stream, name, module, symbols, symbol_mangling,
regexp);
PrintRecognizerDetails(stream, name, enabled, module, symbols,
symbol_mangling, regexp);

stream.EOL();
stream.Flush();
Expand Down Expand Up @@ -1135,18 +1192,24 @@ class CommandObjectFrameRecognizer : public CommandObjectMultiword {
interpreter, "frame recognizer",
"Commands for editing and viewing frame recognizers.",
"frame recognizer [<sub-command-options>] ") {
LoadSubCommand("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
interpreter)));
LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
interpreter)));
LoadSubCommand("add", CommandObjectSP(new CommandObjectFrameRecognizerAdd(
interpreter)));
LoadSubCommand(
"clear",
CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
"enable",
CommandObjectSP(new CommandObjectFrameRecognizerEnable(interpreter)));
LoadSubCommand(
"disable",
CommandObjectSP(new CommandObjectFrameRecognizerDisable(interpreter)));
LoadSubCommand(
"delete",
CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
interpreter)));
LoadSubCommand("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
interpreter)));
LoadSubCommand(
"clear",
CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
}

~CommandObjectFrameRecognizer() override = default;
Expand Down
38 changes: 26 additions & 12 deletions lldb/source/Target/StackFrameRecognizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void StackFrameRecognizerManager::AddRecognizer(
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
module, RegularExpressionSP(), symbols,
RegularExpressionSP(), symbol_mangling,
first_instruction_only});
first_instruction_only, true});
BumpGeneration();
}

Expand All @@ -77,14 +77,15 @@ void StackFrameRecognizerManager::AddRecognizer(
bool first_instruction_only) {
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
ConstString(), module, std::vector<ConstString>(),
symbol, symbol_mangling, first_instruction_only});
symbol, symbol_mangling, first_instruction_only,
true});
BumpGeneration();
}

void StackFrameRecognizerManager::ForEach(
const std::function<
void(uint32_t, std::string, std::string, llvm::ArrayRef<ConstString>,
Mangled::NamePreference name_reference, bool)> &callback) {
const std::function<void(
uint32_t, bool, std::string, std::string, llvm::ArrayRef<ConstString>,
Mangled::NamePreference name_preference, bool)> &callback) {
for (auto entry : m_recognizers) {
if (entry.is_regexp) {
std::string module_name;
Expand All @@ -95,22 +96,32 @@ void StackFrameRecognizerManager::ForEach(
if (entry.symbol_regexp)
symbol_name = entry.symbol_regexp->GetText().str();

callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
llvm::ArrayRef(ConstString(symbol_name)), entry.symbol_mangling,
true);

callback(entry.recognizer_id, entry.enabled, entry.recognizer->GetName(),
module_name, llvm::ArrayRef(ConstString(symbol_name)),
entry.symbol_mangling, true);
} else {
callback(entry.recognizer_id, entry.recognizer->GetName(),
callback(entry.recognizer_id, entry.enabled, entry.recognizer->GetName(),
entry.module.GetCString(), entry.symbols, entry.symbol_mangling,
false);
}
}
}

bool StackFrameRecognizerManager::SetEnabledForID(uint32_t recognizer_id,
bool enabled) {
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;
found->enabled = enabled;
BumpGeneration();
return true;
}

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;
Expand Down Expand Up @@ -142,6 +153,9 @@ StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
Address current_addr = frame->GetFrameCodeAddress();

for (auto entry : m_recognizers) {
if (!entry.enabled)
continue;

if (entry.module)
if (entry.module != module_name)
continue;
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/commands/frame/recognizer/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
OBJC_SOURCES := main.m
C_SOURCES := main.c
CFLAGS_EXTRAS := -g0 # No debug info.
MAKE_DSYM := NO

Expand Down
Loading
Loading