Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Christina Schimpe <christina.schimpe@intel.com>
To: gdb-patches@sourceware.org
Cc: thiago.bauermann@linaro.org
Subject: [PATCH v2 8/9] gdb: Implement the hook 'is_no_return_shadow_stack_address' for amd64 linux.
Date: Fri, 23 Jan 2026 08:05:30 +0000	[thread overview]
Message-ID: <20260123080532.878738-9-christina.schimpe@intel.com> (raw)
In-Reply-To: <20260123080532.878738-1-christina.schimpe@intel.com>

[-- Attachment #1: Type: text/plain, Size: 6839 bytes --]

There can be elements on the shadow stack which are not return addresses.
This can happen, for instance, in case of signals on amd64 linux.
The old shadow stack pointer is pushed in a special format with bit 63 set.

|1...old SSP| - Pointer to old pre-signal ssp in sigframe token format
                (bit 63 set to 1)

Linux kernel documentation: https://docs.kernel.org/arch/x86/shstk.html

Implement the gdbarch hook is_no_return_shadow_stack_address to detect
this scenario to print the shadow stack backtrace correctly.
---
 gdb/amd64-linux-tdep.c                        | 55 ++++++++++++++++++-
 .../amd64-shadow-stack-backtrace-signal.exp   | 49 +++++++++++++++++
 .../gdb.arch/amd64-shadow-stack-signal.c      | 31 +++++++++++
 3 files changed, 134 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp
 create mode 100644 gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c

diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index a4eabccf667..b517f9772f5 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1986,6 +1986,56 @@ amd64_linux_get_shadow_stack_size
   return shadow_stack_bytes / 8;
 }
 
+/* Return true, if FRAME is a valid shadow stack frame while FRAME.VALUE
+   does not refer to a return address.  This can happen, for instance, in
+   case of signals.  The old shadow stack pointer is pushed in a special
+   format with bit 63 set.  In case this is true, configure the string
+   which describes the frame and is displayed instead of the address in
+   the shadow stack backtrace.  */
+
+static bool
+amd64_linux_is_no_return_shadow_stack_address
+  (gdbarch *gdbarch,
+   const shadow_stack_frame_info &frame,
+   std::string &frame_type)
+{
+  /* FRAME must be a valid shadow stack frame.  */
+  std::pair<CORE_ADDR, CORE_ADDR> range;
+  gdb_assert (gdbarch_address_in_shadow_stack_memory_range (gdbarch,
+							    frame.ssp,
+							    &range));
+
+  /* In case bit 63 is not configured, the address on the shadow stack
+     should be a return address.  */
+  constexpr CORE_ADDR mask = (CORE_ADDR) 1 << 63;
+  if ((frame.value & mask) == 0)
+    return false;
+
+  /* To compare the shadow stack pointer of the previous frame with the
+     value of FRAME, we must clear bit 63.  */
+  CORE_ADDR shadow_stack_val_cleared = (frame.value & (~mask));
+
+  /* Compute the previous/old SSP.  The shadow stack grows downwards.  To
+     compute the previous shadow stack pointer, we need to increment
+     FRAME.SSP.  */
+  CORE_ADDR prev_ssp
+    = frame.ssp + gdbarch_shadow_stack_element_size_aligned (gdbarch);
+
+  /* We incremented FRAME.SSP by one element to compute PREV_SSP before.
+     In case FRAME.SSP points to the first element of the shadow stack,
+     PREV_SSP must point to the bottom of the shadow stack (RANGE.SECOND),
+     but not beyond that address.  */
+  gdb_assert (prev_ssp > range.first && prev_ssp <= range.second);
+
+  if (shadow_stack_val_cleared == prev_ssp)
+    {
+      frame_type = _("<sigframe token>");
+      return true;
+    }
+
+  return false;
+}
+
 static void
 amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch,
 			     int num_disp_step_buffers)
@@ -2049,9 +2099,12 @@ amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch,
 
   set_gdbarch_top_addr_empty_shadow_stack
     (gdbarch, amd64_linux_top_addr_empty_shadow_stack);
- 
+
   set_gdbarch_get_shadow_stack_size
     (gdbarch, amd64_linux_get_shadow_stack_size);
+
+  set_gdbarch_is_no_return_shadow_stack_address
+    (gdbarch, amd64_linux_is_no_return_shadow_stack_address);
 }
 
 static void
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp b/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp
new file mode 100644
index 00000000000..21373dc07f3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp
@@ -0,0 +1,49 @@
+# Copyright 2024-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 shadow stack backtrace for signal handling on linux.
+
+require allow_ssp_tests {istarget "*-*-linux*"}
+
+standard_testfile amd64-shadow-stack-signal.c
+
+save_vars { ::env(GLIBC_TUNABLES) } {
+
+    append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
+
+    if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+	  {debug additional_flags="-fcf-protection=return"}] } {
+	return
+    }
+
+    if { ![runto_main] } {
+	return
+    }
+
+    gdb_breakpoint "handler"
+    gdb_test "continue" \
+	".*Program received signal SIGUSR1, User defined signal 1.*" \
+	"continue until signal"
+    gdb_continue_to_breakpoint "continue to breakpoint in handler"
+
+    # Test shadow stack backtrace including <sigframe token>.
+    gdb_test "bt -shadow" \
+	[multi_line \
+	    "#0\[ \t\]*$hex in \[^\r\n\]+" \
+	    "#1\[ \t\]*<sigframe token>" \
+	    "#2\[ \t\]*$hex in \[^\r\n\]+" \
+	    ".*" ] \
+	"test shadow stack backtrace for signal handling."
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c b/gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c
new file mode 100644
index 00000000000..c726e05b224
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2024-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/>.  */
+
+#include <signal.h>
+
+void
+handler (int signo)
+{
+}
+
+int
+main (void)
+{
+  signal (SIGUSR1, handler);
+  raise (SIGUSR1);
+  return 0;
+}
-- 
2.34.1


[-- Attachment #2.1: Type: text/plain, Size: 329 bytes --]

Intel Deutschland GmbH
Registered Address: Dornacher Straße 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht München HRB 186928

[-- Attachment #2.2: Type: text/html, Size: 387 bytes --]

  parent reply	other threads:[~2026-01-23  8:07 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-23  8:05 [PATCH v2 0/9] Add new command to print the shadow stack backtrace Christina Schimpe
2026-01-23  8:05 ` [PATCH v2 1/9] gdb: Generalize handling of the shadow stack pointer Christina Schimpe
2026-02-19 17:55   ` Tom Tromey
2026-02-27 18:09     ` Schimpe, Christina
2026-02-27 18:26       ` Tom Tromey
2026-03-02 11:53         ` Schimpe, Christina
2026-04-09  9:49           ` Schimpe, Christina
2026-04-14 17:34             ` Tom Tromey
2026-04-15  7:35               ` Schimpe, Christina
2026-04-15 15:54                 ` Tom Tromey
2026-02-27 22:54       ` Thiago Jung Bauermann
2026-03-06  3:15   ` Thiago Jung Bauermann
2026-03-06  3:57     ` Thiago Jung Bauermann
2026-04-09 11:57       ` Schimpe, Christina
2026-04-10  5:03         ` Thiago Jung Bauermann
2026-04-10  7:53           ` Schimpe, Christina
2026-04-09 12:06   ` Schimpe, Christina
2026-04-10  5:05     ` Thiago Jung Bauermann
2026-01-23  8:05 ` [PATCH v2 2/9] gdb: Refactor 'stack.c:print_frame' Christina Schimpe
2026-01-23  8:05 ` [PATCH v2 3/9] gdb: Introduce 'stack.c:print_pc' function without frame argument Christina Schimpe
2026-01-23  8:05 ` [PATCH v2 4/9] gdb: Refactor 'find_symbol_funname' and 'info_frame_command_core' in stack.c Christina Schimpe
2026-02-19 17:32   ` Tom Tromey
2026-04-09 12:40     ` Schimpe, Christina
2026-01-23  8:05 ` [PATCH v2 5/9] gdb: Refactor 'stack.c:print_frame_info' Christina Schimpe
2026-01-23  8:05 ` [PATCH v2 6/9] gdb: Add command option 'bt -shadow' to print the shadow stack backtrace Christina Schimpe
2026-01-23  8:52   ` Eli Zaretskii
2026-02-13 16:42     ` Schimpe, Christina
2026-04-14  8:43       ` Schimpe, Christina
2026-04-14 11:53         ` Eli Zaretskii
2026-04-14 13:28           ` Schimpe, Christina
2026-04-14 14:12             ` Eli Zaretskii
2026-04-14 15:05               ` Schimpe, Christina
2026-02-19 18:19   ` Tom Tromey
2026-04-09 16:48     ` Schimpe, Christina
2026-03-06  4:31   ` Thiago Jung Bauermann
2026-03-06  9:39     ` Schimpe, Christina
2026-04-09 15:12     ` Schimpe, Christina
2026-04-10  6:21       ` Thiago Jung Bauermann
2026-04-10 12:12         ` Schimpe, Christina
2026-01-23  8:05 ` [PATCH v2 7/9] gdb: Provide gdbarch hook to distinguish shadow stack backtrace elements Christina Schimpe
2026-01-23  8:47   ` Eli Zaretskii
2026-02-19 17:41   ` Tom Tromey
2026-01-23  8:05 ` Christina Schimpe [this message]
2026-02-19 17:43   ` [PATCH v2 8/9] gdb: Implement the hook 'is_no_return_shadow_stack_address' for amd64 linux Tom Tromey
2026-01-23  8:05 ` [PATCH v2 9/9] gdb, mi: Add -shadow-stack-list-frames command Christina Schimpe
2026-01-23  8:46   ` Eli Zaretskii
2026-02-13 19:17     ` Schimpe, Christina
2026-02-19 18:26   ` Tom Tromey
2026-03-02 12:39 ` [PATCH v2 0/9] Add new command to print the shadow stack backtrace Schimpe, Christina

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=20260123080532.878738-9-christina.schimpe@intel.com \
    --to=christina.schimpe@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=thiago.bauermann@linaro.org \
    /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