llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) <details> <summary>Changes</summary> This patch adds a frame recognizer for Clang's `__builtin_verbose_trap`, which behaves like a `__builtin_trap`, but emits a failure-reason string into debug-info in order for debuggers to display it to a user. The frame recognizer triggers when we encounter a frame with a function name that begins with `__llvm_verbose_trap`, which is the magic prefix Clang emits into debug-info for verbose traps. Once such frame is encountered we display the frame function name as the `Stop Reason` and display that frame to the user. Example output: ``` (lldb) run warning: a.out was compiled with optimization - stepping may behave oddly; variables may not be available. Process 35942 launched: 'a.out' (arm64) Process 35942 stopped * thread #<!-- -->1, queue = 'com.apple.main-thread', stop reason = __llvm_verbose_trap: Function is not implemented frame #<!-- -->1: 0x0000000100003fa4 a.out`main [inlined] Dummy::func(this=<unavailable>) at verbose_trap.cpp:3:5 [opt] 1 struct Dummy { 2 void func() { -> 3 __builtin_verbose_trap("Function is not implemented"); 4 } 5 }; 6 7 int main() { (lldb) bt * thread #<!-- -->1, queue = 'com.apple.main-thread', stop reason = __llvm_verbose_trap: Function is not implemented frame #<!-- -->0: 0x0000000100003fa4 a.out`main [inlined] __llvm_verbose_trap: Function is not implemented at verbose_trap.cpp:0 [opt] * frame #<!-- -->1: 0x0000000100003fa4 a.out`main [inlined] Dummy::func(this=<unavailable>) at verbose_trap.cpp:3:5 [opt] frame #<!-- -->2: 0x0000000100003fa4 a.out`main at verbose_trap.cpp:8:13 [opt] frame #<!-- -->3: 0x0000000189d518b4 dyld`start + 1988 ``` --- Full diff: https://github.com/llvm/llvm-project/pull/80368.diff 6 Files Affected: - (added) lldb/include/lldb/Target/VerboseTrapFrameRecognizer.h (+39) - (modified) lldb/source/Target/CMakeLists.txt (+1) - (modified) lldb/source/Target/Process.cpp (+2) - (added) lldb/source/Target/VerboseTrapFrameRecognizer.cpp (+85) - (added) lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp (+8) - (added) lldb/test/Shell/Recognizer/verbose_trap.test (+9) ``````````diff diff --git a/lldb/include/lldb/Target/VerboseTrapFrameRecognizer.h b/lldb/include/lldb/Target/VerboseTrapFrameRecognizer.h new file mode 100644 index 0000000000000..7e045760a28be --- /dev/null +++ b/lldb/include/lldb/Target/VerboseTrapFrameRecognizer.h @@ -0,0 +1,39 @@ +#ifndef LLDB_TARGET_VERBOSETRAPFRAMERECOGNIZER_H +#define LLDB_TARGET_VERBOSETRAPFRAMERECOGNIZER_H + +#include "lldb/Target/StackFrameRecognizer.h" + +namespace lldb_private { + +void RegisterVerboseTrapFrameRecognizer(Process &process); + +/// Holds the stack frame that caused the Verbose trap and the inlined stop +/// reason message. +class VerboseTrapRecognizedStackFrame : public RecognizedStackFrame { +public: + VerboseTrapRecognizedStackFrame(lldb::StackFrameSP most_relevant_frame_sp, + std::string stop_desc); + + lldb::StackFrameSP GetMostRelevantFrame() override; + +private: + lldb::StackFrameSP m_most_relevant_frame; +}; + +/// When a thread stops, it checks the current frame contains a +/// Verbose Trap diagnostic. If so, it returns a \a +/// VerboseTrapRecognizedStackFrame holding the diagnostic a stop reason +/// description with and the parent frame as the most relavant frame. +class VerboseTrapFrameRecognizer : public StackFrameRecognizer { +public: + std::string GetName() override { + return "Verbose Trap StackFrame Recognizer"; + } + + lldb::RecognizedStackFrameSP + RecognizeFrame(lldb::StackFrameSP frame) override; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_VERBOSETRAPFRAMERECOGNIZER_H diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt index cf4818eae3eb8..8186ccbea27d4 100644 --- a/lldb/source/Target/CMakeLists.txt +++ b/lldb/source/Target/CMakeLists.txt @@ -78,6 +78,7 @@ add_lldb_library(lldbTarget UnixSignals.cpp UnwindAssembly.cpp UnwindLLDB.cpp + VerboseTrapFrameRecognizer.cpp LINK_LIBS lldbBreakpoint diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 23a8a66645c02..04b00aaa1fac9 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -63,6 +63,7 @@ #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Target/ThreadPlanStack.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Target/VerboseTrapFrameRecognizer.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" @@ -497,6 +498,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, value_sp->SetValueAs(platform_cache_line_size); RegisterAssertFrameRecognizer(this); + RegisterVerboseTrapFrameRecognizer(*this); } Process::~Process() { diff --git a/lldb/source/Target/VerboseTrapFrameRecognizer.cpp b/lldb/source/Target/VerboseTrapFrameRecognizer.cpp new file mode 100644 index 0000000000000..d1a9ec18f8fe4 --- /dev/null +++ b/lldb/source/Target/VerboseTrapFrameRecognizer.cpp @@ -0,0 +1,85 @@ +#include "lldb/Target/VerboseTrapFrameRecognizer.h" + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +VerboseTrapRecognizedStackFrame::VerboseTrapRecognizedStackFrame( + StackFrameSP most_relevant_frame_sp, std::string stop_desc) + : m_most_relevant_frame(most_relevant_frame_sp) { + m_stop_desc = std::move(stop_desc); +} + +lldb::RecognizedStackFrameSP +VerboseTrapFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) { + if (frame_sp->GetFrameIndex()) + return {}; + + ThreadSP thread_sp = frame_sp->GetThread(); + ProcessSP process_sp = thread_sp->GetProcess(); + + StackFrameSP most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(1); + + if (!most_relevant_frame_sp) { + Log *log = GetLog(LLDBLog::Unwind); + LLDB_LOG( + log, + "Failed to find most relevant frame: Hit unwinding bound (1 frame)!"); + return {}; + } + + SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything); + + if (!sc.block) + return {}; + + // The runtime error is set as the function name in the inlined function info + // of frame #0 by the compiler + const InlineFunctionInfo *inline_info = nullptr; + Block *inline_block = sc.block->GetContainingInlinedBlock(); + + if (!inline_block) + return {}; + + inline_info = sc.block->GetInlinedFunctionInfo(); + + if (!inline_info) + return {}; + + auto runtime_error = inline_info->GetName().GetString(); + + if (runtime_error.empty()) + return {}; + + return lldb::RecognizedStackFrameSP(new VerboseTrapRecognizedStackFrame( + most_relevant_frame_sp, std::move(runtime_error))); +} + +lldb::StackFrameSP VerboseTrapRecognizedStackFrame::GetMostRelevantFrame() { + return m_most_relevant_frame; +} + +namespace lldb_private { + +void RegisterVerboseTrapFrameRecognizer(Process &process) { + RegularExpressionSP module_regex_sp = nullptr; + RegularExpressionSP symbol_regex_sp( + new RegularExpression("(__llvm_verbose_trap)")); + + StackFrameRecognizerSP srf_recognizer_sp = + std::make_shared<VerboseTrapFrameRecognizer>(); + + process.GetTarget().GetFrameRecognizerManager().AddRecognizer( + srf_recognizer_sp, module_regex_sp, symbol_regex_sp, false); +} + +} // namespace lldb_private diff --git a/lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp b/lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp new file mode 100644 index 0000000000000..6867c245e2fc9 --- /dev/null +++ b/lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp @@ -0,0 +1,8 @@ +struct Dummy { + void func() { __builtin_verbose_trap("Function is not implemented"); } +}; + +int main() { + Dummy{}.func(); + return 0; +} diff --git a/lldb/test/Shell/Recognizer/verbose_trap.test b/lldb/test/Shell/Recognizer/verbose_trap.test new file mode 100644 index 0000000000000..7790354784afd --- /dev/null +++ b/lldb/test/Shell/Recognizer/verbose_trap.test @@ -0,0 +1,9 @@ +# RUN: %clang_host -g -O0 %S/Inputs/verbose_trap.cpp -o %t.out +# RUN: %lldb -b -s %s %t.out | FileCheck %s +run +# CHECK: thread #{{.*}}stop reason = __llvm_verbose_trap: Function is not implemented +frame info +# CHECK: frame #{{.*}}`Dummy::func(this={{.*}}) at verbose_trap.cpp +frame recognizer info 0 +# CHECK: frame 0 is recognized by Verbose Trap StackFrame Recognizer +q `````````` </details> https://github.com/llvm/llvm-project/pull/80368 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits