From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id Ud6pLD3htGqL3zsAWB0awg (envelope-from ) for ; Thu, 24 Sep 2026 04:37:17 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=Qj+nTjyf; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id B21C51E06B; Thu, 24 Sep 2026 04:37:17 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 8D5891E033 for ; Thu, 24 Sep 2026 04:37:15 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9DF034BB3BFF for ; Thu, 24 Sep 2026 08:37:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9DF034BB3BFF Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=Qj+nTjyf Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) by sourceware.org (Postfix) with ESMTPS id 261044BB589D for ; Thu, 24 Sep 2026 08:35:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 261044BB589D Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 261044BB589D Authentication-Results: sourceware.org; arc=none smtp.remote-ip=192.198.163.14 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1790238903; cv=none; b=CuJJ77AABG574e0V8L/OXTujtOIx43HnDtVLahAbGa2R9LzwBXEyTtaI2d8pmTbBvuDmmogxwNMsAHQL1GbFpsYyyq7H39nPVPDatBReTsgXXG7IQ9UfE+CKodV/eIpdNMM7lmXIWPHIjk/vP82CXZSixIz5KbKYREkjfmQwgjk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1790238903; c=relaxed/simple; bh=wz5fqVKvdQ9NmyNaYHLfrtANgIyGwS+6XNafWpp39TM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=FD4Li9p242TL6s8lroVMh8+kWZg/JDH2JCwLXl2R/Q60k+ts4DkMDpnxEXEG+BwuyRYBM9TCi0k6fRqa5lKht6lsiX3ofujN3ypaJL6fFoC+T3uL4eRPtJIWuIKc/6MT5/PR3Bpsgr9MDErseXTEqHzm/qC+0rgXEtEVgpPrURU= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=Qj+nTjyf DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 261044BB589D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1790238904; x=1821774904; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wz5fqVKvdQ9NmyNaYHLfrtANgIyGwS+6XNafWpp39TM=; b=Qj+nTjyffaWWc4BcxuvWmzrWcLqDcY6wI1L1gM8OxUYayChkgtS6UEUe 6ykbZ/muLhXIJRfy/tI95XGTxAEXYAVBUA7koOLNgAHqnH3syfrWfMCBR G7gvBXCSgthH505EAL0fTTUPUWKAC3auPnuQ+XYy3rGjKydjDxJNVUBCA 30t9X5v9VH0xz5eX/h8Vms/8vyH+6OrC0HAJcRF218eDNDfgxhfwapyjY tlPo97vpdWZFPSZGgx0ebFtgVDuyWr7p9NhoKWeXo7XLdMmpSkP65AoQm 5V0J/XEOWjjpZmXRK4ogqII6S9OiIb5CP7TB3Fknb94rMj0Ee93RvPq6K A==; X-CSE-ConnectionGUID: EreaHzOQQ+m6ffSBCkpfOw== X-CSE-MsgGUID: rtpENaOhQAyeIKbZOAtIBg== X-IronPort-AV: E=McAfee;i="6800,10657,11914"; a="91021401" X-IronPort-AV: E=Sophos;i="6.27,120,1787036400"; d="scan'208";a="91021401" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Sep 2026 01:35:03 -0700 X-CSE-ConnectionGUID: u2xz9zDfQPSEXbUz4d7sag== X-CSE-MsgGUID: tdeUA2bbQOiItABqHB0aDA== X-ExtLoop1: 1 Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Sep 2026 01:35:01 -0700 From: Christina Joos To: gdb-patches@sourceware.org Cc: thiago.bauermann@linaro.org, tom@tromey.com, luis.machado.foss@gmail.com Subject: [PATCH v5 12/13] gdb: Enable signal trampolines in the shadow stack backtrace. Date: Thu, 24 Sep 2026 10:33:09 +0200 Message-ID: <20260924083311.1961530-13-christina.joos@intel.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260924083311.1961530-1-christina.joos@intel.com> References: <20260924083311.1961530-1-christina.joos@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Similar to the normal backtrace we now print "" in the shadow stack backtrace, too. ~~~ (gdb) bt -shadow /#0 /#1 /#2 0x00007ffff7c4527e in __GI_raise at ../sysdeps/posix/raise.c:26 /#3 0x0000555555555175 in main at /tmp/gdb.arch/amd64-shadow-stack-signal.c:29 (gdb) bt /#0 handler (signo=10) at /tmp/amd64-shadow-stack-signal.c:23 /#1 /#2 __pthread_kill_implementation (no_tid=0, signo=10, threadid=) at ./nptl/pthread_kill.c:44 /#3 __pthread_kill_internal (signo=10, threadid=) at ./nptl/pthread_kill.c:78 /#4 __GI___pthread_kill (threadid=, signo=signo@entry=10) at ./nptl/pthread_kill.c:89 /#5 0x00007ffff7c4527e in __GI_raise (sig=10) at ../sysdeps/posix/raise.c:26 /#6 0x0000555555555175 in main () at /tmp/amd64-shadow-stack-signal.c:29 ~~~ Reviewed-by: Thiago Jung Bauermann --- gdb/amd64-linux-tdep.c | 36 +++++++++++-------- gdb/gdbarch-gen.c | 32 +++++++++++++++++ gdb/gdbarch-gen.h | 11 ++++++ gdb/gdbarch_components.py | 13 +++++++ gdb/shadow-stack.c | 11 ++++++ gdb/shadow-stack.h | 5 +++ .../amd64-shadow-stack-backtrace-signal.exp | 2 +- 7 files changed, 95 insertions(+), 15 deletions(-) diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 49609e5ac94..8a7a1ed371c 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -147,12 +147,10 @@ static const gdb_byte amd64_x32_linux_sigtramp_code[] = the routine. Otherwise, return 0. */ static CORE_ADDR -amd64_linux_sigtramp_start (const frame_info_ptr &this_frame) +amd64_linux_sigtramp_start (gdbarch *gdbarch, CORE_ADDR pc) { - struct gdbarch *gdbarch; const gdb_byte *sigtramp_code; - CORE_ADDR pc = get_frame_pc (this_frame); - gdb_byte buf[LINUX_SIGTRAMP_LEN]; + std::array buf {}; /* We only recognize a signal trampoline if PC is at the start of one of the two instructions. We optimize for finding the PC at @@ -161,7 +159,7 @@ amd64_linux_sigtramp_start (const frame_info_ptr &this_frame) PC is not at the start of the instruction sequence, there will be a few trailing readable bytes on the stack. */ - if (!safe_frame_unwind_memory (this_frame, pc, buf)) + if (target_read_memory (pc, buf.data (), buf.size ()) != 0) return 0; if (buf[0] != LINUX_SIGTRAMP_INSN0) @@ -170,28 +168,25 @@ amd64_linux_sigtramp_start (const frame_info_ptr &this_frame) return 0; pc -= LINUX_SIGTRAMP_OFFSET1; - if (!safe_frame_unwind_memory (this_frame, pc, buf)) + if (target_read_memory (pc, buf.data (), buf.size ()) != 0) return 0; } - gdbarch = get_frame_arch (this_frame); if (gdbarch_ptr_bit (gdbarch) == 32) sigtramp_code = amd64_x32_linux_sigtramp_code; else sigtramp_code = amd64_linux_sigtramp_code; - if (memcmp (buf, sigtramp_code, LINUX_SIGTRAMP_LEN) != 0) + if (memcmp (buf.data (), sigtramp_code, LINUX_SIGTRAMP_LEN) != 0) return 0; return pc; } -/* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp - routine. */ +/* Return whether PC is pointing to a GNU/Linux sigtramp routine. */ static int -amd64_linux_sigtramp_p (const frame_info_ptr &this_frame) +amd64_linux_is_sigtramp_pc (gdbarch* gdbarch, const CORE_ADDR pc) { - CORE_ADDR pc = get_frame_pc (this_frame); const char *name; find_pc_partial_function (pc, &name, NULL, NULL); @@ -203,11 +198,22 @@ amd64_linux_sigtramp_p (const frame_info_ptr &this_frame) __sigaction, or __libc_sigaction (all aliases to the same function). */ if (name == NULL || strstr (name, "sigaction") != NULL) - return (amd64_linux_sigtramp_start (this_frame) != 0); + return (amd64_linux_sigtramp_start (gdbarch, pc) != 0); return (streq ("__restore_rt", name)); } +/* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp + routine. */ + +static int +amd64_linux_sigtramp_frame_p (const frame_info_ptr &this_frame) +{ + gdbarch *gdbarch = get_frame_arch (this_frame); + CORE_ADDR pc = get_frame_pc (this_frame); + return amd64_linux_is_sigtramp_pc (gdbarch, pc); +} + /* Offset to struct sigcontext in ucontext, from . */ #define AMD64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40 @@ -2026,7 +2032,7 @@ amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch, linux_init_abi (info, gdbarch, num_disp_step_buffers); - tdep->sigtramp_p = amd64_linux_sigtramp_p; + tdep->sigtramp_p = amd64_linux_sigtramp_frame_p; tdep->sigcontext_addr = amd64_linux_sigcontext_addr; tdep->sc_reg_offset = amd64_linux_sc_reg_offset; tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset); @@ -2084,6 +2090,8 @@ amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch, set_gdbarch_is_no_return_shadow_stack_address (gdbarch, amd64_linux_is_no_return_shadow_stack_address); + + set_gdbarch_is_sigtramp_pc (gdbarch, amd64_linux_is_sigtramp_pc); } static void diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c index 894522a7243..3d30a4e2902 100644 --- a/gdb/gdbarch-gen.c +++ b/gdb/gdbarch-gen.c @@ -257,6 +257,7 @@ struct gdbarch gdbarch_top_addr_empty_shadow_stack_ftype *top_addr_empty_shadow_stack = nullptr; int shadow_stack_element_size_aligned = 8; gdbarch_is_no_return_shadow_stack_address_ftype *is_no_return_shadow_stack_address = nullptr; + gdbarch_is_sigtramp_pc_ftype *is_sigtramp_pc = nullptr; }; /* Create a new ``struct gdbarch'' based on information provided by @@ -521,6 +522,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of top_addr_empty_shadow_stack, has predicate. */ /* Skip verify of shadow_stack_element_size_aligned, invalid_p == 0. */ /* Skip verify of is_no_return_shadow_stack_address, has predicate. */ + /* Skip verify of is_sigtramp_pc, has predicate. */ if (!log.empty ()) internal_error (_("verify_gdbarch: the following are invalid ...%s"), log.c_str ()); @@ -1365,6 +1367,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) gdb_printf (file, "gdbarch_dump: is_no_return_shadow_stack_address = <%s>\n", host_address_to_string (gdbarch->is_no_return_shadow_stack_address)); + gdb_printf (file, + "gdbarch_dump: gdbarch_is_sigtramp_pc_p() = %d\n", + gdbarch_is_sigtramp_pc_p (gdbarch)); + gdb_printf (file, + "gdbarch_dump: is_sigtramp_pc = <%s>\n", + host_address_to_string (gdbarch->is_sigtramp_pc)); if (gdbarch->dump_tdep != nullptr) gdbarch->dump_tdep (gdbarch, file); } @@ -5394,3 +5402,27 @@ set_gdbarch_is_no_return_shadow_stack_address (struct gdbarch *gdbarch, { gdbarch->is_no_return_shadow_stack_address = is_no_return_shadow_stack_address; } + +bool +gdbarch_is_sigtramp_pc_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != nullptr); + return gdbarch->is_sigtramp_pc != nullptr; +} + +int +gdbarch_is_sigtramp_pc (struct gdbarch *gdbarch, const CORE_ADDR pc) +{ + gdb_assert (gdbarch != nullptr); + gdb_assert (gdbarch->is_sigtramp_pc != nullptr); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_is_sigtramp_pc called\n"); + return gdbarch->is_sigtramp_pc (gdbarch, pc); +} + +void +set_gdbarch_is_sigtramp_pc (struct gdbarch *gdbarch, + gdbarch_is_sigtramp_pc_ftype is_sigtramp_pc) +{ + gdbarch->is_sigtramp_pc = is_sigtramp_pc; +} diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index 08358b18fcf..e78aad9a89b 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -1814,3 +1814,14 @@ bool gdbarch_is_no_return_shadow_stack_address_p (struct gdbarch *gdbarch); using gdbarch_is_no_return_shadow_stack_address_ftype = std::optional (struct gdbarch *gdbarch, const CORE_ADDR ssp, const CORE_ADDR value, const unsigned long level); std::optional gdbarch_is_no_return_shadow_stack_address (struct gdbarch *gdbarch, const CORE_ADDR ssp, const CORE_ADDR value, const unsigned long level); void set_gdbarch_is_no_return_shadow_stack_address (struct gdbarch *gdbarch, gdbarch_is_no_return_shadow_stack_address_ftype *is_no_return_shadow_stack_address); + +/* Return whether PC is pointing to a sigtramp routine. This is needed in + addition to tdep->sigtramp_p, which requires a frame, because some callers + (e.g. the shadow stack backtrace command) only have a return address + available. */ + +bool gdbarch_is_sigtramp_pc_p (struct gdbarch *gdbarch); + +using gdbarch_is_sigtramp_pc_ftype = int (struct gdbarch *gdbarch, const CORE_ADDR pc); +int gdbarch_is_sigtramp_pc (struct gdbarch *gdbarch, const CORE_ADDR pc); +void set_gdbarch_is_sigtramp_pc (struct gdbarch *gdbarch, gdbarch_is_sigtramp_pc_ftype *is_sigtramp_pc); diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index e8677d641bb..16737efe3a0 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -2872,3 +2872,16 @@ backtrace. Otherwise, return an empty optional. ], predicate=True, ) + +Method( + comment=""" +Return whether PC is pointing to a sigtramp routine. This is needed in +addition to tdep->sigtramp_p, which requires a frame, because some callers +(e.g. the shadow stack backtrace command) only have a return address +available. +""", + type="int", + name="is_sigtramp_pc", + params=[("const CORE_ADDR", "pc")], + predicate=True, +) diff --git a/gdb/shadow-stack.c b/gdb/shadow-stack.c index a31bb02bceb..86633cbcb49 100644 --- a/gdb/shadow-stack.c +++ b/gdb/shadow-stack.c @@ -267,6 +267,8 @@ do_print_shadow_stack_frame_info } else if (frame.type == ssp_frame_type::dummy_frame) str = ""; + else if (frame.type == ssp_frame_type::sigtramp_frame) + str = ""; else gdb_assert_not_reached ("Invalid shadow stack frame type."); @@ -480,6 +482,15 @@ get_shadow_stack_frame_info if (sal_arch == nullptr) sal_arch = fallback_arch; + if (gdbarch_is_sigtramp_pc_p (sal_arch) + && gdbarch_is_sigtramp_pc (sal_arch, value)) + { + return std::optional + ({ssp, value, level, sal_arch, sal, + ssp_frame_type::sigtramp_frame, {}, + ssp_unwind_stop_reason::no_error}); + } + return std::optional ({ssp, value, level, sal_arch, sal, ssp_frame_type::normal_frame, {}, diff --git a/gdb/shadow-stack.h b/gdb/shadow-stack.h index 225fd3996cd..d4b0d53acf3 100644 --- a/gdb/shadow-stack.h +++ b/gdb/shadow-stack.h @@ -80,6 +80,11 @@ enum class ssp_frame_type /* A fake frame, created by GDB when performing an inferior function call. */ dummy_frame, + + /* A shadow stack frame containing a return address which is in a signal + handler, similar to the SIGTRAMP_FRAME frame type in + frame.h:frame_type. */ + sigtramp_frame, }; /* Information of a shadow stack frame belonging to a shadow stack element diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp b/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp index 21373dc07f3..34559f0bd04 100644 --- a/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp +++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp @@ -41,7 +41,7 @@ save_vars { ::env(GLIBC_TUNABLES) } { # Test shadow stack backtrace including . gdb_test "bt -shadow" \ [multi_line \ - "#0\[ \t\]*$hex in \[^\r\n\]+" \ + "#0\[ \t\]*" \ "#1\[ \t\]*" \ "#2\[ \t\]*$hex in \[^\r\n\]+" \ ".*" ] \ -- 2.53.0 ________________________________________ Intel Deutschland GmbH Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany Tel: +49 (89) 99143-0 www.intel.de Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman Chairperson of the Supervisory Board: Sonja Pierer Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928 This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.