From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id TwFTIFmpX2hqXyMAWB0awg (envelope-from ) for ; Sat, 28 Jun 2025 04:35:37 -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=BfPhqYHu; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 78DA41E11E; Sat, 28 Jun 2025 04:35:37 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-10.1 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, RCVD_IN_VALIDITY_RPBL,RCVD_IN_VALIDITY_SAFE autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (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 681CE1E089 for ; Sat, 28 Jun 2025 04:35:35 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0D5C2385C41B for ; Sat, 28 Jun 2025 08:35:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0D5C2385C41B 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=BfPhqYHu Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) by sourceware.org (Postfix) with ESMTPS id 7F2DB3856DF0 for ; Sat, 28 Jun 2025 08:29:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7F2DB3856DF0 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 7F2DB3856DF0 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1751099354; cv=none; b=nFoaifjnJm4zLi3xGCJ0PiWCAsDutJx6EJifq32hikmKIJCXY34WXoZ8Dsi3/kEnS7qKFh3ob1diMuVHNVNF/E8wTXDEdSvz79mEzpnAp7HZxNOnCy967jvk/acR/lacd2sYChHUkwb6OO8cEeO/DPcroj1i3BSoOqH9PejoVHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1751099354; c=relaxed/simple; bh=qnWUeFWOpgyLNZQt28Lycr6MKgGbzpUWnEenrLH3Diw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=YWsmEp6gi0hXVJDyd7iY7g5ES5Rn3jEYgQ6KAc+Iqt20zfCRge6RxUfMTGbYhilifS+7HndzTkR68OrHZhZYWq1cCPu8hH5Ao7poQRVxdkUC8vIoo7DecQUVef/Vrs3KsE5vBqO6+X8AmaV36kS6O5bZ3Kj/mxmMTfMUHmAN8BY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7F2DB3856DF0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1751099350; x=1782635350; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qnWUeFWOpgyLNZQt28Lycr6MKgGbzpUWnEenrLH3Diw=; b=BfPhqYHuDLZ7M74z+tKRIF6PIGwYQiPfkxuYV5QP5Okqfm5bva55IWwX xZLaF0fG95vpbdsP9PxfIfXUFMiBlDTR7WhxusnMziMJsoCOyIREBHkbe KtWv3ULinX27yf2duAl3uHvIu/mP2GBvFLsuBVF8agxCNX6puSxK294EC 7I5v8+YkaAD1E/W7cyIawkH5U3gojIA2El14rvr2mhjqZgSTboZ4ztUjv u1KNK5iRwAI7oSRBYuqxBx95/hZWG/kOtn57NhvJFtB5gLDc/WqJERFJu rYWslXRek7/usMKIMFlpFoVqiJge50FXVpszyay85AIQn9mwNmASFd9n+ g==; X-CSE-ConnectionGUID: apjvEio1Q/CKf18OkCFmEA== X-CSE-MsgGUID: Unn46weuTUiJGdb0fiBP7Q== X-IronPort-AV: E=McAfee;i="6800,10657,11477"; a="53271321" X-IronPort-AV: E=Sophos;i="6.16,272,1744095600"; d="scan'208";a="53271321" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2025 01:29:09 -0700 X-CSE-ConnectionGUID: lCVR8EFXR4O0CdhBsU7u/A== X-CSE-MsgGUID: jfoBDmv+Sz2jBpBCQKzYUA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,272,1744095600"; d="scan'208";a="183917681" Received: from 0007e934a912.jf.intel.com (HELO localhost) ([10.165.58.208]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jun 2025 01:29:08 -0700 From: Christina Schimpe To: gdb-patches@sourceware.org Cc: thiago.bauermann@linaro.org, luis.machado@arm.com Subject: [PATCH v5 09/12] gdb, gdbarch: Enable inferior calls for shadow stack support. Date: Sat, 28 Jun 2025 01:28:07 -0700 Message-ID: <20250628082810.332526-10-christina.schimpe@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250628082810.332526-1-christina.schimpe@intel.com> References: <20250628082810.332526-1-christina.schimpe@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Inferior calls in GDB reset the current PC to the beginning of the function that is called. As no call instruction is executed the new return address needs to be pushed to the shadow stack and the shadow stack pointer needs to be updated. This commit adds a new gdbarch method to push an address on the shadow stack. The method is used to adapt the function 'call_function_by_hand_dummy' for inferior call shadow stack support. Reviewed-by: Thiago Jung Bauermann Reviewed-By: Luis Machado --- gdb/gdbarch-gen.c | 32 ++++++++++++++++++++++++++++++++ gdb/gdbarch-gen.h | 14 ++++++++++++++ gdb/gdbarch_components.py | 16 ++++++++++++++++ gdb/infcall.c | 14 ++++++++++---- 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c index fc570d37a8d..a4b72793fd8 100644 --- a/gdb/gdbarch-gen.c +++ b/gdb/gdbarch-gen.c @@ -262,6 +262,7 @@ struct gdbarch gdbarch_read_core_file_mappings_ftype *read_core_file_mappings = default_read_core_file_mappings; gdbarch_use_target_description_from_corefile_notes_ftype *use_target_description_from_corefile_notes = default_use_target_description_from_corefile_notes; gdbarch_core_parse_exec_context_ftype *core_parse_exec_context = default_core_parse_exec_context; + gdbarch_shadow_stack_push_ftype *shadow_stack_push = nullptr; }; /* Create a new ``struct gdbarch'' based on information provided by @@ -535,6 +536,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of read_core_file_mappings, invalid_p == 0. */ /* Skip verify of use_target_description_from_corefile_notes, invalid_p == 0. */ /* Skip verify of core_parse_exec_context, invalid_p == 0. */ + /* Skip verify of shadow_stack_push, has predicate. */ if (!log.empty ()) internal_error (_("verify_gdbarch: the following are invalid ...%s"), log.c_str ()); @@ -1406,6 +1408,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) gdb_printf (file, "gdbarch_dump: core_parse_exec_context = <%s>\n", host_address_to_string (gdbarch->core_parse_exec_context)); + gdb_printf (file, + "gdbarch_dump: gdbarch_shadow_stack_push_p() = %d\n", + gdbarch_shadow_stack_push_p (gdbarch)); + gdb_printf (file, + "gdbarch_dump: shadow_stack_push = <%s>\n", + host_address_to_string (gdbarch->shadow_stack_push)); if (gdbarch->dump_tdep != NULL) gdbarch->dump_tdep (gdbarch, file); } @@ -5551,3 +5559,27 @@ set_gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, { gdbarch->core_parse_exec_context = core_parse_exec_context; } + +bool +gdbarch_shadow_stack_push_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->shadow_stack_push != NULL; +} + +void +gdbarch_shadow_stack_push (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->shadow_stack_push != NULL); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_shadow_stack_push called\n"); + gdbarch->shadow_stack_push (gdbarch, new_addr, regcache); +} + +void +set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch, + gdbarch_shadow_stack_push_ftype shadow_stack_push) +{ + gdbarch->shadow_stack_push = shadow_stack_push; +} diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index 281b97b7aa8..71142332540 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -1802,3 +1802,17 @@ extern void set_gdbarch_use_target_description_from_corefile_notes (struct gdbar typedef core_file_exec_context (gdbarch_core_parse_exec_context_ftype) (struct gdbarch *gdbarch, bfd *cbfd); extern core_file_exec_context gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, bfd *cbfd); extern void set_gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, gdbarch_core_parse_exec_context_ftype *core_parse_exec_context); + +/* Some targets support special hardware-assisted control-flow protection + technologies. For example, the Intel Control-Flow Enforcement Technology + (Intel CET) on x86 provides a shadow stack and indirect branch tracking. + To enable shadow stack support for inferior calls the shadow_stack_push + gdbarch hook has to be provided. + + Push NEW_ADDR to the shadow stack and update the shadow stack pointer. */ + +extern bool gdbarch_shadow_stack_push_p (struct gdbarch *gdbarch); + +typedef void (gdbarch_shadow_stack_push_ftype) (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache); +extern void gdbarch_shadow_stack_push (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache); +extern void set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch, gdbarch_shadow_stack_push_ftype *shadow_stack_push); diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index 91c867e69bf..abc79588473 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -2848,3 +2848,19 @@ which all assume current_inferior() is the one to read from. predefault="default_core_parse_exec_context", invalid=False, ) + +Method( + comment=""" +Some targets support special hardware-assisted control-flow protection +technologies. For example, the Intel Control-Flow Enforcement Technology +(Intel CET) on x86 provides a shadow stack and indirect branch tracking. +To enable shadow stack support for inferior calls the shadow_stack_push +gdbarch hook has to be provided. + +Push NEW_ADDR to the shadow stack and update the shadow stack pointer. +""", + type="void", + name="shadow_stack_push", + params=[("CORE_ADDR", "new_addr"), ("regcache *", "regcache")], + predicate=True, +) diff --git a/gdb/infcall.c b/gdb/infcall.c index 2b5936d1621..db6d6774367 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -1448,10 +1448,16 @@ call_function_by_hand_dummy (struct value *function, /* Create the dummy stack frame. Pass in the call dummy address as, presumably, the ABI code knows where, in the call dummy, the return address should be pointed. */ - sp = gdbarch_push_dummy_call (gdbarch, function, - get_thread_regcache (inferior_thread ()), - bp_addr, args.size (), args.data (), - sp, return_method, struct_addr); + regcache *regcache = get_thread_regcache (inferior_thread ()); + sp = gdbarch_push_dummy_call (gdbarch, function, regcache, bp_addr, + args.size (), args.data (), sp, + return_method, struct_addr); + + /* Push the return address of the inferior (bp_addr) to the shadow stack + and update the shadow stack pointer. As we don't execute a call + instruction to call the function we need to handle this manually. */ + if (gdbarch_shadow_stack_push_p (gdbarch)) + gdbarch_shadow_stack_push (gdbarch, bp_addr, regcache); /* Set up a frame ID for the dummy frame so we can pass it to set_momentary_breakpoint. We need to give the breakpoint a frame -- 2.43.0