https://github.com/vogelsgesang created https://github.com/llvm/llvm-project/pull/109219
Sometimes you only want to temporarily disable a frame recognizer instead of deleting it. In particular, when dealing with one of the builtin frame recognizers, which cannot be restored after deletion. >From c471c2fe615082fb9f9c5f39466bd47ec5b86bb0 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang <avogelsges...@salesforce.com> Date: Wed, 18 Sep 2024 22:34:30 +0000 Subject: [PATCH] [lldb] Add support for disabling frame recognizers Sometimes you only want to temporarily disable a frame recognizer instead of deleting it. In particular, when dealing with one of the builtin frame recognizers, which cannot be restored after deletion. --- .../lldb/Target/StackFrameRecognizer.h | 7 +- lldb/source/Commands/CommandObjectFrame.cpp | 144 +++++++++++++----- lldb/source/Target/StackFrameRecognizer.cpp | 29 +++- 3 files changed, 131 insertions(+), 49 deletions(-) diff --git a/lldb/include/lldb/Target/StackFrameRecognizer.h b/lldb/include/lldb/Target/StackFrameRecognizer.h index 617b1617d404a1..0deb4d46454784 100644 --- a/lldb/include/lldb/Target/StackFrameRecognizer.h +++ b/lldb/include/lldb/Target/StackFrameRecognizer.h @@ -125,11 +125,13 @@ class StackFrameRecognizerManager { 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, + void(uint32_t recognizer_id, bool enabled, + std::string recognizer_name, std::string module, + llvm::ArrayRef<ConstString> symbols, Mangled::NamePreference name_reference, bool regexp)> const &callback); + bool SetEnabledForID(uint32_t recognizer_id, bool enabled); bool RemoveRecognizerWithID(uint32_t recognizer_id); void RemoveAllRecognizers(); @@ -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; diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index d8091e8993fde1..86db334ddc677e 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -31,8 +31,10 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/Args.h" +#include <iostream> #include <memory> #include <optional> +#include <ostream> #include <string> using namespace lldb; @@ -930,10 +932,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()) @@ -957,53 +962,43 @@ PrintRecognizerDetails(Stream &strm, const std::string &name, llvm::interleaveComma(symbols, strm); } -class CommandObjectFrameRecognizerDelete : public CommandObjectParsed { -public: - CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "frame recognizer delete", - "Delete an existing frame recognizer by id.", - nullptr) { - AddSimpleArgumentList(eArgTypeRecognizerID); - } - - ~CommandObjectFrameRecognizerDelete() override = default; +// Base class for commands which accept a single frame recognizer as an argument +class CommandObjectWithFrameRecognizerArg : public CommandObjectParsed { + public: + 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); + } void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { + std::cerr << request.GetCursorIndex() << std::endl; 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; - } - - GetTarget().GetFrameRecognizerManager().RemoveAllRecognizers(); - result.SetStatus(eReturnStatusSuccessFinishResult); - return; - } + virtual void DoExecuteWithId(CommandReturnObject &result, uint32_t recognizer_id) = 0; + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() != 1) { result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n", m_cmd_name.c_str()); @@ -1017,10 +1012,73 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed { return; } - if (!GetTarget().GetFrameRecognizerManager().RemoveRecognizerWithID( - recognizer_id)) { - result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n", - command.GetArgumentAtIndex(0)); + 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); + } +}; + +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); + } +}; + +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); @@ -1041,7 +1099,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(); @@ -1050,7 +1108,7 @@ class CommandObjectFrameRecognizerList : public CommandObjectParsed { name = "(internal)"; stream << std::to_string(recognizer_id) << ": "; - PrintRecognizerDetails(stream, name, module, symbols, symbol_mangling, + PrintRecognizerDetails(stream, name, enabled, module, symbols, symbol_mangling, regexp); stream.EOL(); @@ -1135,18 +1193,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; diff --git a/lldb/source/Target/StackFrameRecognizer.cpp b/lldb/source/Target/StackFrameRecognizer.cpp index fa24253320a3f2..4592702942f8c9 100644 --- a/lldb/source/Target/StackFrameRecognizer.cpp +++ b/lldb/source/Target/StackFrameRecognizer.cpp @@ -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(); } @@ -77,13 +77,14 @@ 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>, + void(uint32_t, bool, std::string, std::string, llvm::ArrayRef<ConstString>, Mangled::NamePreference name_reference, bool)> &callback) { for (auto entry : m_recognizers) { if (entry.is_regexp) { @@ -95,22 +96,33 @@ void StackFrameRecognizerManager::ForEach( if (entry.symbol_regexp) symbol_name = entry.symbol_regexp->GetText().str(); - callback(entry.recognizer_id, entry.recognizer->GetName(), module_name, + 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; @@ -142,6 +154,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; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits