Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Bratislav Filipovic <bfilipov@amd.com>
To: <gdb-patches@sourceware.org>
Cc: <simon.marchi@polymtl.ca>, <six.lancelot@amd.com>,
	<pedro@palves.net>, Bratislav Filipovic <bfilipov@amd.com>
Subject: [PATCH] gdb: Show __builtin_verbose_trap message in backtraces
Date: Mon, 21 Sep 2026 14:38:49 +0200	[thread overview]
Message-ID: <20260921123852.11526-1-bfilipov@amd.com> (raw)

__builtin_verbose_trap is a Clang-19+ builtin that allows embedding
custom trap messages in the binary for better crash diagnostics.
When called, it emits a trap instruction and creates an artificial
inline frame with a specially-formatted name:
__clang_trap_msg$<category>$<message>.

Currently, when a program hits a verbose trap, GDB hides this inline
frame by default (as it does for all inline frames during normal
stepping).  This means the trap message is not visible in backtraces,
defeating the purpose of verbose traps.

Before this fix, a backtrace after hitting a verbose trap shows:

    #0  test_trap_kernel () at test.cpp:24

After this fix:

    #0  __clang_trap_msg$check verbose$This is verbose trap! ()
        at test.cpp:23
    #1  test_trap_kernel () at test.cpp:24

This affects both CPU (x86_64) and GPU (AMDGPU) targets, though with
different trap mechanisms:
- CPU: ud2 instruction generates SIGILL
- GPU: s_trap 2 instruction generates SIGABRT

To fix this, add a new gdbarch hook 'should_show_inline_frame' that
allows architecture-specific code to decide whether an inline frame
should be shown.  The hook receives the symbol and the stop signal,
returning true if the frame should be displayed.

The hook is implemented for:
- amd64-linux: checks for SIGILL + __clang_trap_msg$ prefix
- amdgpu: checks for SIGABRT + __clang_trap_msg$ prefix

The signal check ensures the frame is only shown when the trap actually
fires, preserving normal stepping behavior where inline frames are
hidden.
---
 gdb/amd64-linux-tdep.c                        | 32 ++++++
 gdb/amdgpu-tdep.c                             | 29 ++++++
 gdb/arch-utils.c                              | 12 +++
 gdb/arch-utils.h                              |  5 +
 gdb/gdbarch-gen.c                             | 22 +++++
 gdb/gdbarch-gen.h                             | 22 +++++
 gdb/gdbarch_components.py                     | 27 +++++
 gdb/inline-frame.c                            |  7 +-
 .../gdb.base/builtin_verbose_trap.cpp         | 29 ++++++
 .../gdb.base/builtin_verbose_trap.exp         | 96 ++++++++++++++++++
 .../gdb.rocm/builtin_verbose_trap.cpp         | 34 +++++++
 .../gdb.rocm/builtin_verbose_trap.exp         | 98 +++++++++++++++++++
 12 files changed, 412 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.base/builtin_verbose_trap.cpp
 create mode 100644 gdb/testsuite/gdb.base/builtin_verbose_trap.exp
 create mode 100644 gdb/testsuite/gdb.rocm/builtin_verbose_trap.cpp
 create mode 100644 gdb/testsuite/gdb.rocm/builtin_verbose_trap.exp

diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index 9b23db72bbe..c73b5f66b79 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -2077,6 +2077,32 @@ amd64_init_reg (gdbarch *gdbarch, int regnum, dwarf2_frame_state_reg *reg,
     }
 }
 
+/* Determine whether to show an inline frame.
+   Show verbose trap frames (__clang_trap_msg$...) when SIGILL occurs.  */
+
+static bool
+amd64_linux_should_show_inline_frame (struct gdbarch *gdbarch,
+				      const struct symbol *func,
+				      enum gdb_signal stop_signal)
+{
+  /* Only show verbose trap frames when stopped due to illegal instruction.
+     The ud2 instruction used by verbose traps on x86_64 generates SIGILL.
+     This ensures we only show the frame when the trap actually fired,
+     not when user stepped into it with commands like "step".  */
+  if (stop_signal != GDB_SIGNAL_ILL)
+    return false;
+
+  /* Check if this is a verbose trap inline frame by looking for the
+     compiler-generated function name pattern.  */
+  const char *name = func->linkage_name ();
+  if (name == nullptr)
+    return false;
+
+  /* Verbose trap frames have names like:
+     "__clang_trap_msg$<category>$<message>"  */
+  return startswith (name, "__clang_trap_msg$");
+}
+
 static void
 amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch,
 			     int num_disp_step_buffers)
@@ -2138,6 +2164,12 @@ amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch,
   set_gdbarch_shadow_stack_push (gdbarch, amd64_linux_shadow_stack_push);
   set_gdbarch_get_shadow_stack_pointer (gdbarch,
 					amd64_linux_get_shadow_stack_pointer);
+
+  /* Show verbose trap inline frames when stopped due to illegal
+     instruction.  */
+  set_gdbarch_should_show_inline_frame
+    (gdbarch, amd64_linux_should_show_inline_frame);
+
   dwarf2_frame_set_init_reg (gdbarch, amd64_init_reg);
 }
 
diff --git a/gdb/amdgpu-tdep.c b/gdb/amdgpu-tdep.c
index b0d6023a410..e9e9912ffe7 100644
--- a/gdb/amdgpu-tdep.c
+++ b/gdb/amdgpu-tdep.c
@@ -1041,6 +1041,31 @@ amdgpu_supports_arch_info (const struct bfd_arch_info *info)
   return status == AMD_DBGAPI_STATUS_SUCCESS;
 }
 
+/* Determine whether to show an inline frame.
+   Show verbose trap frames (__clang_trap_msg$...) when SIGABRT occurs.  */
+
+static bool
+amdgpu_should_show_inline_frame (struct gdbarch *gdbarch,
+				 const struct symbol *func,
+				 enum gdb_signal stop_signal)
+{
+  /* Only show verbose trap frames when stopped due to abort signal.
+     This ensures we only show the frame when the trap actually fired,
+     not when user stepped into it with commands like "step".  */
+  if (stop_signal != GDB_SIGNAL_ABRT)
+    return false;
+
+  /* Check if this is a verbose trap inline frame by looking for the
+     compiler-generated function name pattern.  */
+  const char *name = func->linkage_name ();
+  if (name == nullptr)
+    return false;
+
+  /* Verbose trap frames have names like:
+     "__clang_trap_msg$<category>$<message>"  */
+  return startswith (name, "__clang_trap_msg$");
+}
+
 static struct gdbarch *
 amdgpu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -1270,6 +1295,10 @@ amdgpu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_decr_pc_after_break (gdbarch, pc_adjust);
 
+  /* Show verbose trap inline frames when stopped due to abort signal.  */
+  set_gdbarch_should_show_inline_frame (gdbarch,
+					amdgpu_should_show_inline_frame);
+
   return gdbarch_u.release ();
 }
 
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 473a352e781..f691d0f4d14 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -1537,6 +1537,18 @@ core_file_exec_context::environment () const
   return e;
 }
 
+/* See arch-utils.h.  */
+
+/* Default implementation: don't show inline frames.  */
+
+bool
+default_should_show_inline_frame (struct gdbarch *gdbarch,
+				  const struct symbol *func,
+				  enum gdb_signal stop_signal)
+{
+  return false;
+}
+
 INIT_GDB_FILE (gdbarch_utils)
 {
   add_setshow_enum_cmd ("endian", class_support,
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 06902050043..73ca48c3c65 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -410,4 +410,9 @@ extern enum return_value_convention default_gdbarch_return_value
 extern std::optional<CORE_ADDR> default_get_shadow_stack_pointer
   (gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled);
 
+/* Default implementation of gdbarch_should_show_inline_frame.  */
+extern bool default_should_show_inline_frame
+  (struct gdbarch *gdbarch, const struct symbol *func,
+   enum gdb_signal stop_signal);
+
 #endif /* GDB_ARCH_UTILS_H */
diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c
index 6008003466c..a4b9a78e003 100644
--- a/gdb/gdbarch-gen.c
+++ b/gdb/gdbarch-gen.c
@@ -253,6 +253,7 @@ struct gdbarch
   gdbarch_core_parse_exec_context_ftype *core_parse_exec_context = default_core_parse_exec_context;
   gdbarch_shadow_stack_push_ftype *shadow_stack_push = nullptr;
   gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer = default_get_shadow_stack_pointer;
+  gdbarch_should_show_inline_frame_ftype *should_show_inline_frame = default_should_show_inline_frame;
 };
 
 /* Create a new ``struct gdbarch'' based on information provided by
@@ -513,6 +514,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of core_parse_exec_context, invalid_p == 0.  */
   /* Skip verify of shadow_stack_push, has predicate.  */
   /* Skip verify of get_shadow_stack_pointer, invalid_p == 0.  */
+  /* Skip verify of should_show_inline_frame, invalid_p == 0.  */
   if (!log.empty ())
     internal_error (_("verify_gdbarch: the following are invalid ...%s"),
 		    log.c_str ());
@@ -1339,6 +1341,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   gdb_printf (file,
 	      "gdbarch_dump: get_shadow_stack_pointer = <%s>\n",
 	      host_address_to_string (gdbarch->get_shadow_stack_pointer));
+  gdb_printf (file,
+	      "gdbarch_dump: should_show_inline_frame = <%s>\n",
+	      host_address_to_string (gdbarch->should_show_inline_frame));
   if (gdbarch->dump_tdep != nullptr)
     gdbarch->dump_tdep (gdbarch, file);
 }
@@ -5286,3 +5291,20 @@ set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch,
 {
   gdbarch->get_shadow_stack_pointer = get_shadow_stack_pointer;
 }
+
+bool
+gdbarch_should_show_inline_frame (struct gdbarch *gdbarch, const struct symbol *func, enum gdb_signal stop_signal)
+{
+  gdb_assert (gdbarch != nullptr);
+  gdb_assert (gdbarch->should_show_inline_frame != nullptr);
+  if (gdbarch_debug >= 2)
+    gdb_printf (gdb_stdlog, "gdbarch_should_show_inline_frame called\n");
+  return gdbarch->should_show_inline_frame (gdbarch, func, stop_signal);
+}
+
+void
+set_gdbarch_should_show_inline_frame (struct gdbarch *gdbarch,
+				      gdbarch_should_show_inline_frame_ftype should_show_inline_frame)
+{
+  gdbarch->should_show_inline_frame = should_show_inline_frame;
+}
diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
index 6eda8693d58..5f6b9391ee0 100644
--- a/gdb/gdbarch-gen.h
+++ b/gdb/gdbarch-gen.h
@@ -1758,3 +1758,25 @@ void set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch, gdbarch_shadow_stac
 using gdbarch_get_shadow_stack_pointer_ftype = std::optional<CORE_ADDR> (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled);
 std::optional<CORE_ADDR> gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled);
 void set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer);
+
+/* Determine whether an inline frame should be shown in backtraces.
+
+   This hook is called when GDB encounters an inline frame to decide whether
+   it should be displayed to the user or hidden.  By default, inline frames
+   are hidden during normal stepping to provide a source-level debugging
+   experience.  However, some inline frames contain important diagnostic
+   information that should always be visible.
+
+   A common use case is verbose trap frames (e.g., __builtin_verbose_trap)
+   which embed crash diagnostic messages in specially-named inline frames.
+   When such a trap fires, the inline frame should be shown even though
+   inline frames are normally hidden.
+
+   The hook receives the inline frame's symbol and the signal that stopped
+   execution, allowing architecture-specific code to make the decision.
+
+   Return true if the inline frame should be shown, false to hide it. */
+
+using gdbarch_should_show_inline_frame_ftype = bool (struct gdbarch *gdbarch, const struct symbol *func, enum gdb_signal stop_signal);
+bool gdbarch_should_show_inline_frame (struct gdbarch *gdbarch, const struct symbol *func, enum gdb_signal stop_signal);
+void set_gdbarch_should_show_inline_frame (struct gdbarch *gdbarch, gdbarch_should_show_inline_frame_ftype *should_show_inline_frame);
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
index d8b2d114909..d961cb44c7b 100644
--- a/gdb/gdbarch_components.py
+++ b/gdb/gdbarch_components.py
@@ -2789,3 +2789,30 @@ SHADOW_STACK_ENABLED to false.
     predefault="default_get_shadow_stack_pointer",
     invalid=False,
 )
+
+Method(
+    comment="""
+Determine whether an inline frame should be shown in backtraces.
+
+This hook is called when GDB encounters an inline frame to decide whether
+it should be displayed to the user or hidden.  By default, inline frames
+are hidden during normal stepping to provide a source-level debugging
+experience.  However, some inline frames contain important diagnostic
+information that should always be visible.
+
+A common use case is verbose trap frames (e.g., __builtin_verbose_trap)
+which embed crash diagnostic messages in specially-named inline frames.
+When such a trap fires, the inline frame should be shown even though
+inline frames are normally hidden.
+
+The hook receives the inline frame's symbol and the signal that stopped
+execution, allowing architecture-specific code to make the decision.
+
+Return true if the inline frame should be shown, false to hide it.
+""",
+    type="bool",
+    name="should_show_inline_frame",
+    params=[("const struct symbol *", "func"), ("enum gdb_signal", "stop_signal")],
+    predefault="default_should_show_inline_frame",
+    invalid=False,
+)
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index a1ccd4ed0da..ba9ad7c2133 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -28,6 +28,7 @@
 #include "regcache.h"
 #include "symtab.h"
 #include "frame.h"
+#include "gdbarch.h"
 #include "cli/cli-cmds.h"
 #include "cli/cli-style.h"
 #include <algorithm>
@@ -428,10 +429,14 @@ skip_inline_frames (thread_info *thread, bpstat *stop_chain)
      which contains all of the inlined functions, we never skip this.  */
   int skipped_frames = 0;
 
+  struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
+  enum gdb_signal stop_signal = thread->stop_signal ();
+
   for (const auto sym : function_symbols)
     {
       if (stopped_by_user_bp_inline_frame (sym, stop_chain)
-	  || sym == function_symbols.back ())
+	  || sym == function_symbols.back ()
+	  || gdbarch_should_show_inline_frame (gdbarch, sym, stop_signal))
 	break;
 
       ++skipped_frames;
diff --git a/gdb/testsuite/gdb.base/builtin_verbose_trap.cpp b/gdb/testsuite/gdb.base/builtin_verbose_trap.cpp
new file mode 100644
index 00000000000..c1fa495556a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/builtin_verbose_trap.cpp
@@ -0,0 +1,29 @@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+void
+test_trap_function ()
+{
+  int x = 1;
+  __builtin_verbose_trap ("check verbose", "This is verbose trap!");
+}
+
+int
+main ()
+{
+  test_trap_function ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/builtin_verbose_trap.exp b/gdb/testsuite/gdb.base/builtin_verbose_trap.exp
new file mode 100644
index 00000000000..4c51d973d14
--- /dev/null
+++ b/gdb/testsuite/gdb.base/builtin_verbose_trap.exp
@@ -0,0 +1,96 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test that __builtin_verbose_trap inline frames are shown when trap fires.
+# __builtin_verbose_trap is a Clang-only builtin, added in Clang 19.
+
+require {expr {[test_compiler_info clang*]
+	       && ![test_compiler_info {clang-1[0-8]-*}]
+	       && ![test_compiler_info {clang-[1-9]-*}]}}
+
+# Compiler Line Table Bug:
+# Some Clang versions emit incorrect line table information for
+# __builtin_verbose_trap, associating the trap instruction with the
+# previous source line instead of the __builtin_verbose_trap line.
+# This causes GDB to receive the trap signal immediately when stepping past
+# that line, rather than stopping at the __builtin_verbose_trap call first.
+# The tests below use xfail to handle this known compiler issue.
+
+standard_testfile .cpp
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
+    return
+}
+
+if {![runto test_trap_function]} {
+    return
+}
+
+# Continue to trigger the trap.
+gdb_test "continue" \
+    "received signal SIGILL.*" \
+    "received trap signal"
+
+# Verify verbose trap message appears in backtrace.
+gdb_test "bt" \
+    "This is verbose trap.*" \
+    "verbose trap message appears in backtrace"
+
+# Test single stepping to the trap line.
+# Expected: step should stop at __builtin_verbose_trap line, then
+# next step triggers the trap.
+clean_restart $testfile
+
+if {![runto_main]} {
+    return
+}
+
+# Set breakpoint at "int x = 1" line to avoid line table ambiguity
+# when running to the test function.
+set line_x [gdb_get_line_number "int x = 1"]
+gdb_breakpoint "$srcfile:$line_x"
+gdb_test "continue" "Breakpoint.*$line_x.*" "run to line $line_x"
+
+# Check for compiler line table bug using info line.
+# If the __builtin_verbose_trap line shows "contains no code",
+# the trap instruction is not mapped to that line (bug exists).
+set has_line_table_bug 0
+set line_trap [gdb_get_line_number "__builtin_verbose_trap"]
+
+gdb_test_multiple "info line $line_trap" "" {
+    -re "contains no code" {
+	set has_line_table_bug 1
+	exp_continue
+    }
+    -re -wrap "" {
+	pass $gdb_test_name
+    }
+}
+
+gdb_test_multiple "next" "step to trap line" {
+    -re -wrap "SIGILL.*" {
+	if {$has_line_table_bug} {
+	    xfail "$gdb_test_name (compiler line table bug)"
+	} else {
+	    fail "$gdb_test_name"
+	}
+    }
+    -re -wrap "__builtin_verbose_trap.*" {
+	pass $gdb_test_name
+
+	# Next step should trigger the trap.
+	gdb_test "next" "SIGILL.*" "step triggers trap"
+    }
+}
diff --git a/gdb/testsuite/gdb.rocm/builtin_verbose_trap.cpp b/gdb/testsuite/gdb.rocm/builtin_verbose_trap.cpp
new file mode 100644
index 00000000000..09e3d922920
--- /dev/null
+++ b/gdb/testsuite/gdb.rocm/builtin_verbose_trap.cpp
@@ -0,0 +1,34 @@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+   Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <hip/hip_runtime.h>
+
+__global__ void
+test_trap_kernel ()
+{
+  int x = 1;
+  __builtin_verbose_trap ("check verbose", "This is verbose trap!");
+}
+
+int
+main ()
+{
+  test_trap_kernel<<<1, 1>>> ();
+  return hipDeviceSynchronize () != hipSuccess;
+}
diff --git a/gdb/testsuite/gdb.rocm/builtin_verbose_trap.exp b/gdb/testsuite/gdb.rocm/builtin_verbose_trap.exp
new file mode 100644
index 00000000000..3440070733b
--- /dev/null
+++ b/gdb/testsuite/gdb.rocm/builtin_verbose_trap.exp
@@ -0,0 +1,98 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
+
+# This file is part of GDB.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test that __builtin_verbose_trap PC is correctly adjusted.
+
+load_lib rocm.exp
+require allow_hip_tests
+
+# Compiler Line Table Bug:
+# Some Clang versions emit incorrect line table information for
+# __builtin_verbose_trap, associating the trap instruction
+# with the previous source line instead of the __builtin_verbose_trap line.
+# This causes GDB to receive the trap signal immediately when stepping past
+# that line, rather than stopping at the __builtin_verbose_trap call first.
+# The tests below use xfail to handle this known compiler issue.
+
+standard_testfile .cpp
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug hip}]} {
+    return
+}
+
+with_rocm_gpu_lock {
+    if {![runto test_trap_kernel -allow-pending]} {
+	return
+    }
+
+    # Continue to trigger the trap.
+    gdb_test "continue" \
+	"received signal SIGABRT.*" \
+	"received trap signal"
+
+    # Check PC points to trap instruction.
+    gdb_test "x/i \$pc" \
+	"s_trap.*" \
+	"PC points to trap instruction"
+
+    # Verify verbose trap message appears in backtrace.
+    gdb_test "bt" \
+	"This is verbose trap.*" \
+	"verbose trap message appears in backtrace"
+
+    # Test single stepping to the trap line.
+    # Expected: step should stop at __builtin_verbose_trap line, then
+    # next step triggers the trap.
+    clean_restart $testfile
+
+    if {![runto test_trap_kernel -allow-pending]} {
+	return
+    }
+
+    # Check for compiler line table bug using info line.
+    # If the __builtin_verbose_trap line shows "contains no code",
+    # the trap instruction is not mapped to that line (bug exists).
+    set has_line_table_bug 0
+    set line_trap [gdb_get_line_number "__builtin_verbose_trap"]
+
+    gdb_test_multiple "info line $line_trap" "" {
+	-re "contains no code" {
+	    set has_line_table_bug 1
+	    exp_continue
+	}
+	-re -wrap "" {
+	    pass $gdb_test_name
+	}
+    }
+
+    gdb_test_multiple "next" "step to trap line" {
+	-re -wrap "SIGABRT.*" {
+	    if {$has_line_table_bug} {
+		xfail "$gdb_test_name (compiler line table bug)"
+	    } else {
+		fail "$gdb_test_name"
+	    }
+	}
+	-re -wrap "__builtin_verbose_trap.*" {
+	    pass $gdb_test_name
+
+	    # Next step should trigger the trap.
+	    gdb_test "next" "SIGABRT.*" "step triggers trap"
+	}
+    }
+}
-- 
2.43.0


                 reply	other threads:[~2026-09-21 12:42 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260921123852.11526-1-bfilipov@amd.com \
    --to=bfilipov@amd.com \
    --cc=gdb-patches@sourceware.org \
    --cc=pedro@palves.net \
    --cc=simon.marchi@polymtl.ca \
    --cc=six.lancelot@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox