[Lldb-commits] [lldb] [lldb] Add frame recognizers for libc++ `std::invoke` (PR #105695)
Adrian Vogelsgesang via lldb-commits
lldb-commits at lists.llvm.org
Sun Aug 25 15:27:48 PDT 2024
https://github.com/vogelsgesang updated https://github.com/llvm/llvm-project/pull/105695
>From 19b4370c240cfcf4a57a5c38a64c8ba933d8102c Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Thu, 22 Aug 2024 10:50:13 +0000
Subject: [PATCH 1/4] [lldb-dap] Add frame recognizers for libc++ `std::invoke`
With this commit, we also hide the implementation details of
`std::invoke`. To do so, the `LibCXXFrameRecognizer` got a couple more
regular expressions.
The regular expression passed into the `AddRecognizer` became
problematic, as it was evaluated on the demangled name. Those names also
included result types for C++ symbols. For `std::__invoke` the return
type is a huge `decltype(...)`, making the regular expresison really
hard to write.
Instead, I added support for `AddRecognizer` to match on the demangled
names without result type and argument types.
By hiding the implementation details of `invoke`, also the back traces
for `std::function` become even nicer, because `std::function` is using
`__invoke` internally.
---
.../lldb/Target/StackFrameRecognizer.h | 8 +++-
lldb/source/Commands/Options.td | 2 +-
.../CPlusPlus/CPPLanguageRuntime.cpp | 48 ++++++++++++++-----
lldb/source/Target/StackFrameRecognizer.cpp | 41 ++++++++++++++--
.../TestStdFunctionRecognizer.py | 21 +++++++-
.../lang/cpp/std-invoke-recognizer/Makefile | 5 ++
.../TestStdInvokeRecognizer.py | 31 ++++++++++++
.../lang/cpp/std-invoke-recognizer/main.cpp | 40 ++++++++++++++++
8 files changed, 175 insertions(+), 21 deletions(-)
create mode 100644 lldb/test/API/lang/cpp/std-invoke-recognizer/Makefile
create mode 100644 lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py
create mode 100644 lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp
diff --git a/lldb/include/lldb/Target/StackFrameRecognizer.h b/lldb/include/lldb/Target/StackFrameRecognizer.h
index 2f5c5caa6a4561..fe25dbbde745d1 100644
--- a/lldb/include/lldb/Target/StackFrameRecognizer.h
+++ b/lldb/include/lldb/Target/StackFrameRecognizer.h
@@ -107,12 +107,14 @@ class StackFrameRecognizerManager {
public:
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
ConstString module, llvm::ArrayRef<ConstString> symbols,
- bool first_instruction_only = true);
+ bool first_instruction_only = true,
+ Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled);
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
lldb::RegularExpressionSP module,
lldb::RegularExpressionSP symbol,
- bool first_instruction_only = true);
+ bool first_instruction_only = true,
+ Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled);
void ForEach(std::function<
void(uint32_t recognizer_id, std::string recognizer_name,
@@ -143,10 +145,12 @@ class StackFrameRecognizerManager {
std::vector<ConstString> symbols;
lldb::RegularExpressionSP symbol_regexp;
bool first_instruction_only;
+ Mangled::NamePreference mangling_preference;
};
std::deque<RegisteredEntry> m_recognizers;
uint16_t m_generation = 0;
+ std::unordered_set<Mangled::NamePreference> m_used_manglings;
};
/// \class ValueObjectRecognizerSynthesizedValue
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index 9c4dbed6939ba9..df906e9d7c808f 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -1049,7 +1049,7 @@ let Command = "thread backtrace" in {
def thread_backtrace_extended : Option<"extended", "e">, Group<1>,
Arg<"Boolean">, Desc<"Show the extended backtrace, if available">;
def thread_backtrace_unfiltered : Option<"unfiltered", "u">, Group<1>,
- Desc<"Filter out frames according to installed frame recognizers">;
+ Desc<"Do not filter out frames according to installed frame recognizers">;
}
let Command = "thread step scope" in {
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index c60200ab186d09..3665e1a4c77e55 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include <cstring>
+#include <iostream>
#include <memory>
@@ -44,7 +45,7 @@ char CPPLanguageRuntime::ID = 0;
/// A frame recognizer that is installed to hide libc++ implementation
/// details from the backtrace.
class LibCXXFrameRecognizer : public StackFrameRecognizer {
- RegularExpression m_hidden_function_regex;
+ std::array<RegularExpression, 3> m_hidden_regex;
RecognizedStackFrameSP m_hidden_frame;
struct LibCXXHiddenFrame : public RecognizedStackFrame {
@@ -53,10 +54,32 @@ class LibCXXFrameRecognizer : public StackFrameRecognizer {
public:
LibCXXFrameRecognizer()
- : m_hidden_function_regex(
- R"(^std::__1::(__function.*::operator\(\)|__invoke))"
- R"((\[.*\])?)" // ABI tag.
- R"(( const)?$)"), // const.
+ : m_hidden_regex{
+ // internal implementation details of std::function
+ // std::__1::__function::__alloc_func<void (*)(), std::__1::allocator<void (*)()>, void ()>::operator()[abi:ne200000]
+ // std::__1::__function::__func<void (*)(), std::__1::allocator<void (*)()>, void ()>::operator()
+ // std::__1::__function::__value_func<void ()>::operator()[abi:ne200000]() const
+ RegularExpression{""
+ R"(^std::__[0-9]*::)" // Namespace.
+ R"(__function::.*::operator\(\))"
+ R"((\[.*\])?)" // ABI tag.
+ R"(( const)?$)"}, // const.
+ // internal implementation details of std::invoke
+ // std::__1::__invoke[abi:ne200000]<void (*&)()>
+ RegularExpression{
+ R"(^std::__[0-9]*::)" // Namespace.
+ R"(__invoke)"
+ R"((\[.*\])?)" // ABI tag.
+ R"(<.*>)"}, // template argument.
+ // internal implementation details of std::invoke
+ // std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ne200000]<void (*&)()>
+ RegularExpression{
+ R"(^std::__[0-9]*::)" // Namespace.
+ R"(__invoke_void_return_wrapper<.*>::__call)"
+ R"((\[.*\])?)" // ABI tag.
+ R"(<.*>)"} // template argument.
+
+ },
m_hidden_frame(new LibCXXHiddenFrame()) {}
std::string GetName() override { return "libc++ frame recognizer"; }
@@ -69,8 +92,9 @@ class LibCXXFrameRecognizer : public StackFrameRecognizer {
if (!sc.function)
return {};
- if (m_hidden_function_regex.Execute(sc.function->GetNameNoArguments()))
- return m_hidden_frame;
+ for (RegularExpression &r : m_hidden_regex)
+ if (r.Execute(sc.function->GetNameNoArguments()))
+ return m_hidden_frame;
return {};
}
@@ -81,8 +105,9 @@ CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
if (process)
process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {},
- std::make_shared<RegularExpression>("^std::__1::"),
- /*first_instruction_only*/ false);
+ std::make_shared<RegularExpression>("std::__[0-9]*::"),
+ /*first_instruction_only=*/ false,
+ /*mangling_preference=*/ Mangled::ePreferDemangledWithoutArguments);
}
bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
@@ -108,8 +133,7 @@ bool contains_lambda_identifier(llvm::StringRef &str_ref) {
CPPLanguageRuntime::LibCppStdFunctionCallableInfo
line_entry_helper(Target &target, const SymbolContext &sc, Symbol *symbol,
- llvm::StringRef first_template_param_sref,
- bool has_invoke) {
+ llvm::StringRef first_template_param_sref, bool has_invoke) {
CPPLanguageRuntime::LibCppStdFunctionCallableInfo optional_info;
@@ -190,7 +214,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
ValueObjectSP sub_member_f_(member_f_->GetChildMemberWithName("__f_"));
if (sub_member_f_)
- member_f_ = sub_member_f_;
+ member_f_ = sub_member_f_;
}
if (!member_f_)
diff --git a/lldb/source/Target/StackFrameRecognizer.cpp b/lldb/source/Target/StackFrameRecognizer.cpp
index 44411afc65dda9..37901a2ea526a8 100644
--- a/lldb/source/Target/StackFrameRecognizer.cpp
+++ b/lldb/source/Target/StackFrameRecognizer.cpp
@@ -62,19 +62,24 @@ void StackFrameRecognizerManager::BumpGeneration() {
void StackFrameRecognizerManager::AddRecognizer(
StackFrameRecognizerSP recognizer, ConstString module,
- llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
+ llvm::ArrayRef<ConstString> symbols, bool first_instruction_only,
+ Mangled::NamePreference mangling_preference) {
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
module, RegularExpressionSP(), symbols,
RegularExpressionSP(), first_instruction_only});
+ m_used_manglings.insert(mangling_preference);
BumpGeneration();
}
void StackFrameRecognizerManager::AddRecognizer(
StackFrameRecognizerSP recognizer, RegularExpressionSP module,
- RegularExpressionSP symbol, bool first_instruction_only) {
+ RegularExpressionSP symbol, bool first_instruction_only,
+ Mangled::NamePreference mangling_preference) {
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
ConstString(), module, std::vector<ConstString>(),
- symbol, first_instruction_only});
+ symbol, first_instruction_only,
+ mangling_preference});
+ m_used_manglings.insert(mangling_preference);
BumpGeneration();
}
@@ -119,13 +124,30 @@ bool StackFrameRecognizerManager::RemoveRecognizerWithID(
void StackFrameRecognizerManager::RemoveAllRecognizers() {
BumpGeneration();
m_recognizers.clear();
+ m_used_manglings.clear();
}
StackFrameRecognizerSP
StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
const SymbolContext &symctx = frame->GetSymbolContext(
eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
- ConstString function_name = symctx.GetFunctionName();
+ ConstString function_name_mangled;
+ ConstString function_name_demangled;
+ ConstString function_name_noargs;
+ for (Mangled::NamePreference m : m_used_manglings) {
+ switch (m) {
+ case Mangled::ePreferMangled:
+ function_name_mangled = symctx.GetFunctionName(m);
+ break;
+ case Mangled::ePreferDemangled:
+ function_name_demangled = symctx.GetFunctionName(m);
+ break;
+ case Mangled::ePreferDemangledWithoutArguments:
+ function_name_noargs = symctx.GetFunctionName(m);
+ break;
+ }
+ }
+
ModuleSP module_sp = symctx.module_sp;
if (!module_sp)
return StackFrameRecognizerSP();
@@ -145,6 +167,17 @@ StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
if (!entry.module_regexp->Execute(module_name.GetStringRef()))
continue;
+ ConstString function_name = [&]() {
+ switch (entry.mangling_preference) {
+ case Mangled::ePreferMangled:
+ return function_name_mangled;
+ case Mangled::ePreferDemangled:
+ return function_name_demangled;
+ case Mangled::ePreferDemangledWithoutArguments:
+ return function_name_noargs;
+ }
+ }();
+
if (!entry.symbols.empty())
if (!llvm::is_contained(entry.symbols, function_name))
continue;
diff --git a/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py b/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py
index 30fe3ecb1e4bf4..28004194dee07c 100644
--- a/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py
+++ b/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py
@@ -7,6 +7,23 @@
class LibCxxStdFunctionRecognizerTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
+ @add_test_categories(["libc++"])
+ def test_frame_recognizer(self):
+ """Test that std::function all implementation details are hidden in SBFrame"""
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ self.assertIn("foo", thread.GetFrameAtIndex(0).GetFunctionName())
+ # Skip all hidden frames
+ frame_id = 1
+ while frame_id < thread.GetNumFrames() and thread.GetFrameAtIndex(frame_id).IsHidden():
+ frame_id = frame_id + 1
+ # Expect `std::function<...>::operator()` to be the direct parent of `foo`
+ self.assertIn("::operator()", thread.GetFrameAtIndex(frame_id).GetFunctionName())
+ # And right above that, there should be the `main` frame
+ self.assertIn("main", thread.GetFrameAtIndex(frame_id + 1).GetFunctionName())
+
@add_test_categories(["libc++"])
def test_backtrace(self):
"""Test that std::function implementation details are hidden in bt"""
@@ -27,12 +44,12 @@ def test_backtrace(self):
self.expect(
"thread backtrace -u",
ordered=True,
- patterns=["frame.*foo", "frame.*std::__1::__function", "frame.*main"],
+ patterns=["frame.*foo", "frame.*std::__[0-9]*::__function", "frame.*main"],
)
self.expect(
"thread backtrace --unfiltered",
ordered=True,
- patterns=["frame.*foo", "frame.*std::__1::__function", "frame.*main"],
+ patterns=["frame.*foo", "frame.*std::__[0-9]*::__function", "frame.*main"],
)
@add_test_categories(["libc++"])
diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/Makefile b/lldb/test/API/lang/cpp/std-invoke-recognizer/Makefile
new file mode 100644
index 00000000000000..69014eb9c0f2eb
--- /dev/null
+++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/Makefile
@@ -0,0 +1,5 @@
+CXX_SOURCES := main.cpp
+USE_LIBCPP := 1
+CXXFLAGS_EXTRAS := -std=c++17
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py
new file mode 100644
index 00000000000000..ef75e1afd9cba5
--- /dev/null
+++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py
@@ -0,0 +1,31 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LibCxxStdFunctionRecognizerTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @add_test_categories(["libc++"])
+ def test_frame_recognizer(self):
+ """Test that implementation details details of `std::invoke`"""
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+
+ while process.GetState() != lldb.eStateExited:
+ self.assertTrue(any(f in thread.GetFrameAtIndex(0).GetFunctionName() for f in ["print_num", "add", "PrintAdder"]))
+ print(thread.GetFrameAtIndex(0).GetFunctionName())
+ # Skip all hidden frames
+ frame_id = 1
+ while frame_id < thread.GetNumFrames() and thread.GetFrameAtIndex(frame_id).IsHidden():
+ print(thread.GetFrameAtIndex(frame_id).GetFunctionName())
+ frame_id = frame_id + 1
+ print(thread.GetFrameAtIndex(frame_id).GetFunctionName())
+ # Expect `std::invoke` to be the direct parent
+ self.assertIn("::invoke", thread.GetFrameAtIndex(frame_id).GetFunctionName())
+ # And right above that, there should be the `main` frame
+ self.assertIn("main", thread.GetFrameAtIndex(frame_id + 1).GetFunctionName())
+ process.Continue()
diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp b/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp
new file mode 100644
index 00000000000000..78497d2938fe8a
--- /dev/null
+++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp
@@ -0,0 +1,40 @@
+#include <functional>
+#include <iostream>
+
+void print_num(int i) {
+ // break here
+ std::cout << i << '\n';
+}
+
+int add(int i, int j) {
+ // break here
+ return i + j;
+}
+
+struct PrintAdder {
+ PrintAdder(int num) : num_(num) {}
+ void operator()(int i) const {
+ // break here
+ std::cout << i << '\n';
+ }
+ void print_add(int i) const {
+ // break here
+ std::cout << num_ + i << '\n';
+ }
+ int num_;
+};
+
+int main() {
+ // Invoke a void-returning function
+ std::invoke(print_num, -9);
+
+ // Invoke a non-void-returning function
+ std::cout << std::invoke(add, 1, 10) << '\n';
+
+ // Invoke a member function
+ const PrintAdder foo(314159);
+ std::invoke(&PrintAdder::print_add, foo, 1);
+
+ // Invoke a function object
+ std::invoke(PrintAdder(12), 18);
+}
>From c96bafa7bb55ad43f2a7d79dfbe3a9aec1d82132 Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Sun, 25 Aug 2024 23:24:57 +0200
Subject: [PATCH 2/4] Remove caching of demangled name in StackFrameRecognizer
They are already cached in `Mangled`
---
.../lldb/Target/StackFrameRecognizer.h | 1 -
lldb/source/Target/StackFrameRecognizer.cpp | 26 +++----------------
2 files changed, 3 insertions(+), 24 deletions(-)
diff --git a/lldb/include/lldb/Target/StackFrameRecognizer.h b/lldb/include/lldb/Target/StackFrameRecognizer.h
index fe25dbbde745d1..4ef0d1b2f56dfb 100644
--- a/lldb/include/lldb/Target/StackFrameRecognizer.h
+++ b/lldb/include/lldb/Target/StackFrameRecognizer.h
@@ -150,7 +150,6 @@ class StackFrameRecognizerManager {
std::deque<RegisteredEntry> m_recognizers;
uint16_t m_generation = 0;
- std::unordered_set<Mangled::NamePreference> m_used_manglings;
};
/// \class ValueObjectRecognizerSynthesizedValue
diff --git a/lldb/source/Target/StackFrameRecognizer.cpp b/lldb/source/Target/StackFrameRecognizer.cpp
index 37901a2ea526a8..7c0dfde993948f 100644
--- a/lldb/source/Target/StackFrameRecognizer.cpp
+++ b/lldb/source/Target/StackFrameRecognizer.cpp
@@ -67,7 +67,6 @@ void StackFrameRecognizerManager::AddRecognizer(
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
module, RegularExpressionSP(), symbols,
RegularExpressionSP(), first_instruction_only});
- m_used_manglings.insert(mangling_preference);
BumpGeneration();
}
@@ -79,7 +78,6 @@ void StackFrameRecognizerManager::AddRecognizer(
ConstString(), module, std::vector<ConstString>(),
symbol, first_instruction_only,
mangling_preference});
- m_used_manglings.insert(mangling_preference);
BumpGeneration();
}
@@ -124,30 +122,12 @@ bool StackFrameRecognizerManager::RemoveRecognizerWithID(
void StackFrameRecognizerManager::RemoveAllRecognizers() {
BumpGeneration();
m_recognizers.clear();
- m_used_manglings.clear();
}
StackFrameRecognizerSP
StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
const SymbolContext &symctx = frame->GetSymbolContext(
eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
- ConstString function_name_mangled;
- ConstString function_name_demangled;
- ConstString function_name_noargs;
- for (Mangled::NamePreference m : m_used_manglings) {
- switch (m) {
- case Mangled::ePreferMangled:
- function_name_mangled = symctx.GetFunctionName(m);
- break;
- case Mangled::ePreferDemangled:
- function_name_demangled = symctx.GetFunctionName(m);
- break;
- case Mangled::ePreferDemangledWithoutArguments:
- function_name_noargs = symctx.GetFunctionName(m);
- break;
- }
- }
-
ModuleSP module_sp = symctx.module_sp;
if (!module_sp)
return StackFrameRecognizerSP();
@@ -170,11 +150,11 @@ StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
ConstString function_name = [&]() {
switch (entry.mangling_preference) {
case Mangled::ePreferMangled:
- return function_name_mangled;
+ return symctx.GetFunctionName(entry.mangling_preference);
case Mangled::ePreferDemangled:
- return function_name_demangled;
+ return symctx.GetFunctionName(entry.mangling_preference);
case Mangled::ePreferDemangledWithoutArguments:
- return function_name_noargs;
+ return symctx.GetFunctionName(entry.mangling_preference);
}
}();
>From 32786ae0abb7c465dfab602b1d53da11dd1dc7a7 Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Sun, 25 Aug 2024 23:30:50 +0200
Subject: [PATCH 3/4] Fix regex
---
.../Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index 3665e1a4c77e55..bfd23ed9c3120e 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -105,7 +105,7 @@ CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
if (process)
process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {},
- std::make_shared<RegularExpression>("std::__[0-9]*::"),
+ std::make_shared<RegularExpression>("^std::__[0-9]*::"),
/*first_instruction_only=*/ false,
/*mangling_preference=*/ Mangled::ePreferDemangledWithoutArguments);
}
>From 4e3044b4f5b2b89edfee3318ce8c19bc083abc0b Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Mon, 26 Aug 2024 00:00:59 +0200
Subject: [PATCH 4/4] Copy additional content from adrian-prantl's commit
---
.../lldb/Target/StackFrameRecognizer.h | 21 +++++--
lldb/source/Commands/CommandObjectFrame.cpp | 58 ++++++++++++-------
.../CPlusPlus/CPPLanguageRuntime.cpp | 4 +-
lldb/source/Target/AssertFrameRecognizer.cpp | 2 +
lldb/source/Target/StackFrameRecognizer.cpp | 36 +++++-------
.../Target/VerboseTrapFrameRecognizer.cpp | 2 +-
.../frame/recognizer/TestFrameRecognizer.py | 16 ++---
.../Target/StackFrameRecognizerTest.cpp | 3 +-
8 files changed, 81 insertions(+), 61 deletions(-)
diff --git a/lldb/include/lldb/Target/StackFrameRecognizer.h b/lldb/include/lldb/Target/StackFrameRecognizer.h
index 4ef0d1b2f56dfb..617b1617d404a1 100644
--- a/lldb/include/lldb/Target/StackFrameRecognizer.h
+++ b/lldb/include/lldb/Target/StackFrameRecognizer.h
@@ -105,21 +105,30 @@ class ScriptedStackFrameRecognizer : public StackFrameRecognizer {
/// Class that provides a registry of known stack frame recognizers.
class StackFrameRecognizerManager {
public:
+ /// Add a new recognizer that triggers on a given symbol name.
+ ///
+ /// \param symbol_mangling controls whether the symbol name should be
+ /// compared to the mangled or demangled name.
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
ConstString module, llvm::ArrayRef<ConstString> symbols,
- bool first_instruction_only = true,
- Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled);
+ Mangled::NamePreference symbol_mangling,
+ bool first_instruction_only = true);
+ /// Add a new recognizer that triggers on a symbol regex.
+ ///
+ /// \param symbol_mangling controls whether the regex should apply
+ /// to the mangled or demangled name.
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
lldb::RegularExpressionSP module,
lldb::RegularExpressionSP symbol,
- bool first_instruction_only = true,
- Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled);
+ 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,
- bool regexp)> const &callback);
+ Mangled::NamePreference name_reference, bool regexp)> const
+ &callback);
bool RemoveRecognizerWithID(uint32_t recognizer_id);
@@ -144,8 +153,8 @@ class StackFrameRecognizerManager {
lldb::RegularExpressionSP module_regexp;
std::vector<ConstString> symbols;
lldb::RegularExpressionSP symbol_regexp;
+ Mangled::NamePreference symbol_mangling;
bool first_instruction_only;
- Mangled::NamePreference mangling_preference;
};
std::deque<RegisteredEntry> m_recognizers;
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index 46c75e3dd159c0..4ddd7664bf1e0c 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -168,8 +168,7 @@ class CommandObjectFrameDiagnose : public CommandObjectParsed {
// We've already handled the case where the value object sp is null, so
// this is just to make sure future changes don't skip that:
assert(valobj_sp.get() && "Must have a valid ValueObject to print");
- ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(),
- options);
+ ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(), options);
if (llvm::Error error = printer.PrintValueObject())
result.AppendError(toString(std::move(error)));
}
@@ -927,6 +926,31 @@ class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
}
};
+static void
+PrintRecognizerDetails(Stream &strm, const std::string &module,
+ llvm::ArrayRef<lldb_private::ConstString> symbols,
+ Mangled::NamePreference symbol_mangling, bool regexp) {
+ if (!module.empty())
+ strm << ", module " << module;
+
+ switch (symbol_mangling) {
+ case Mangled::NamePreference ::ePreferMangled:
+ strm << "mangled symbol ";
+ break;
+ case Mangled::NamePreference ::ePreferDemangled:
+ strm << "demangled symbol ";
+ break;
+ case Mangled::NamePreference ::ePreferDemangledWithoutArguments:
+ strm << "demangled (no args) symbol ";
+ break;
+ }
+
+ if (regexp)
+ strm << "regex ";
+
+ llvm::interleaveComma(symbols, strm);
+}
+
class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
public:
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
@@ -947,19 +971,13 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
GetTarget().GetFrameRecognizerManager().ForEach(
[&request](uint32_t rid, std::string rname, std::string module,
llvm::ArrayRef<lldb_private::ConstString> symbols,
- bool regexp) {
+ Mangled::NamePreference symbol_mangling, bool regexp) {
StreamString strm;
if (rname.empty())
rname = "(internal)";
- strm << rname;
- if (!module.empty())
- strm << ", module " << module;
- if (!symbols.empty())
- for (auto &symbol : symbols)
- strm << ", symbol " << symbol;
- if (regexp)
- strm << " (regexp)";
+ PrintRecognizerDetails(strm, module, symbols, symbol_mangling,
+ regexp);
request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
});
@@ -1016,22 +1034,18 @@ class CommandObjectFrameRecognizerList : public CommandObjectParsed {
void DoExecute(Args &command, CommandReturnObject &result) override {
bool any_printed = false;
GetTarget().GetFrameRecognizerManager().ForEach(
- [&result, &any_printed](
- uint32_t recognizer_id, std::string name, std::string module,
- llvm::ArrayRef<ConstString> symbols, bool regexp) {
+ [&result,
+ &any_printed](uint32_t recognizer_id, std::string name,
+ std::string module, llvm::ArrayRef<ConstString> symbols,
+ Mangled::NamePreference symbol_mangling, bool regexp) {
Stream &stream = result.GetOutputStream();
if (name.empty())
name = "(internal)";
-
stream << std::to_string(recognizer_id) << ": " << name;
- if (!module.empty())
- stream << ", module " << module;
- if (!symbols.empty())
- for (auto &symbol : symbols)
- stream << ", symbol " << symbol;
- if (regexp)
- stream << " (regexp)";
+
+ PrintRecognizerDetails(stream, module, symbols, symbol_mangling,
+ regexp);
stream.EOL();
stream.Flush();
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index bfd23ed9c3120e..0bf16a8630600c 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -106,8 +106,8 @@ CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {},
std::make_shared<RegularExpression>("^std::__[0-9]*::"),
- /*first_instruction_only=*/ false,
- /*mangling_preference=*/ Mangled::ePreferDemangledWithoutArguments);
+ /*mangling_preference=*/Mangled::ePreferDemangledWithoutArguments,
+ /*first_instruction_only=*/false);
}
bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
diff --git a/lldb/source/Target/AssertFrameRecognizer.cpp b/lldb/source/Target/AssertFrameRecognizer.cpp
index da7c102645c014..00b1f54023f168 100644
--- a/lldb/source/Target/AssertFrameRecognizer.cpp
+++ b/lldb/source/Target/AssertFrameRecognizer.cpp
@@ -89,6 +89,7 @@ void RegisterAssertFrameRecognizer(Process *process) {
target.GetFrameRecognizerManager().AddRecognizer(
std::make_shared<AssertFrameRecognizer>(),
location.module_spec.GetFilename(), location.symbols,
+ Mangled::ePreferDemangled,
/*first_instruction_only*/ false);
return;
}
@@ -112,6 +113,7 @@ void RegisterAssertFrameRecognizer(Process *process) {
std::make_shared<AssertFrameRecognizer>(),
std::make_shared<RegularExpression>(std::move(module_re)),
std::make_shared<RegularExpression>(std::move(symbol_re)),
+ Mangled::ePreferDemangled,
/*first_instruction_only*/ false);
}
diff --git a/lldb/source/Target/StackFrameRecognizer.cpp b/lldb/source/Target/StackFrameRecognizer.cpp
index 7c0dfde993948f..f7781a32b542e2 100644
--- a/lldb/source/Target/StackFrameRecognizer.cpp
+++ b/lldb/source/Target/StackFrameRecognizer.cpp
@@ -62,28 +62,29 @@ void StackFrameRecognizerManager::BumpGeneration() {
void StackFrameRecognizerManager::AddRecognizer(
StackFrameRecognizerSP recognizer, ConstString module,
- llvm::ArrayRef<ConstString> symbols, bool first_instruction_only,
- Mangled::NamePreference mangling_preference) {
+ llvm::ArrayRef<ConstString> symbols,
+ Mangled::NamePreference symbol_mangling, bool first_instruction_only) {
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
module, RegularExpressionSP(), symbols,
- RegularExpressionSP(), first_instruction_only});
+ RegularExpressionSP(), first_instruction_only,
+ symbol_mangling});
BumpGeneration();
}
void StackFrameRecognizerManager::AddRecognizer(
StackFrameRecognizerSP recognizer, RegularExpressionSP module,
- RegularExpressionSP symbol, bool first_instruction_only,
- Mangled::NamePreference mangling_preference) {
+ RegularExpressionSP symbol,
+ Mangled::NamePreference symbol_mangling, bool first_instruction_only) {
m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
ConstString(), module, std::vector<ConstString>(),
- symbol, first_instruction_only,
- mangling_preference});
+ symbol, first_instruction_only, symbol_mangling});
BumpGeneration();
}
void StackFrameRecognizerManager::ForEach(
- const std::function<void(uint32_t, std::string, std::string,
- llvm::ArrayRef<ConstString>, bool)> &callback) {
+ const std::function<
+ void(uint32_t, std::string, std::string, llvm::ArrayRef<ConstString>,
+ Mangled::NamePreference name_reference, bool)> &callback) {
for (auto entry : m_recognizers) {
if (entry.is_regexp) {
std::string module_name;
@@ -95,11 +96,13 @@ void StackFrameRecognizerManager::ForEach(
symbol_name = entry.symbol_regexp->GetText().str();
callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
- llvm::ArrayRef(ConstString(symbol_name)), true);
+ llvm::ArrayRef(ConstString(symbol_name)), entry.symbol_mangling,
+ true);
} else {
callback(entry.recognizer_id, entry.recognizer->GetName(),
- entry.module.GetCString(), entry.symbols, false);
+ entry.module.GetCString(), entry.symbols, entry.symbol_mangling,
+ false);
}
}
}
@@ -147,16 +150,7 @@ StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
if (!entry.module_regexp->Execute(module_name.GetStringRef()))
continue;
- ConstString function_name = [&]() {
- switch (entry.mangling_preference) {
- case Mangled::ePreferMangled:
- return symctx.GetFunctionName(entry.mangling_preference);
- case Mangled::ePreferDemangled:
- return symctx.GetFunctionName(entry.mangling_preference);
- case Mangled::ePreferDemangledWithoutArguments:
- return symctx.GetFunctionName(entry.mangling_preference);
- }
- }();
+ ConstString function_name = symctx.GetFunctionName(entry.symbol_mangling);
if (!entry.symbols.empty())
if (!llvm::is_contained(entry.symbols, function_name))
diff --git a/lldb/source/Target/VerboseTrapFrameRecognizer.cpp b/lldb/source/Target/VerboseTrapFrameRecognizer.cpp
index fe72c8aec570d3..9a1b721b99a518 100644
--- a/lldb/source/Target/VerboseTrapFrameRecognizer.cpp
+++ b/lldb/source/Target/VerboseTrapFrameRecognizer.cpp
@@ -116,7 +116,7 @@ void RegisterVerboseTrapFrameRecognizer(Process &process) {
std::make_shared<VerboseTrapFrameRecognizer>();
process.GetTarget().GetFrameRecognizerManager().AddRecognizer(
- srf_recognizer_sp, module_regex_sp, symbol_regex_sp, false);
+ srf_recognizer_sp, module_regex_sp, symbol_regex_sp, Mangled::ePreferDemangled, false);
}
} // namespace lldb_private
diff --git a/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py b/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
index 6174ac61a709dd..9cbbd7c0ec3bf5 100644
--- a/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
+++ b/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py
@@ -35,7 +35,7 @@ def test_frame_recognizer_1(self):
self.expect(
"frame recognizer list",
- substrs=["0: recognizer.MyFrameRecognizer, module a.out, symbol foo"],
+ substrs=["0: recognizer.MyFrameRecognizer, module a.out, demangled symbol foo"],
)
self.runCmd(
@@ -45,8 +45,8 @@ def test_frame_recognizer_1(self):
self.expect(
"frame recognizer list",
substrs=[
- "1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)",
- "0: recognizer.MyFrameRecognizer, module a.out, symbol foo",
+ "1: recognizer.MyOtherFrameRecognizer, module a.out, demangled symbol regex bar",
+ "0: recognizer.MyFrameRecognizer, module a.out, demangled symbol foo",
],
)
@@ -56,7 +56,7 @@ def test_frame_recognizer_1(self):
self.expect(
"frame recognizer list",
substrs=[
- "1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)"
+ "1: recognizer.MyOtherFrameRecognizer, module a.out, demangled symbol bar (regexp)"
],
)
self.expect(
@@ -79,7 +79,7 @@ def test_frame_recognizer_1(self):
self.expect(
"frame recognizer list",
substrs=[
- "1: recognizer.MyOtherFrameRecognizer, module a.out, symbol bar (regexp)"
+ "1: recognizer.MyOtherFrameRecognizer, module a.out, demangled symbol regexp bar"
],
)
self.expect(
@@ -224,7 +224,7 @@ def test_frame_recognizer_multi_symbol(self):
self.expect(
"frame recognizer list",
substrs=[
- "recognizer.MyFrameRecognizer, module a.out, symbol foo, symbol bar"
+ "recognizer.MyFrameRecognizer, module a.out, demangled symbol foo, bar"
],
)
@@ -279,7 +279,7 @@ def test_frame_recognizer_target_specific(self):
self.expect(
"frame recognizer list",
substrs=[
- "recognizer.MyFrameRecognizer, module a.out, symbol foo, symbol bar"
+ "recognizer.MyFrameRecognizer, module a.out, demangled symbol foo, bar"
],
)
@@ -305,7 +305,7 @@ def test_frame_recognizer_target_specific(self):
self.expect(
"frame recognizer list",
- substrs=["recognizer.MyFrameRecognizer, module a.out, symbol bar"],
+ substrs=["recognizer.MyFrameRecognizer, module a.out, demangled symbol bar"],
)
# Now the new target should also recognize the frame.
diff --git a/lldb/unittests/Target/StackFrameRecognizerTest.cpp b/lldb/unittests/Target/StackFrameRecognizerTest.cpp
index 695f091227d6a0..df4458e3138c49 100644
--- a/lldb/unittests/Target/StackFrameRecognizerTest.cpp
+++ b/lldb/unittests/Target/StackFrameRecognizerTest.cpp
@@ -55,7 +55,7 @@ void RegisterDummyStackFrameRecognizer(StackFrameRecognizerManager &manager) {
StackFrameRecognizerSP dummy_recognizer_sp(new DummyStackFrameRecognizer());
manager.AddRecognizer(dummy_recognizer_sp, module_regex_sp, symbol_regex_sp,
- false);
+ Mangled::NamePreference::ePreferDemangled, false);
}
} // namespace
@@ -72,6 +72,7 @@ TEST_F(StackFrameRecognizerTest, NullModuleRegex) {
manager.ForEach([&any_printed](uint32_t recognizer_id, std::string name,
std::string function,
llvm::ArrayRef<ConstString> symbols,
+ Mangled::NamePreference symbol_mangling,
bool regexp) { any_printed = true; });
EXPECT_TRUE(any_printed);
More information about the lldb-commits
mailing list