From e90463e8967c2019e220b063ed4ce73cd0172bf3 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Thu, 22 Aug 2024 10:50:13 +0000 Subject: [PATCH 1/7] [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 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 symbols; lldb::RegularExpressionSP symbol_regexp; bool first_instruction_only; + Mangled::NamePreference mangling_preference; }; std::deque m_recognizers; uint16_t m_generation = 0; + std::unordered_set 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 1e4a2cbb1133f7..6d446a099efc78 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include +#include #include @@ -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 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::__.*::(__function.*::operator\(\)|__invoke))" - R"((\[.*\])?)" // ABI tag. - R"(( const)?$)"), // const. + : m_hidden_regex{ + // internal implementation details of std::function + // std::__1::__function::__alloc_func, void ()>::operator()[abi:ne200000] + // std::__1::__function::__func, void ()>::operator() + // std::__1::__function::__value_func::operator()[abi:ne200000]() const + RegularExpression{"" + R"(^std::__[^:]*::)" // Namespace. + R"(__function::.*::operator\(\))" + R"((\[.*\])?)" // ABI tag. + R"(( const)?$)"}, // const. + // internal implementation details of std::invoke + // std::__1::__invoke[abi:ne200000] + RegularExpression{ + R"(^std::__[^:]*::)" // Namespace. + R"(__invoke)" + R"((\[.*\])?)" // ABI tag. + R"(<.*>)"}, // template argument. + // internal implementation details of std::invoke + // std::__1::__invoke_void_return_wrapper::__call[abi:ne200000] + RegularExpression{ + R"(^std::__[^:]*::)" // 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("^std::__.*::"), - /*first_instruction_only*/ false); + std::make_shared("^std::__[^:]*::"), + /*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 symbols, bool first_instruction_only) { + llvm::ArrayRef 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(), - 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 8d4b6bfe17166e..fa7a4f379e92b4 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::__.*::__function", "frame.*main"], + patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"], ) self.expect( "thread backtrace --unfiltered", ordered=True, - patterns=["frame.*foo", "frame.*std::__.*::__function", "frame.*main"], + patterns=["frame.*foo", "frame.*std::__[^:]*::__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 +#include + +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 6947b139c7515bb601a9993714e7ee0590997393 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Sun, 25 Aug 2024 23:24:57 +0200 Subject: [PATCH 2/7] 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 m_recognizers; uint16_t m_generation = 0; - std::unordered_set 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(), 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 e384eb9d94eb2f09a58db5805dc70af53cece93c Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Mon, 26 Aug 2024 00:00:59 +0200 Subject: [PATCH 3/7] Copy additional content from adrian-prantl's commit --- .../lldb/Target/StackFrameRecognizer.h | 21 ++++-- lldb/source/Commands/CommandObjectFrame.cpp | 68 ++++++++++++------- .../CPlusPlus/CPPLanguageRuntime.cpp | 4 +- .../AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 2 +- .../AbortWithPayloadFrameRecognizer.cpp | 11 +-- lldb/source/Target/AssertFrameRecognizer.cpp | 2 + lldb/source/Target/StackFrameRecognizer.cpp | 36 ++++------ .../Target/VerboseTrapFrameRecognizer.cpp | 3 +- .../frame/recognizer/TestFrameRecognizer.py | 20 +++--- .../completion/TestCompletion.py | 2 +- .../TestStdFunctionRecognizer.py | 9 ++- .../TestStdInvokeRecognizer.py | 20 ++++-- .../Target/StackFrameRecognizerTest.cpp | 3 +- 13 files changed, 125 insertions(+), 76 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 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 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 symbols; lldb::RegularExpressionSP symbol_regexp; + Mangled::NamePreference symbol_mangling; bool first_instruction_only; - Mangled::NamePreference mangling_preference; }; std::deque m_recognizers; diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index 46c75e3dd159c0..ef57582a203b39 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))); } @@ -899,13 +898,16 @@ void CommandObjectFrameRecognizerAdd::DoExecute(Args &command, auto func = RegularExpressionSP(new RegularExpression(m_options.m_symbols.front())); GetTarget().GetFrameRecognizerManager().AddRecognizer( - recognizer_sp, module, func, m_options.m_first_instruction_only); + recognizer_sp, module, func, Mangled::NamePreference::ePreferDemangled, + m_options.m_first_instruction_only); } else { auto module = ConstString(m_options.m_module); std::vector symbols(m_options.m_symbols.begin(), m_options.m_symbols.end()); GetTarget().GetFrameRecognizerManager().AddRecognizer( - recognizer_sp, module, symbols, m_options.m_first_instruction_only); + recognizer_sp, module, symbols, + Mangled::NamePreference::ePreferDemangled, + m_options.m_first_instruction_only); } #endif @@ -927,6 +929,34 @@ class CommandObjectFrameRecognizerClear : public CommandObjectParsed { } }; +static void +PrintRecognizerDetails(Stream &strm, const std::string &name, + const std::string &module, + llvm::ArrayRef symbols, + Mangled::NamePreference symbol_mangling, bool regexp) { + strm << name << ", "; + + 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 +977,13 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed { GetTarget().GetFrameRecognizerManager().ForEach( [&request](uint32_t rid, std::string rname, std::string module, llvm::ArrayRef 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, rname, module, symbols, symbol_mangling, + regexp); request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString()); }); @@ -1016,22 +1040,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 symbols, bool regexp) { + [&result, + &any_printed](uint32_t recognizer_id, std::string name, + std::string module, llvm::ArrayRef 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)"; + stream << std::to_string(recognizer_id) << ": "; + PrintRecognizerDetails(stream, name, 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 6d446a099efc78..a9204d9f8857df 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("^std::__[^:]*::"), - /*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/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 9409497f1c81ba..c810ba0c3b171e 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -3465,6 +3465,6 @@ static void RegisterObjCExceptionRecognizer(Process *process) { process->GetTarget().GetFrameRecognizerManager().AddRecognizer( StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()), - module.GetFilename(), symbols, + module.GetFilename(), symbols, Mangled::NamePreference::ePreferDemangled, /*first_instruction_only*/ true); } diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp index d42e31c2aea0a0..cd9260a27719ba 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp @@ -36,8 +36,9 @@ void RegisterAbortWithPayloadFrameRecognizer(Process *process) { return; process->GetTarget().GetFrameRecognizerManager().AddRecognizer( - std::make_shared(), module_name, - sym_name, /*first_instruction_only*/ false); + std::make_shared(), module_name, + sym_name, Mangled::NamePreference::ePreferDemangled, + /*first_instruction_only*/ false); } RecognizedStackFrameSP @@ -55,7 +56,7 @@ AbortWithPayloadFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) { static constexpr llvm::StringLiteral info_key("abort_with_payload"); Log *log = GetLog(LLDBLog::SystemRuntime); - + if (!frame_sp) { LLDB_LOG(log, "abort_with_payload recognizer: invalid frame."); return {}; @@ -196,8 +197,8 @@ AbortWithPayloadFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) { abort_dict_sp->AddStringItem(reason_key, reason_string); abort_dict_sp->AddIntegerItem(flags_key, flags_val); - // This will overwrite the abort_with_payload information in the dictionary - // already. But we can only crash on abort_with_payload once, so that + // This will overwrite the abort_with_payload information in the dictionary + // already. But we can only crash on abort_with_payload once, so that // shouldn't matter. process->GetExtendedCrashInfoDict()->AddItem(info_key, abort_dict_sp); 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(), location.module_spec.GetFilename(), location.symbols, + Mangled::ePreferDemangled, /*first_instruction_only*/ false); return; } @@ -112,6 +113,7 @@ void RegisterAssertFrameRecognizer(Process *process) { std::make_shared(), std::make_shared(std::move(module_re)), std::make_shared(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..fa24253320a3f2 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 symbols, bool first_instruction_only, - Mangled::NamePreference mangling_preference) { + llvm::ArrayRef 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(), symbol_mangling, + first_instruction_only}); 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(), - symbol, first_instruction_only, - mangling_preference}); + symbol, symbol_mangling, first_instruction_only}); BumpGeneration(); } void StackFrameRecognizerManager::ForEach( - const std::function, bool)> &callback) { + const std::function< + void(uint32_t, std::string, std::string, llvm::ArrayRef, + 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..de710fcda54064 100644 --- a/lldb/source/Target/VerboseTrapFrameRecognizer.cpp +++ b/lldb/source/Target/VerboseTrapFrameRecognizer.cpp @@ -116,7 +116,8 @@ void RegisterVerboseTrapFrameRecognizer(Process &process) { std::make_shared(); 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..e25df2b6cdc245 100644 --- a/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py +++ b/lldb/test/API/commands/frame/recognizer/TestFrameRecognizer.py @@ -35,7 +35,9 @@ 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 +47,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 +58,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 +81,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 +226,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 +281,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 +307,9 @@ 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/test/API/functionalities/completion/TestCompletion.py b/lldb/test/API/functionalities/completion/TestCompletion.py index 95873405eab84e..bf19a990cf6e30 100644 --- a/lldb/test/API/functionalities/completion/TestCompletion.py +++ b/lldb/test/API/functionalities/completion/TestCompletion.py @@ -708,7 +708,7 @@ def test_frame_recognizer_delete(self): ) self.check_completion_with_desc( "frame recognizer delete ", - [["0", "py_class, module module_name, symbol recognizer_name"]], + [["0", "py_class, module module_name, demangled symbol recognizer_name"]], ) def test_platform_install_local_file(self): 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 fa7a4f379e92b4..d1cb8214d658ff 100644 --- a/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py +++ b/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py @@ -17,10 +17,15 @@ def test_frame_recognizer(self): 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(): + 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()) + 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()) diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py index ef75e1afd9cba5..e3112a6539e766 100644 --- a/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py +++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py @@ -16,16 +16,28 @@ def test_frame_recognizer(self): ) while process.GetState() != lldb.eStateExited: - self.assertTrue(any(f in thread.GetFrameAtIndex(0).GetFunctionName() for f in ["print_num", "add", "PrintAdder"])) + 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(): + 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()) + 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()) + self.assertIn( + "main", thread.GetFrameAtIndex(frame_id + 1).GetFunctionName() + ) process.Continue() 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 symbols, + Mangled::NamePreference symbol_mangling, bool regexp) { any_printed = true; }); EXPECT_TRUE(any_printed); From 51eb02e978493f4f020a58b6ca68aaf95c7bb032 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Mon, 26 Aug 2024 05:16:53 +0000 Subject: [PATCH 4/7] Fix libc++ ABI v2 --- .../LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index a9204d9f8857df..089a8477c50317 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -45,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 { - std::array m_hidden_regex; + std::array m_hidden_regex; RecognizedStackFrameSP m_hidden_frame; struct LibCXXHiddenFrame : public RecognizedStackFrame { @@ -64,6 +64,13 @@ class LibCXXFrameRecognizer : public StackFrameRecognizer { R"(__function::.*::operator\(\))" R"((\[.*\])?)" // ABI tag. R"(( const)?$)"}, // const. + // internal implementation details of std::function in ABI v2 + // std::__2::__function::__policy_invoker::__call_impl[abi:ne200000]> + RegularExpression{"" + R"(^std::__[^:]*::)" // Namespace. + R"(__function::.*::__call_impl)" + R"((\[.*\])?)" // ABI tag. + R"(<.*>)"}, // template argument. // internal implementation details of std::invoke // std::__1::__invoke[abi:ne200000] RegularExpression{ From 44059b8f58c1c6d3e711a11dc824c32743405df8 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Mon, 26 Aug 2024 11:09:50 +0000 Subject: [PATCH 5/7] Address simple review comments --- .../MacOSX/AbortWithPayloadFrameRecognizer.cpp | 6 +++--- .../cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp index cd9260a27719ba..fd04db7807a4a0 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp @@ -56,7 +56,7 @@ AbortWithPayloadFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) { static constexpr llvm::StringLiteral info_key("abort_with_payload"); Log *log = GetLog(LLDBLog::SystemRuntime); - + if (!frame_sp) { LLDB_LOG(log, "abort_with_payload recognizer: invalid frame."); return {}; @@ -197,8 +197,8 @@ AbortWithPayloadFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) { abort_dict_sp->AddStringItem(reason_key, reason_string); abort_dict_sp->AddIntegerItem(flags_key, flags_val); - // This will overwrite the abort_with_payload information in the dictionary - // already. But we can only crash on abort_with_payload once, so that + // This will overwrite the abort_with_payload information in the dictionary + // already. But we can only crash on abort_with_payload once, so that // shouldn't matter. process->GetExtendedCrashInfoDict()->AddItem(info_key, abort_dict_sp); diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py index e3112a6539e766..ddf3fb607d7786 100644 --- a/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py +++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py @@ -9,7 +9,7 @@ class LibCxxStdFunctionRecognizerTestCase(TestBase): @add_test_categories(["libc++"]) def test_frame_recognizer(self): - """Test that implementation details details of `std::invoke`""" + """Test that implementation details of `std::invoke` are hidden""" self.build() (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "// break here", lldb.SBFileSpec("main.cpp") @@ -22,16 +22,13 @@ def test_frame_recognizer(self): 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() From 17302d3d4315228d4248ca0293ac11fe4d9445a1 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Tue, 27 Aug 2024 16:37:04 +0000 Subject: [PATCH 6/7] Address remaining comments --- .../CPlusPlus/CPPLanguageRuntime.cpp | 17 +++-------- .../TestStdInvokeRecognizer.py | 8 ++++-- .../lang/cpp/std-invoke-recognizer/main.cpp | 28 ++++++++----------- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 089a8477c50317..faa05e8f834ea1 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -61,31 +61,22 @@ class LibCXXFrameRecognizer : public StackFrameRecognizer { // std::__1::__function::__value_func::operator()[abi:ne200000]() const RegularExpression{"" R"(^std::__[^:]*::)" // Namespace. - R"(__function::.*::operator\(\))" - R"((\[.*\])?)" // ABI tag. - R"(( const)?$)"}, // const. + R"(__function::.*::operator\(\))"}, // internal implementation details of std::function in ABI v2 // std::__2::__function::__policy_invoker::__call_impl[abi:ne200000]> RegularExpression{"" R"(^std::__[^:]*::)" // Namespace. - R"(__function::.*::__call_impl)" - R"((\[.*\])?)" // ABI tag. - R"(<.*>)"}, // template argument. + R"(__function::.*::__call_impl)"}, // internal implementation details of std::invoke // std::__1::__invoke[abi:ne200000] RegularExpression{ R"(^std::__[^:]*::)" // Namespace. - R"(__invoke)" - R"((\[.*\])?)" // ABI tag. - R"(<.*>)"}, // template argument. + R"(__invoke)"}, // internal implementation details of std::invoke // std::__1::__invoke_void_return_wrapper::__call[abi:ne200000] RegularExpression{ R"(^std::__[^:]*::)" // Namespace. - R"(__invoke_void_return_wrapper<.*>::__call)" - R"((\[.*\])?)" // ABI tag. - R"(<.*>)"} // template argument. - + R"(__invoke_void_return_wrapper<.*>::__call)"} }, m_hidden_frame(new LibCXXHiddenFrame()) {} diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py index ddf3fb607d7786..dbe29610bf7982 100644 --- a/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py +++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/TestStdInvokeRecognizer.py @@ -12,14 +12,16 @@ def test_frame_recognizer(self): """Test that implementation details of `std::invoke` are hidden""" self.build() (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( - self, "// break here", lldb.SBFileSpec("main.cpp") + self, "break here", lldb.SBFileSpec("main.cpp") ) + stop_cnt = 0 while process.GetState() != lldb.eStateExited: + stop_cnt += 1 self.assertTrue( any( f in thread.GetFrameAtIndex(0).GetFunctionName() - for f in ["print_num", "add", "PrintAdder"] + for f in ["consume_number", "add", "Callable"] ) ) # Skip all hidden frames @@ -38,3 +40,5 @@ def test_frame_recognizer(self): "main", thread.GetFrameAtIndex(frame_id + 1).GetFunctionName() ) process.Continue() + + self.assertEqual(stop_cnt, 4) diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp b/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp index 78497d2938fe8a..0d655d6c535e4f 100644 --- a/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp +++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp @@ -1,9 +1,7 @@ #include -#include -void print_num(int i) { - // break here - std::cout << i << '\n'; +void consume_number(int i) { + __builtin_printf("break here"); } int add(int i, int j) { @@ -11,30 +9,28 @@ int add(int i, int j) { return i + j; } -struct PrintAdder { - PrintAdder(int num) : num_(num) {} +struct Callable { + Callable(int num) : num_(num) {} void operator()(int i) const { - // break here - std::cout << i << '\n'; + __builtin_printf("break here"); } - void print_add(int i) const { - // break here - std::cout << num_ + i << '\n'; + void member_function(int i) const { + __builtin_printf("break here"); } int num_; }; int main() { // Invoke a void-returning function - std::invoke(print_num, -9); + std::invoke(consume_number, -9); // Invoke a non-void-returning function - std::cout << std::invoke(add, 1, 10) << '\n'; + std::invoke(add, 1, 10); // Invoke a member function - const PrintAdder foo(314159); - std::invoke(&PrintAdder::print_add, foo, 1); + const Callable foo(314159); + std::invoke(&Callable::member_function, foo, 1); // Invoke a function object - std::invoke(PrintAdder(12), 18); + std::invoke(Callable(12), 18); } From 3763051a8b25547ec0fa9e7d6b06e6759afcd037 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Tue, 27 Aug 2024 16:59:52 +0000 Subject: [PATCH 7/7] Fix code formatting --- .../test/API/lang/cpp/std-invoke-recognizer/main.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp b/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp index 0d655d6c535e4f..bafbbd28386e8b 100644 --- a/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp +++ b/lldb/test/API/lang/cpp/std-invoke-recognizer/main.cpp @@ -1,8 +1,6 @@ #include -void consume_number(int i) { - __builtin_printf("break here"); -} +void consume_number(int i) { __builtin_printf("break here"); } int add(int i, int j) { // break here @@ -11,12 +9,8 @@ int add(int i, int j) { struct Callable { Callable(int num) : num_(num) {} - void operator()(int i) const { - __builtin_printf("break here"); - } - void member_function(int i) const { - __builtin_printf("break here"); - } + void operator()(int i) const { __builtin_printf("break here"); } + void member_function(int i) const { __builtin_printf("break here"); } int num_; };