[Lldb-commits] [lldb] [lldb] Add support for disabling frame recognizers (PR #109219)

Adrian Vogelsgesang via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 18 16:32:45 PDT 2024


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 <avogelsgesang at 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;



More information about the lldb-commits mailing list