diff --git a/lldb/source/Target/VerboseTrapFrameRecognizer.cpp b/lldb/source/Target/VerboseTrapFrameRecognizer.cpp index 7c5d633ac4e814..26bfb2e7363ca6 100644 --- a/lldb/source/Target/VerboseTrapFrameRecognizer.cpp +++ b/lldb/source/Target/VerboseTrapFrameRecognizer.cpp @@ -4,11 +4,14 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/StackFrameRecognizer.h" #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" +#include "clang/CodeGen/ModuleBuilder.h" + using namespace llvm; using namespace lldb; using namespace lldb_private; @@ -55,26 +58,47 @@ VerboseTrapFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) { if (!inline_info) return {}; - auto error_message = inline_info->GetName().GetString(); - if (error_message.empty()) + auto func_name = inline_info->GetName().GetStringRef(); + if (func_name.empty()) return {}; - // Replaces "__llvm_verbose_trap: " with "Runtime Error: " - auto space_position = error_message.find(" "); - if (space_position == std::string::npos) { - Log *log = GetLog(LLDBLog::Unwind); - LLDB_LOGF(log, - "Unexpected function name format. Expected ': " - "' but got: '%s'.", - error_message.c_str()); + static auto trap_regex = + llvm::Regex(llvm::formatv("^{0}\\$(.*)\\$(.*)$", ClangTrapPrefix).str()); + SmallVector matches; + std::string regex_err_msg; + if (!trap_regex.match(func_name, &matches, ®ex_err_msg)) { + LLDB_LOGF(GetLog(LLDBLog::Unwind), + "Failed to parse match trap regex for '%s': %s", func_name.data(), + regex_err_msg.c_str()); + + return {}; + } + + // For `__clang_trap_msg$category$message$` we expect 3 matches: + // 1. entire string + // 2. category + // 3. message + if (matches.size() != 3) { + LLDB_LOGF(GetLog(LLDBLog::Unwind), + "Unexpected function name format. Expected '$$'$ but got: '%s'. %zu", + func_name.data(), matches.size()); return {}; } - error_message.replace(0, space_position, "Runtime Error:"); + auto category = matches[1]; + auto message = matches[2]; + + std::string stop_reason = + category.empty() ? "" : category.str(); + if (!message.empty()) { + stop_reason += ": "; + stop_reason += message.str(); + } - return lldb::RecognizedStackFrameSP(new VerboseTrapRecognizedStackFrame( - most_relevant_frame_sp, std::move(error_message))); + return std::make_shared( + most_relevant_frame_sp, std::move(stop_reason)); } lldb::StackFrameSP VerboseTrapRecognizedStackFrame::GetMostRelevantFrame() { @@ -85,8 +109,8 @@ namespace lldb_private { void RegisterVerboseTrapFrameRecognizer(Process &process) { RegularExpressionSP module_regex_sp = nullptr; - RegularExpressionSP symbol_regex_sp( - new RegularExpression("^__llvm_verbose_trap: ")); + auto symbol_regex_sp = std::make_shared( + llvm::formatv("^{0}", ClangTrapPrefix).str()); StackFrameRecognizerSP srf_recognizer_sp = std::make_shared(); diff --git a/lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp b/lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp index 6867c245e2fc9f..89962b54379980 100644 --- a/lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp +++ b/lldb/test/Shell/Recognizer/Inputs/verbose_trap.cpp @@ -1,5 +1,9 @@ +#if !defined(VERBOSE_TRAP_TEST_CATEGORY) || !defined(VERBOSE_TRAP_TEST_MESSAGE) +#error Please define required macros +#endif + struct Dummy { - void func() { __builtin_verbose_trap("Function is not implemented"); } + void func() { __builtin_verbose_trap(VERBOSE_TRAP_TEST_CATEGORY, VERBOSE_TRAP_TEST_MESSAGE); } }; int main() { diff --git a/lldb/test/Shell/Recognizer/verbose_trap.test b/lldb/test/Shell/Recognizer/verbose_trap.test index 3fb3bd7abcd390..45ef84bef611fe 100644 --- a/lldb/test/Shell/Recognizer/verbose_trap.test +++ b/lldb/test/Shell/Recognizer/verbose_trap.test @@ -1,7 +1,20 @@ -# RUN: %clang_host -g -O0 %S/Inputs/verbose_trap.cpp -o %t.out -# RUN: %lldb -b -s %s %t.out | FileCheck %s +# RUN: %clang_host -g -O0 %S/Inputs/verbose_trap.cpp -o %t.out -DVERBOSE_TRAP_TEST_CATEGORY=\"Foo\" -DVERBOSE_TRAP_TEST_MESSAGE=\"Bar\" +# RUN: %lldb -b -s %s %t.out | FileCheck %s --check-prefixes=CHECK,CHECK-BOTH +# +# RUN: %clang_host -g -O0 %S/Inputs/verbose_trap.cpp -o %t.out -DVERBOSE_TRAP_TEST_CATEGORY=\"\" -DVERBOSE_TRAP_TEST_MESSAGE=\"Bar\" +# RUN: %lldb -b -s %s %t.out | FileCheck %s --check-prefixes=CHECK,CHECK-MESSAGE_ONLY +# +# RUN: %clang_host -g -O0 %S/Inputs/verbose_trap.cpp -o %t.out -DVERBOSE_TRAP_TEST_CATEGORY=\"Foo\" -DVERBOSE_TRAP_TEST_MESSAGE=\"\" +# RUN: %lldb -b -s %s %t.out | FileCheck %s --check-prefixes=CHECK,CHECK-CATEGORY_ONLY +# +# RUN: %clang_host -g -O0 %S/Inputs/verbose_trap.cpp -o %t.out -DVERBOSE_TRAP_TEST_CATEGORY=\"\" -DVERBOSE_TRAP_TEST_MESSAGE=\"\" +# RUN: %lldb -b -s %s %t.out | FileCheck %s --check-prefixes=CHECK,CHECK-NONE + run -# CHECK: thread #{{.*}}stop reason = Runtime Error: Function is not implemented +# CHECK-BOTH: thread #{{.*}}stop reason = Foo: Bar +# CHECK-MESSAGE_ONLY: thread #{{.*}}stop reason = : Bar +# CHECK-CATEGORY_ONLY: thread #{{.*}}stop reason = Foo +# CHECK-NONE: thread #{{.*}}stop reason = frame info # CHECK: frame #{{.*}}`Dummy::func(this={{.*}}) at verbose_trap.cpp frame recognizer info 0