https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/133079
>From 2314f9e584d736ce2093cc196c7c57c2087cde42 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Wed, 26 Mar 2025 12:54:36 +0000 Subject: [PATCH 1/2] [lldb][Instrumentation] Set selected frame to outside sanitizer libraries --- .../Target/InstrumentationRuntimeStopInfo.h | 3 ++ lldb/include/lldb/Target/StackFrameList.h | 2 + lldb/include/lldb/Target/Thread.h | 4 ++ .../Target/InstrumentationRuntimeStopInfo.cpp | 42 +++++++++++++++++++ lldb/source/Target/Process.cpp | 2 + 5 files changed, 53 insertions(+) diff --git a/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h index 5345160850914..dafa41c11327a 100644 --- a/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h +++ b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h @@ -24,6 +24,9 @@ class InstrumentationRuntimeStopInfo : public StopInfo { return lldb::eStopReasonInstrumentation; } + std::optional<uint32_t> + GetSuggestedStackFrameIndex(bool inlined_stack) override; + const char *GetDescription() override; bool DoShouldNotify(Event *event_ptr) override { return true; } diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h index 8a66296346f2d..be6ec3b09d8aa 100644 --- a/lldb/include/lldb/Target/StackFrameList.h +++ b/lldb/include/lldb/Target/StackFrameList.h @@ -36,6 +36,8 @@ class StackFrameList { /// Get the frame at index \p idx. Invisible frames cannot be indexed. lldb::StackFrameSP GetFrameAtIndex(uint32_t idx); + void ResetSuggestedStackFrameIndex() { m_selected_frame_idx.reset(); } + /// Get the first concrete frame with index greater than or equal to \p idx. /// Unlike \ref GetFrameAtIndex, this cannot return a synthetic frame. lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx); diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 1d1e3dcfc1dc6..747d7299025f8 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -433,6 +433,10 @@ class Thread : public std::enable_shared_from_this<Thread>, return GetStackFrameList()->GetFrameAtIndex(idx); } + virtual void ResetSuggestedStackFrameIndex() { + return GetStackFrameList()->ResetSuggestedStackFrameIndex(); + } + virtual lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx); diff --git a/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp b/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp index 7f82581cc601e..1daeebdbaf9c7 100644 --- a/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp +++ b/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp @@ -8,13 +8,20 @@ #include "lldb/Target/InstrumentationRuntimeStopInfo.h" +#include "lldb/Core/Module.h" #include "lldb/Target/InstrumentationRuntime.h" #include "lldb/Target/Process.h" +#include "lldb/lldb-enumerations.h" #include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; +static bool IsStoppedInDarwinSanitizer(Thread &thread, Module &module) { + return module.GetFileSpec().GetFilename().GetStringRef().starts_with( + "libclang_rt."); +} + InstrumentationRuntimeStopInfo::InstrumentationRuntimeStopInfo( Thread &thread, std::string description, StructuredData::ObjectSP additional_data) @@ -34,3 +41,38 @@ InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData( return StopInfoSP( new InstrumentationRuntimeStopInfo(thread, description, additionalData)); } + +std::optional<uint32_t> +InstrumentationRuntimeStopInfo::GetSuggestedStackFrameIndex( + bool inlined_stack) { + auto thread_sp = GetThread(); + if (!thread_sp) + return std::nullopt; + + // Defensive upper-bound of when we stop walking up the frames in + // case we somehow ended up looking at an infinite recursion. + const size_t max_stack_depth = 128; + + // Start at parent frame. + size_t stack_idx = 1; + StackFrameSP most_relevant_frame_sp = + thread_sp->GetStackFrameAtIndex(stack_idx); + + while (most_relevant_frame_sp && stack_idx <= max_stack_depth) { + auto const &sc = + most_relevant_frame_sp->GetSymbolContext(lldb::eSymbolContextModule); + + if (!sc.module_sp) + return std::nullopt; + + // Found a frame outside of the sanitizer runtime libraries. + // That's the one we want to display. + if (!IsStoppedInDarwinSanitizer(*thread_sp, *sc.module_sp)) + return stack_idx; + + ++stack_idx; + most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(stack_idx); + } + + return stack_idx; +} diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index f2f5598f0ab53..f82cea2d668ed 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -4257,6 +4257,8 @@ bool Process::ProcessEventData::ShouldStop(Event *event_ptr, // appropriately. We also need to stop processing actions, since they // aren't expecting the target to be running. + thread_sp->ResetSuggestedStackFrameIndex(); + // FIXME: we might have run. if (stop_info_sp->HasTargetRunSinceMe()) { SetRestarted(true); >From 6ae615b48bcbbc9b872c27061a8147b82e2215de Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Wed, 26 Mar 2025 13:58:03 +0000 Subject: [PATCH 2/2] fixup! add tests --- lldb/test/API/functionalities/asan/TestMemoryHistory.py | 4 ++++ lldb/test/API/functionalities/asan/TestReportData.py | 4 ++++ lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lldb/test/API/functionalities/asan/TestMemoryHistory.py b/lldb/test/API/functionalities/asan/TestMemoryHistory.py index b04182a543719..03003f1e4112a 100644 --- a/lldb/test/API/functionalities/asan/TestMemoryHistory.py +++ b/lldb/test/API/functionalities/asan/TestMemoryHistory.py @@ -52,6 +52,10 @@ def libsanitizer_tests(self): substrs=["stopped", "stop reason = Use of deallocated memory"], ) + # Make sure we're not stopped in the sanitizer library but instead at the + # point of failure in the user-code. + self.assertEqual(self.frame().GetFunctionName(), "main") + # test the 'memory history' command self.expect( "memory history 'pointer'", diff --git a/lldb/test/API/functionalities/asan/TestReportData.py b/lldb/test/API/functionalities/asan/TestReportData.py index fabc985d0ed44..496a2db67c038 100644 --- a/lldb/test/API/functionalities/asan/TestReportData.py +++ b/lldb/test/API/functionalities/asan/TestReportData.py @@ -69,6 +69,10 @@ def asan_tests(self, libsanitizers=False): lldb.eStopReasonInstrumentation, ) + # Make sure we're not stopped in the sanitizer library but instead at the + # point of failure in the user-code. + self.assertEqual(self.frame().GetFunctionName(), "main") + self.expect( "bt", "The backtrace should show the crashing line", diff --git a/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py b/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py index 868a2864d2b5e..f46d167d910ea 100644 --- a/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py +++ b/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py @@ -52,8 +52,8 @@ def ubsan_tests(self): substrs=["1 match found"], ) - # We should be stopped in __ubsan_on_report - self.assertIn("__ubsan_on_report", frame.GetFunctionName()) + # We should not be stopped in the sanitizer library. + self.assertIn("main", frame.GetFunctionName()) # The stopped thread backtrace should contain either 'align line' found = False _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits