[Lldb-commits] [lldb] 1b7c9ea - [lldb] Store StackFrameRecognizers in the target instead of a global list

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Fri Jul 17 00:26:53 PDT 2020


Author: Raphael Isemann
Date: 2020-07-17T09:26:27+02:00
New Revision: 1b7c9eae6dcad09c264e29e41a69bed0d34c2f5f

URL: https://github.com/llvm/llvm-project/commit/1b7c9eae6dcad09c264e29e41a69bed0d34c2f5f
DIFF: https://github.com/llvm/llvm-project/commit/1b7c9eae6dcad09c264e29e41a69bed0d34c2f5f.diff

LOG: [lldb] Store StackFrameRecognizers in the target instead of a global list

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

Added: 
    

Modified: 
    lldb/include/lldb/Target/StackFrameRecognizer.h
    lldb/include/lldb/Target/Target.h
    lldb/include/lldb/lldb-forward.h
    lldb/source/Commands/CommandObjectFrame.cpp
    lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/source/Target/AssertFrameRecognizer.cpp
    lldb/source/Target/StackFrame.cpp
    lldb/source/Target/StackFrameRecognizer.cpp
    lldb/source/Target/Target.cpp
    lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
    lldb/unittests/Target/StackFrameRecognizerTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Target/StackFrameRecognizer.h b/lldb/include/lldb/Target/StackFrameRecognizer.h
index 9c9105ac04e4..38b21e7c9856 100644
--- a/lldb/include/lldb/Target/StackFrameRecognizer.h
+++ b/lldb/include/lldb/Target/StackFrameRecognizer.h
@@ -17,6 +17,8 @@
 #include "lldb/lldb-private-forward.h"
 #include "lldb/lldb-public.h"
 
+#include <vector>
+
 namespace lldb_private {
 
 /// \class RecognizedStackFrame
@@ -95,37 +97,45 @@ class ScriptedStackFrameRecognizer : public StackFrameRecognizer {
   operator=(const ScriptedStackFrameRecognizer &) = delete;
 };
 
-/// \class StackFrameRecognizerManager
-///
-/// Static class that provides a registry of known stack frame recognizers.
-/// Has static methods to add, enumerate, remove, query and invoke recognizers.
-
+/// Class that provides a registry of known stack frame recognizers.
 class StackFrameRecognizerManager {
 public:
-  static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
-                            ConstString module,
-                            llvm::ArrayRef<ConstString> symbols,
-                            bool first_instruction_only = true);
+  void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
+                     ConstString module, llvm::ArrayRef<ConstString> symbols,
+                     bool first_instruction_only = true);
+
+  void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
+                     lldb::RegularExpressionSP module,
+                     lldb::RegularExpressionSP symbol,
+                     bool first_instruction_only = true);
 
-  static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
-                            lldb::RegularExpressionSP module,
-                            lldb::RegularExpressionSP symbol,
-                            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,
+                    bool regexp)> const &callback);
 
-  static void
-  ForEach(std::function<void(uint32_t recognizer_id,
-                             std::string recognizer_name, std::string module,
-                             llvm::ArrayRef<ConstString> symbols,
-                             bool regexp)> const &callback);
+  bool RemoveRecognizerWithID(uint32_t recognizer_id);
 
-  static bool RemoveRecognizerWithID(uint32_t recognizer_id);
+  void RemoveAllRecognizers();
 
-  static void RemoveAllRecognizers();
+  lldb::StackFrameRecognizerSP GetRecognizerForFrame(lldb::StackFrameSP frame);
 
-  static lldb::StackFrameRecognizerSP GetRecognizerForFrame(
-      lldb::StackFrameSP frame);
+  lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame);
+
+private:
+  struct RegisteredEntry {
+    uint32_t recognizer_id;
+    bool deleted;
+    lldb::StackFrameRecognizerSP recognizer;
+    bool is_regexp;
+    ConstString module;
+    lldb::RegularExpressionSP module_regexp;
+    std::vector<ConstString> symbols;
+    lldb::RegularExpressionSP symbol_regexp;
+    bool first_instruction_only;
+  };
 
-  static lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame);
+  std::deque<RegisteredEntry> m_recognizers;
 };
 
 /// \class ValueObjectRecognizerSynthesizedValue

diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 280ce6359c72..c12c68d292b8 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1251,6 +1251,10 @@ class Target : public std::enable_shared_from_this<Target>,
 
   void SetREPL(lldb::LanguageType language, lldb::REPLSP repl_sp);
 
+  StackFrameRecognizerManager &GetFrameRecognizerManager() {
+    return *m_frame_recognizer_manager_up;
+  }
+
 protected:
   /// Implementing of ModuleList::Notifier.
 
@@ -1325,6 +1329,8 @@ class Target : public std::enable_shared_from_this<Target>,
   bool m_suppress_stop_hooks;
   bool m_is_dummy_target;
   unsigned m_next_persistent_variable_index = 0;
+  /// Stores the frame recognizers of this target.
+  lldb::StackFrameRecognizerManagerUP m_frame_recognizer_manager_up;
 
   static void ImageSearchPathsChanged(const PathMappingList &path_list,
                                       void *baton);

diff  --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 4fd2a07dd616..478ed1a06443 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -402,6 +402,8 @@ typedef std::weak_ptr<lldb_private::StackFrame> StackFrameWP;
 typedef std::shared_ptr<lldb_private::StackFrameList> StackFrameListSP;
 typedef std::shared_ptr<lldb_private::StackFrameRecognizer>
     StackFrameRecognizerSP;
+typedef std::unique_ptr<lldb_private::StackFrameRecognizerManager>
+    StackFrameRecognizerManagerUP;
 typedef std::shared_ptr<lldb_private::StopInfo> StopInfoSP;
 typedef std::shared_ptr<lldb_private::StoppointLocation> StoppointLocationSP;
 typedef std::shared_ptr<lldb_private::Stream> StreamSP;

diff  --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index 6ebad9b5c488..b42020d76751 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -898,12 +898,14 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
         RegularExpressionSP(new RegularExpression(m_options.m_module));
     auto func =
         RegularExpressionSP(new RegularExpression(m_options.m_symbols.front()));
-    StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);
+    GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
+        recognizer_sp, module, func);
   } else {
     auto module = ConstString(m_options.m_module);
     std::vector<ConstString> symbols(m_options.m_symbols.begin(),
                                      m_options.m_symbols.end());
-    StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, symbols);
+    GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
+        recognizer_sp, module, symbols);
   }
 #endif
 
@@ -921,7 +923,9 @@ class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    StackFrameRecognizerManager::RemoveAllRecognizers();
+    GetSelectedOrDummyTarget()
+        .GetFrameRecognizerManager()
+        .RemoveAllRecognizers();
     result.SetStatus(eReturnStatusSuccessFinishResult);
     return result.Succeeded();
   }
@@ -941,7 +945,7 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
     if (request.GetCursorIndex() != 0)
       return;
 
-    StackFrameRecognizerManager::ForEach(
+    GetSelectedOrDummyTarget().GetFrameRecognizerManager().ForEach(
         [&request](uint32_t rid, std::string rname, std::string module,
                    llvm::ArrayRef<lldb_private::ConstString> symbols,
                    bool regexp) {
@@ -973,7 +977,9 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
         return false;
       }
 
-      StackFrameRecognizerManager::RemoveAllRecognizers();
+      GetSelectedOrDummyTarget()
+          .GetFrameRecognizerManager()
+          .RemoveAllRecognizers();
       result.SetStatus(eReturnStatusSuccessFinishResult);
       return result.Succeeded();
     }
@@ -993,7 +999,9 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
       return false;
     }
 
-    StackFrameRecognizerManager::RemoveRecognizerWithID(recognizer_id);
+    GetSelectedOrDummyTarget()
+        .GetFrameRecognizerManager()
+        .RemoveRecognizerWithID(recognizer_id);
     result.SetStatus(eReturnStatusSuccessFinishResult);
     return result.Succeeded();
   }
@@ -1011,7 +1019,7 @@ class CommandObjectFrameRecognizerList : public CommandObjectParsed {
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
     bool any_printed = false;
-    StackFrameRecognizerManager::ForEach(
+    GetSelectedOrDummyTarget().GetFrameRecognizerManager().ForEach(
         [&result, &any_printed](
             uint32_t recognizer_id, std::string name, std::string module,
             llvm::ArrayRef<ConstString> symbols, bool regexp) {
@@ -1106,8 +1114,9 @@ class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
       return false;
     }
 
-    auto recognizer =
-        StackFrameRecognizerManager::GetRecognizerForFrame(frame_sp);
+    auto recognizer = GetSelectedOrDummyTarget()
+                          .GetFrameRecognizerManager()
+                          .GetRecognizerForFrame(frame_sp);
 
     Stream &output_stream = result.GetOutputStream();
     output_stream.Printf("frame %d ", frame_index);

diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index ac9a09394021..ae77dfeb4ad4 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -407,7 +407,7 @@ ExtractRuntimeGlobalSymbol(Process *process, ConstString name,
   }
 }
 
-static void RegisterObjCExceptionRecognizer();
+static void RegisterObjCExceptionRecognizer(Process *process);
 
 AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
                                        const ModuleSP &objc_module_sp)
@@ -429,7 +429,7 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
   m_has_object_getClass =
       (objc_module_sp->FindFirstSymbolWithNameAndType(
            g_gdb_object_getClass, eSymbolTypeCode) != nullptr);
-  RegisterObjCExceptionRecognizer();
+  RegisterObjCExceptionRecognizer(process);
 }
 
 bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
@@ -2711,16 +2711,14 @@ class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer {
   };
 };
 
-static void RegisterObjCExceptionRecognizer() {
-  static llvm::once_flag g_once_flag;
-  llvm::call_once(g_once_flag, []() {
-    FileSpec module;
-    ConstString function;
-    std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation();
-    std::vector<ConstString> symbols = {function};
-    StackFrameRecognizerManager::AddRecognizer(
-        StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
-        module.GetFilename(), symbols,
-        /*first_instruction_only*/ true);
-  });
+static void RegisterObjCExceptionRecognizer(Process *process) {
+  FileSpec module;
+  ConstString function;
+  std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation();
+  std::vector<ConstString> symbols = {function};
+
+  process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
+      StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
+      module.GetFilename(), symbols,
+      /*first_instruction_only*/ true);
 }

diff  --git a/lldb/source/Target/AssertFrameRecognizer.cpp b/lldb/source/Target/AssertFrameRecognizer.cpp
index d87459ac2fdd..fe5fa3a362f8 100644
--- a/lldb/source/Target/AssertFrameRecognizer.cpp
+++ b/lldb/source/Target/AssertFrameRecognizer.cpp
@@ -86,20 +86,17 @@ bool GetAssertLocation(llvm::Triple::OSType os, SymbolLocation &location) {
 }
 
 void RegisterAssertFrameRecognizer(Process *process) {
-  static llvm::once_flag g_once_flag;
-  llvm::call_once(g_once_flag, [process]() {
-    Target &target = process->GetTarget();
-    llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
-    SymbolLocation location;
-
-    if (!GetAbortLocation(os, location))
-      return;
-
-    StackFrameRecognizerManager::AddRecognizer(
-        StackFrameRecognizerSP(new AssertFrameRecognizer()),
-        location.module_spec.GetFilename(), location.symbols,
-        /*first_instruction_only*/ false);
-  });
+  Target &target = process->GetTarget();
+  llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
+  SymbolLocation location;
+
+  if (!GetAbortLocation(os, location))
+    return;
+
+  target.GetFrameRecognizerManager().AddRecognizer(
+      StackFrameRecognizerSP(new AssertFrameRecognizer()),
+      location.module_spec.GetFilename(), location.symbols,
+      /*first_instruction_only*/ false);
 }
 
 } // namespace lldb_private

diff  --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 3d6cc5dc90b3..098aed9cd812 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -1956,8 +1956,11 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
 
 RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {
   if (!m_recognized_frame_sp) {
-    m_recognized_frame_sp =
-        StackFrameRecognizerManager::RecognizeFrame(CalculateStackFrame());
+    m_recognized_frame_sp = GetThread()
+                                ->GetProcess()
+                                ->GetTarget()
+                                .GetFrameRecognizerManager()
+                                .RecognizeFrame(CalculateStackFrame());
   }
   return m_recognized_frame_sp;
 }

diff  --git a/lldb/source/Target/StackFrameRecognizer.cpp b/lldb/source/Target/StackFrameRecognizer.cpp
index 7dc6e9d1e490..6fa09a387ad2 100644
--- a/lldb/source/Target/StackFrameRecognizer.cpp
+++ b/lldb/source/Target/StackFrameRecognizer.cpp
@@ -6,12 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <vector>
+#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/Target/StackFrameRecognizer.h"
 #include "lldb/Utility/RegularExpression.h"
 
 using namespace lldb;
@@ -48,158 +47,106 @@ ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
       new ScriptedRecognizedStackFrame(args_synthesized));
 }
 
-class StackFrameRecognizerManagerImpl {
-public:
-  void 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 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 ForEach(std::function<
-               void(uint32_t recognized_id, std::string recognizer_name,
-                    std::string module, llvm::ArrayRef<ConstString> symbols,
-                    bool regexp)> const &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 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::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 RemoveAllRecognizers() {
-    m_recognizers.clear();
-  }
+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});
+}
 
-  StackFrameRecognizerSP 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;
+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)
-        if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue;
-
-      if (!entry.symbols.empty())
-        if (!llvm::is_contained(entry.symbols, function_name))
-          continue;
-
+        module_name = entry.module_regexp->GetText().str();
       if (entry.symbol_regexp)
-        if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
-          continue;
+        symbol_name = entry.symbol_regexp->GetText().str();
 
-      if (entry.first_instruction_only)
-        if (start_addr != current_addr) continue;
+      callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
+               llvm::makeArrayRef(ConstString(symbol_name)), true);
 
-      return entry.recognizer;
+    } else {
+      callback(entry.recognizer_id, entry.recognizer->GetName(),
+               entry.module.GetCString(), entry.symbols, false);
     }
-    return StackFrameRecognizerSP();
   }
-
-  RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) {
-    auto recognizer = GetRecognizerForFrame(frame);
-    if (!recognizer) return RecognizedStackFrameSP();
-    return recognizer->RecognizeFrame(frame);
-  }
-
- private:
-  struct RegisteredEntry {
-    uint32_t recognizer_id;
-    bool deleted;
-    StackFrameRecognizerSP recognizer;
-    bool is_regexp;
-    ConstString module;
-    RegularExpressionSP module_regexp;
-    std::vector<ConstString> symbols;
-    RegularExpressionSP symbol_regexp;
-    bool first_instruction_only;
-  };
-
-  std::deque<RegisteredEntry> m_recognizers;
-};
-
-StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() {
-  static StackFrameRecognizerManagerImpl instance =
-      StackFrameRecognizerManagerImpl();
-  return instance;
 }
 
-void StackFrameRecognizerManager::AddRecognizer(
-    StackFrameRecognizerSP recognizer, ConstString module,
-    llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
-  GetStackFrameRecognizerManagerImpl().AddRecognizer(
-      recognizer, module, symbols, first_instruction_only);
+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::AddRecognizer(
-    StackFrameRecognizerSP recognizer, RegularExpressionSP module,
-    RegularExpressionSP symbol, bool first_instruction_only) {
-  GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
-                                                     first_instruction_only);
+void StackFrameRecognizerManager::RemoveAllRecognizers() {
+  m_recognizers.clear();
 }
 
-void StackFrameRecognizerManager::ForEach(
-    std::function<void(uint32_t recognized_id, std::string recognizer_name,
-                       std::string module, llvm::ArrayRef<ConstString> symbols,
-                       bool regexp)> const &callback) {
-  GetStackFrameRecognizerManagerImpl().ForEach(callback);
-}
+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();
 
-void StackFrameRecognizerManager::RemoveAllRecognizers() {
-  GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers();
-}
+  for (auto entry : m_recognizers) {
+    if (entry.deleted)
+      continue;
+    if (entry.module)
+      if (entry.module != module_name)
+        continue;
 
-bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) {
-  return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id);
-}
+    if (entry.module_regexp)
+      if (!entry.module_regexp->Execute(module_name.GetStringRef()))
+        continue;
 
-RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame(
-    StackFrameSP frame) {
-  return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame);
+    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();
 }
 
-StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame(
-    lldb::StackFrameSP frame) {
-  return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame);
+RecognizedStackFrameSP
+StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) {
+  auto recognizer = GetRecognizerForFrame(frame);
+  if (!recognizer)
+    return RecognizedStackFrameSP();
+  return recognizer->RecognizeFrame(frame);
 }

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index dad56376005c..364997f139b1 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -45,6 +45,7 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StackFrameRecognizer.h"
 #include "lldb/Target/SystemRuntime.h"
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/ThreadSpec.h"
@@ -94,6 +95,8 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
       m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
       m_valid(true), m_suppress_stop_hooks(false),
       m_is_dummy_target(is_dummy_target),
+      m_frame_recognizer_manager_up(
+          std::make_unique<StackFrameRecognizerManager>()),
       m_stats_storage(static_cast<int>(StatisticKind::StatisticMax))
 
 {
@@ -143,6 +146,9 @@ void Target::PrimeFromDummyTarget(Target *target) {
     BreakpointName *new_bp_name = new BreakpointName(*bp_name_entry.second);
     AddBreakpointName(new_bp_name);
   }
+
+  m_frame_recognizer_manager_up = std::make_unique<StackFrameRecognizerManager>(
+      *target->m_frame_recognizer_manager_up);
 }
 
 void Target::Dump(Stream *s, lldb::DescriptionLevel description_level) {

diff  --git a/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py b/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
index 218c7e85aae7..f807937f2f17 100644
--- a/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
+++ b/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
@@ -145,6 +145,50 @@ def test_frame_recognizer_multi_symbol(self):
         self.expect("frame recognizer info 0",
                     substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer'])
 
+    @skipUnlessDarwin
+    def test_frame_recognizer_target_specific(self):
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+
+        # Clear internal & plugins recognizers that get initialized at launch
+        self.runCmd("frame recognizer clear")
+
+        # Create a target.
+        target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "foo",
+                                                                 exe_name = exe)
+
+        self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py"))
+
+        # Check that this doesn't contain our own FrameRecognizer somehow.
+        self.expect("frame recognizer list",
+                    matching=False, substrs=['MyFrameRecognizer'])
+
+        # Add a frame recognizer in that target.
+        self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo -n bar")
+
+        self.expect("frame recognizer list",
+                    substrs=['recognizer.MyFrameRecognizer, module a.out, symbol foo, symbol bar'])
+
+        self.expect("frame recognizer info 0",
+                    substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer'])
+
+        # Create a second target. That one shouldn't have the frame recognizer.
+        target, process, thread, _ = lldbutil.run_to_name_breakpoint(self, "bar",
+                                                                 exe_name = exe)
+
+        self.expect("frame recognizer info 0",
+                    substrs=['frame 0 not recognized by any recognizer'])
+
+        # Add a frame recognizer to the new target.
+        self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n bar")
+
+        self.expect("frame recognizer list",
+                    substrs=['recognizer.MyFrameRecognizer, module a.out, symbol bar'])
+
+        # Now the new target should also recognize the frame.
+        self.expect("frame recognizer info 0",
+                    substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer'])
+
     @no_debug_info_test
     def test_frame_recognizer_delete_invalid_arg(self):
         self.expect("frame recognizer delete a", error=True,

diff  --git a/lldb/unittests/Target/StackFrameRecognizerTest.cpp b/lldb/unittests/Target/StackFrameRecognizerTest.cpp
index 067a56a19902..bf458b3b1414 100644
--- a/lldb/unittests/Target/StackFrameRecognizerTest.cpp
+++ b/lldb/unittests/Target/StackFrameRecognizerTest.cpp
@@ -51,18 +51,14 @@ class DummyStackFrameRecognizer : public StackFrameRecognizer {
   std::string GetName() override { return "Dummy StackFrame Recognizer"; }
 };
 
-void RegisterDummyStackFrameRecognizer() {
-  static llvm::once_flag g_once_flag;
+void RegisterDummyStackFrameRecognizer(StackFrameRecognizerManager &manager) {
+  RegularExpressionSP module_regex_sp = nullptr;
+  RegularExpressionSP symbol_regex_sp(new RegularExpression("boom"));
 
-  llvm::call_once(g_once_flag, []() {
-    RegularExpressionSP module_regex_sp = nullptr;
-    RegularExpressionSP symbol_regex_sp(new RegularExpression("boom"));
+  StackFrameRecognizerSP dummy_recognizer_sp(new DummyStackFrameRecognizer());
 
-    StackFrameRecognizerSP dummy_recognizer_sp(new DummyStackFrameRecognizer());
-
-    StackFrameRecognizerManager::AddRecognizer(
-        dummy_recognizer_sp, module_regex_sp, symbol_regex_sp, false);
-  });
+  manager.AddRecognizer(dummy_recognizer_sp, module_regex_sp, symbol_regex_sp,
+                        false);
 }
 
 } // namespace
@@ -71,13 +67,15 @@ TEST_F(StackFrameRecognizerTest, NullModuleRegex) {
   DebuggerSP debugger_sp = Debugger::CreateInstance();
   ASSERT_TRUE(debugger_sp);
 
-  RegisterDummyStackFrameRecognizer();
+  StackFrameRecognizerManager manager;
+
+  RegisterDummyStackFrameRecognizer(manager);
 
   bool any_printed = false;
-  StackFrameRecognizerManager::ForEach(
-      [&any_printed](uint32_t recognizer_id, std::string name,
-                     std::string function, llvm::ArrayRef<ConstString> symbols,
-                     bool regexp) { any_printed = true; });
+  manager.ForEach([&any_printed](uint32_t recognizer_id, std::string name,
+                                 std::string function,
+                                 llvm::ArrayRef<ConstString> symbols,
+                                 bool regexp) { any_printed = true; });
 
   EXPECT_TRUE(any_printed);
 }


        


More information about the lldb-commits mailing list