From patchwork Wed Jun 18 05:54:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897539 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp135135wrb; Tue, 17 Jun 2025 22:57:07 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUIBxxG2urNwa1HJ3jSXWQXfGNwTz0KILfjpVN5m+jBRzke84x/awfeJVGz1pAuEl9qxrZswg==@linaro.org X-Google-Smtp-Source: AGHT+IFqMKrajNcNN6hCrf+LKOwYjGHU4rzFhjHQ0jN0uvFo+Ba4cd929rEMPAlx1Pg6AiwQkJEB X-Received: by 2002:a05:620a:4385:b0:7c4:bca3:6372 with SMTP id af79cd13be357-7d3e9219e34mr259331485a.0.1750226226514; Tue, 17 Jun 2025 22:57:06 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226226; cv=pass; d=google.com; s=arc-20240605; b=Q4xGzxPu4/PeDjtkSagnQLmxnXubrl5ebGLp1gwCU8GiCnDOfKLwGMevNgDxxCG9Um rzSL2DOtMszwGg6Yd7Yl4XGfF08iSzeC+orTagufgp/LhMRPAVlsxm7bZhd0kMjNppj/ /RONoqkWqp5Lc0spw4faQkaTAVF6OshEt8UZlcjNZuCYU99ZK4+6iYPEyMhmdhq8IUOA D6MJ+LuPl49X01CtutflaZCuMKdc7IOHxtaNdN36V4iMB+6PLxdpKORZ3jT6SbVcYWVM P3F6pU0WCEHrjJA5bQ8EnBCl2vOXg4MV7+NixcVweXna3NbWzxydkqmM3LEbXWRu2H+U NK+g== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=TFZwSzq/KDbGqApCaY7nwS7NEJ592QNeaA48FD4nUyo=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=P8RmKCn5irFTUjgrGRrs7dFMTkdoNr6a8vsPkVI8YeeiLPBymNBQ/BToz/FVaXAIxF NJ2RVFssO9azUEdOw7+3TKrxjX0txHW/33GSnYNq3prpTWOlAYEI1K3Z+SACPYOw4ftx 1OrfKmPLqeLkcNeHBbTP91IX/qoO8wu/WklFF93x7XN0iZ7pimIp157+x/5rihFJs1VS XI+0ZmiA2WgnR/itjuIOuxt+Y1tHgbr0i+OWv5uQRPbtuvh3s+OXvatZproW7csAOXZA VJ4s1lu5PHA8QQTc5/D1CUTuRlIoti8ucjR3k7YOGeYxVlakEjJlOHHS28gcGPZAecwe 0LXA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=d0ZECguQ; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7d3b8ef3ec8si1368891285a.393.2025.06.17.22.57.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:57:06 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=d0ZECguQ; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B55193835C25 for ; Wed, 18 Jun 2025 05:57:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B55193835C25 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=d0ZECguQ X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pg1-x535.google.com (mail-pg1-x535.google.com [IPv6:2607:f8b0:4864:20::535]) by sourceware.org (Postfix) with ESMTPS id 389763835C25 for ; Wed, 18 Jun 2025 05:54:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 389763835C25 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 389763835C25 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::535 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226092; cv=none; b=byF9V6uJVGP2qpJ3+hMdyHfJSsJB44SXs6xw2zwEW7BTx4NISc7EqBIwm5JSqYduOhjThMGXDFcM+lh/Q9W+A6YuHNWPUf8OZr0hkwQOPBgTO4oeSDR4Vi5aP7YjP/bfrVqzBkP//OktWZL90ZRjWOdiVIl3FvRhVfByAkeXJmA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226092; c=relaxed/simple; bh=1rJftsMxCQzy/QNhjpamBDi/m3aCMOlBnDvqvXuLXtQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=oTTY+iQi2Zt/jDhKqPqocdftNpIwWUHzmuA9I62stLtvymTdVdODScq1JMbiizTsyODyQh0NllOrk0XBrUWw4FRp07b2PbzJMDcDsR33rwGovehfHnGUWmMYwYRJiRm8BK+PSuuFjSCjg80g4CbVVp5ZyW/9MNviUSl/YzoWKbk= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 389763835C25 Received: by mail-pg1-x535.google.com with SMTP id 41be03b00d2f7-b2c4476d381so308506a12.0 for ; Tue, 17 Jun 2025 22:54:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226091; x=1750830891; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TFZwSzq/KDbGqApCaY7nwS7NEJ592QNeaA48FD4nUyo=; b=d0ZECguQnWOXPZdfV9tMAQYLCbumBVgksktNhlASa9UT4/gCIuWhUZmwMS3HlyA1AX ok9Rba/vwWUgxuwks5VUJ44NotNYtHl1m6gCqyPWu2RCRGJxP9mrjEFHQdHr2jnoeoMz KpA31oP05bXS2cRzDkzK/S7yS5FzrV2ShP6ytHJTW5pu0DFTSyWERnp/dcT/+bwo6yC/ HIAKgTZVdaSdzAemzsletXGejqOAzpTPcvlXTrmgIiHuvExl1oeWTGPlVgstVBxI7ogn VLRf7S0mbwIHTjZzO2j2eekuZ0sF5LHvrBCREly3zXDjRSlgytSkiTyXdM1lOYVxdpzG Wxmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226091; x=1750830891; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TFZwSzq/KDbGqApCaY7nwS7NEJ592QNeaA48FD4nUyo=; b=f14EmwDCi8vbmnFjJ/1XXh5SrGBHvXTDWYuaqPqPUMs6niJ9NhJciKXkOV7d2vJX6b PvRT3aQW0gZx90zK0VYpm8hdGaZoqMV5QyOYQnjeeq+TdhWS276f4cMzsLdY686QGkUg fXwpQCxZriu9V5Q7zSScIvNMlBpDb+pgznI//JyPAMSDZ1QS+9VoolrrLcArwNk16VeI jNkO17zFKDtrpSUslv+ATIQRBEYzSGF5qik/qiSap6bRnY4i8pmmvR2xaMsAtTMyuDUd tOFthqeMP4PQ5OYFVQk2fy120xGhnQEohwFzlVkXK6/KNIdx6PpzDy9NyPYXggX8vO8i e0vw== X-Gm-Message-State: AOJu0YwAvTe2+AdFIjV3YquGacKhIdHgCcyCiUOii8B4m9WwuOmR25Po 1s//gDLbybrWffY5B778LcRTIjHI269kf26sADKkanmdSsoNHw3YpnkVp1S4hJmJXMWPZh+ptbY c+SIr X-Gm-Gg: ASbGncs0ibF9LGc5aWz2F22FRQo20ZZ5pQ0OFcvUqLfz6Zd/Wktwe+fHEayL5AK28MT CgC/CQ38riaDG57ZpeWdS9/9zShUx8EiwI+b01snQKLVyVXb1CAFmeqA2BV/yQsV2Bs8ukcfHJB rLOQYYUjgbXDhIgZEbcaH8T8igtmyGeSEijYXIojHlBMC0vILFlDuljY1XA2F/C/DfYSXx8VdKk NyOnmQ7JMLQ7BaVMjfgMKWclFCp7ffDLd1s6m5ZEbpyjPWFQTSTiqdo6d0zxzLxhCkhKXdu3AgF JPnM3tM3WEj+Gi7qQD4zXJtHjeVueGOpFT9m8Uk8/wwCXXDMfy1zxF25LwpoJh0yAiCn X-Received: by 2002:a17:90b:3c48:b0:311:ab20:1591 with SMTP id 98e67ed59e1d1-3157c86a744mr2164125a91.15.1750226091072; Tue, 17 Jun 2025 22:54:51 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-313c1c5e2ebsm11782643a91.33.2025.06.17.22.54.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:54:50 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 1/9] GDB: Linux: Add function linux_address_in_shadow_stack_mem_range Date: Wed, 18 Jun 2025 02:54:37 -0300 Message-ID: <20250618055445.709416-2-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org From: Christina Schimpe The function comes from the following patch from the Intel CET shadow stack support series: [PATCH v4 07/11] gdb: Handle shadow stack pointer register unwinding for amd64 linux. AArch64 also needs the function for unwinding the GCSPR, so include it in this patch series. Abridged-by: Thiago Jung Bauermann --- gdb/linux-tdep.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/linux-tdep.h | 7 +++++++ 2 files changed, 54 insertions(+) This is the patch mentioned above: https://inbox.sourceware.org/gdb-patches/20250617121147.1956686-8-christina.schimpe@intel.com/ Minus the change in amd64-linux-tdep.c and the testcase. Patch 8 in this series adds the corresponding AArch64 change and testcase. diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 1e339b59e2e8..c532b8758bfa 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -47,6 +47,7 @@ #include "gdbsupport/unordered_map.h" #include +#include /* This enum represents the values that the user can choose when informing the Linux kernel about which memory mappings will be @@ -96,6 +97,10 @@ struct smaps_vmflags /* Memory map has memory tagging enabled. */ unsigned int memory_tagging : 1; + + /* Memory map used for shadow stack. */ + + unsigned int shadow_stack_memory : 1; }; /* Data structure that holds the information contained in the @@ -537,6 +542,8 @@ decode_vmflags (char *p, struct smaps_vmflags *v) v->shared_mapping = 1; else if (strcmp (s, "mt") == 0) v->memory_tagging = 1; + else if (strcmp (s, "ss") == 0) + v->shadow_stack_memory = 1; } } @@ -3036,6 +3043,46 @@ show_dump_excluded_mappings (struct ui_file *file, int from_tty, " flag is %s.\n"), value); } +/* See linux-tdep.h. */ + +bool +linux_address_in_shadow_stack_mem_range + (CORE_ADDR addr, std::pair *range) +{ + if (!target_has_execution () || current_inferior ()->fake_pid_p) + return false; + + const int pid = current_inferior ()->pid; + + std::string smaps_file = string_printf ("/proc/%d/smaps", pid); + + gdb::unique_xmalloc_ptr data + = target_fileio_read_stralloc (nullptr, smaps_file.c_str ()); + + if (data == nullptr) + return false; + + const std::vector smaps + = parse_smaps_data (data.get (), std::move (smaps_file)); + + auto find_addr_mem_range = [&addr] (const smaps_data &map) + { + bool addr_in_mem_range + = (addr >= map.start_address && addr < map.end_address); + return (addr_in_mem_range && map.vmflags.shadow_stack_memory); + }; + auto it = std::find_if (smaps.begin (), smaps.end (), find_addr_mem_range); + + if (it != smaps.end ()) + { + range->first = it->start_address; + range->second = it->end_address; + return true; + } + + return false; +} + /* To be called from the various GDB_OSABI_LINUX handlers for the various GNU/Linux architectures and machine types. diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h index 7485fc132a63..7083635b976c 100644 --- a/gdb/linux-tdep.h +++ b/gdb/linux-tdep.h @@ -117,4 +117,11 @@ extern CORE_ADDR linux_get_hwcap2 (); extern struct link_map_offsets *linux_ilp32_fetch_link_map_offsets (); extern struct link_map_offsets *linux_lp64_fetch_link_map_offsets (); +/* Returns true if ADDR belongs to a shadow stack memory range. If this + is the case, assign the shadow stack memory range to RANGE + [start_address, end_address). */ + +extern bool linux_address_in_shadow_stack_mem_range + (CORE_ADDR addr, std::pair *range); + #endif /* GDB_LINUX_TDEP_H */ From patchwork Wed Jun 18 05:54:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897536 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp135008wrb; Tue, 17 Jun 2025 22:56:36 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCU2wQas66xBlG6uH5B0Tx7z5X86av+ARCESITRb8czBqemqtg4ImUHb/Z5V0cja5K2LKFlMdA==@linaro.org X-Google-Smtp-Source: AGHT+IHGJKzawbRiS69hhl13+/q/0U62c0hdM+92gUFXdT381GXkAAkgUAnQxCmDWnyirxvhr0xE X-Received: by 2002:a05:620a:8086:b0:7d0:9d42:732b with SMTP id af79cd13be357-7d3c6c1926dmr2320502585a.20.1750226196339; Tue, 17 Jun 2025 22:56:36 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226196; cv=pass; d=google.com; s=arc-20240605; b=BCZNViX/FYsB7cRpI2Sq2P30mreDK4+o9rqHY0uprt3RTAeOgVTfAualz0wwQxgy7J ab2hzU4e6ypmlQp92OZBLvM17wI16aLUqfWjAo2z5McdenAbhcVuHCPIjWQEuzwoBVAb LcdgxmdMBOd+gIOOo3wQGidFhbKe1kLioW6jfb0NZeycYWtraxHvGd83AlbwsfM8IhdR 14UKdiOupoOzsWPVDUqGI55Y4waJupUroIe/h3FJz0nRdt+Fzkk8GUHmuGxlKymISu+p OhQL7RwqmBu2h4OmtTpvnS+jJWMMGKlhsa7S9jrRlEOjeHv18dbcITmh5iJ4dMBemszw Binw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=Cwa3a0aO5PRnNnEND/5n7yTE5tzZdW23MiQzhCdjdbM=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=PmgXdXfgXsJapkNgDBFKVUeL8BOMZgWMh8aZ41o05yEN2BEb7XpPQLqoQF1C6fum/i DoIAIzc8ZXHd7WGpHmM3TumDcYUErvTmwqtbv2qVJh/wvq8n9kB326YDkNFPBsGXp+Iz NPZdLhaOGwf7XqqHIx9m1RDx20gf+pJkWQJDZY2nGHoq6Bufl5lQm8jWrUpooIiVxq+g s3PwscJlqHuY2Vl54gDBgmdDJ1+rLX3xaTVhzztHNojWDYjzWmvENz2PTX0ekD3kH7WL ff7OIvahLrm9sCG70/woTPdWtcliy+YqsLITBM1f/Vd4XMaACjQyZWBrnwFFkeRU2WGk firg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="RZ/g+NPS"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id 6a1803df08f44-6fb561aa6ddsi61872686d6.211.2025.06.17.22.56.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:56:36 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="RZ/g+NPS"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E17803816949 for ; Wed, 18 Jun 2025 05:56:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E17803816949 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=RZ/g+NPS X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x62b.google.com (mail-pl1-x62b.google.com [IPv6:2607:f8b0:4864:20::62b]) by sourceware.org (Postfix) with ESMTPS id 25F1D381694A for ; Wed, 18 Jun 2025 05:54:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 25F1D381694A Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 25F1D381694A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226095; cv=none; b=gjsV/aB0GfsMJSChTFTgZ+zU96PzwvmkljrkywNU/4Wi6QLK9v3TPLTU4CLH5ylti6Yt1V+ASgf62KxzeoUF+NuMSH1p7SQWdk69jXqO09UVyNvcE6vWVmVyGffHDs8xTXOIMSduorTkGzRhsJt/sg3ktoRR3H6nN7hAx5G/5Tk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226095; c=relaxed/simple; bh=/j4tTrKMSRuf7aeU93UdHnQ+z/GlpjKDDdd0DzGs/Rw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=TCRQ6ulb1ayhxgj0CBRwlOLxUcem4NCQBeZ+tQAO2Ai2O0QeLcAbReq3CtfLyWh/0s9y5dPdxDX1Erw5ZUvQi8u82r64dgd4Mr7IoZpvhPYfNtyVJ2ZM7rYenxiYMNjPlxNdrr//qxmyu8Y9tlpRjFmhGDC2fjryF6iN5j0YTJo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 25F1D381694A Received: by mail-pl1-x62b.google.com with SMTP id d9443c01a7336-235e1d710d8so81138675ad.1 for ; Tue, 17 Jun 2025 22:54:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226094; x=1750830894; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Cwa3a0aO5PRnNnEND/5n7yTE5tzZdW23MiQzhCdjdbM=; b=RZ/g+NPS4bOfsZ4zSW82rofqMFJeHIBbMGMdGo3zT1sXZfPwRsc46h/l93nsWrFBcM YA9NFUAJVIkOieIbylihXwXYQfyh2dakTVdQzwkmWwC+YvZKSPCEYYDS+efE+4rYc4xD oewQc2+Zl7hco8GRv0EW32gex58Ikf5QGtNfWgVuscBXhaPMP5yowVshSDgVrHDIgu0i LGtKfUVQ9DBRzapa9dZ9p/nrtUBozOu4ZqEHwVIIkuHmqew0virdNKMT+9RPdjo8LrOE q73fzvrz3l5XsJY44OT5vqTDeKq1PDqTxoap0UlX3fHXoNEnjnGLNtPDRsQnU7pZ4tog 4knw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226094; x=1750830894; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Cwa3a0aO5PRnNnEND/5n7yTE5tzZdW23MiQzhCdjdbM=; b=Ihi0PhTE4fczif/rfbXE/mi2cnewIe9P453E25QWsSc8uZ7lnx6Hu2GZLLCWDoKV7N uLM56b31aAgHEK6sL8gI1RAD8FLzvgRR8W4bSn9wjSzSdqf+saACzBNzl08JzP90R6Zp JUtpK6sZOWFbjz/QIuMm0tN8iEgDVLMugfn3gHpzNhd9yE7vMqwqsCXIZGS84KdL7FPb mW4CT2T8mL8o8jMVEF67KBhhmz4Xy/LhvTyjcJ7jQ+VEyzP7znEDMV0FjF33Zs2HoNBF FirqKRx69+j5zrFTeX42i9Vuz4BZwO8+M7KuS5A92fBmvVrCvNg+MAIHZ4oFlrYI6tqa mb6Q== X-Gm-Message-State: AOJu0YxHo34GqHBOnd1Gbh/fRygyE2rM0eLFDTPQ0AXY0F2paFbxYGeB fRVpr3HNq/JdzIatRCfwKMqho35UklWOJkpeH0ZKd4S+hJFcAqLkTQhnfuPHtJ1+8RCyKB2FO8k JFGHw X-Gm-Gg: ASbGnctrbPNSxLGjsm8xAPezVcNCGwFoaKurCRrv/ab5l4gkevHBkJhiNJCxAJSGEUl 4veP4GhLytyNIn8KfrV3vp+RzW3noyCMdAy2kO1/RyP32jym7XXfKYNd3ljFJ1rMJArwyYUOMTs n4jVTpEO4vC669ldsQWUvZNzlpbl5srZyh064dNJtZeC0w5MkAvv9CQG3gMESSK9FTdFGC/ATp2 y1dzmjZi+uujtkorb5L+wFUcHgCnjtesgjtKjI2X3fTULjc44BiDv0nj875fwUzzPeVG6ZWUhAB /xUVi3Ur1WryxL0ATFiQgxGZrSyfyzYwioWeBcA0/6NRANdV3bH9O6rxfcugAQ9DMT6wDKjdAVl bTs4= X-Received: by 2002:a17:90b:3843:b0:313:176b:3d4b with SMTP id 98e67ed59e1d1-313f1ce5d1fmr20428195a91.22.1750226093843; Tue, 17 Jun 2025 22:54:53 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-313c1c4e3b9sm13268315a91.29.2025.06.17.22.54.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:54:53 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 2/9] gdb, gdbarch: Enable inferior calls for shadow stack support. Date: Wed, 18 Jun 2025 02:54:38 -0300 Message-ID: <20250618055445.709416-3-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org From: Christina Schimpe 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 --- 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(-) This is exactly: [PATCH v4 08/11] gdb, gdbarch: Enable inferior calls for shadow stack support. https://inbox.sourceware.org/gdb-patches/20250617121147.1956686-9-christina.schimpe@intel.com/ diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c index 32d16598940b..3ca19c427a31 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 313a8f198fdb..c276cd66d716 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -1801,3 +1801,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 inferior calls the function shadow_stack_push has to be provided. + + Push the address NEW_ADDR on 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 ec09d9550889..ab685b14ec7d 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 inferior calls the function shadow_stack_push has to be provided. + +Push the address NEW_ADDR on 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 098072dfd2aa..a1c80c812380 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) on the shadow stack + and update the shadow stack pointer. As we don't execute a call + instruction to start the inferior 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 From patchwork Wed Jun 18 05:54:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897540 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp135154wrb; Tue, 17 Jun 2025 22:57:12 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVS2Gm6PckNk14+B5cA3Tm5qlS7BEWxWFYY7vSQXJArReo7SglebXlwJptiPKS0sI+WkYOEmQ==@linaro.org X-Google-Smtp-Source: AGHT+IHsLrgTCXZqkDvY1mHIXKQhUcCqop8cNTZIPLQ+rFPTQicwQxfh8rS0PDwA/dm7PooXpuph X-Received: by 2002:a05:622a:316:b0:4a6:f587:ade2 with SMTP id d75a77b69052e-4a73c4bece2mr272767801cf.18.1750226232037; Tue, 17 Jun 2025 22:57:12 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226232; cv=pass; d=google.com; s=arc-20240605; b=lsD+/87qMheGM6yQMccgoTUHYku/vOvZyvOkkR4Wpzw5xkeh0BKeWj55chuV+6fxM9 496lNe6rp3aOvKnxO/TVow5jWzi+Zpz9gCTSpTKeORcHphshYaRI/0u0q49k0sIYWeH3 rwyIkpYuQBk5qQq9HBBFMX4IleM9nPm8qTn2lb8MMwvgIpZ75K/isgiVoMEWCsTYyLPG eTZgRJp6imWN3l61B8OTdQVcIr14H+dZk229gAbHOmKBEwXTYmV8WWrolT32+X7fvpF+ BckP8jQHEfueNp8gaBjrOsuZBfS9qqc9ULjNhPXzfIR9qdYtIlUQd7HnXbkcrchaKLTw nYtg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=8y5ObXPHryGjUlxYenCRlE0BCBBW6Wsi8+LlIvBecTQ=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=EjAV8tkfwqJ5y97nS0PFEcgVN8/JG6BDwLe0zYThSFOEBYap8c3Y8fbPzjje1Plzpz sc8rGXTd1S7xXBrX+jgcTvBXoqp1UoAQot43fJcTWNBaPmqlgUUIto6cqs+KQA8jS51W B4fLX9gnA0HlvcKC1IRoO905QcV8ToTS+LlMdEEv2CzU2nmrUX+4ZDvBeaSTjVYOm8Wj /dm7TtyAhmoqA/owS4ju20CcShT27PtYQLK3SY1xASnAz9U0WRHVc+qGeMBhpAmnDpw9 jQTNuHiFhFNRhOJRcioJXSbU7FuYdeUyZNIo99iA+kxTStZ/bXHXhrOPA6NTCbsZUmjt Iyag==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ll07CNox; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id d75a77b69052e-4a72a4b1e5bsi135275591cf.309.2025.06.17.22.57.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:57:12 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ll07CNox; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 634673858C24 for ; Wed, 18 Jun 2025 05:57:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 634673858C24 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=ll07CNox X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by sourceware.org (Postfix) with ESMTPS id 5C9F83858C24 for ; Wed, 18 Jun 2025 05:54:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5C9F83858C24 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 5C9F83858C24 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::434 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226098; cv=none; b=N6pEwC85SBSLz+g3MOHBwV0n+tigK70ZW2BLXcyu7AsHqNAFL755/aeMun7v5VSm00UQW5HKQLiZ9QM23PF483XAy7/4XUIPh9Gh8ekqX1/y26NpN1sSZS4196RtJ+x9VybWXGTjMu4/b9CgCC7CPNNefh2B1FMez5onSXqLoWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226098; c=relaxed/simple; bh=hH5hHTjpH6ueJ4Q0kcRndynfmQlWfho3Sk4Fm1kPcMo=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=n8rZTcDSilRhk9nfb64oAGXpXcgVhsPteJUgzEZqlPp2qyBwXJRYZXagjO4tYWwzAM0IwDPVu7PtNvFq6L+FzpglO70smZLiiOS2M3LY8bTFrvYmSPoOsR+zWj14tyqV9cFgvcMAN/m3IQmytPBqE1l76mQp3mRI3c0grTrs3zk= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5C9F83858C24 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-74264d1832eso7307424b3a.0 for ; Tue, 17 Jun 2025 22:54:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226097; x=1750830897; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8y5ObXPHryGjUlxYenCRlE0BCBBW6Wsi8+LlIvBecTQ=; b=ll07CNoxRCqqTQ/DzDNWS6vO3Ok2jzjnXRKsEVdTHPS7V9hf+VEsydRThQz5As/0aO DD248OyPxzFHFE0MwTIdQkIb/1twoySKh8aABdPdXHeJ9mm8apGcYFkmNcM6wTZfe+jI TV9Oirrm8ZkmLlAmWF1dyiYP/9EUGOD4q+/5okARGlup2ElEHHbY6/GDWBBFu4+vSy8J gyaUVsIg+qb31230RlVNbUu3p1CpGap8pfuLL/2Pc3Eoe+T6mQT3Y+8rdhHIy9jTu8Ai kScl1GiS6cn6ghF7FGWPkCSjVtYX+/eOc3mIDFJXeMPiZ2hHfcLJOjKowRY7jApzb+6q iZxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226097; x=1750830897; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8y5ObXPHryGjUlxYenCRlE0BCBBW6Wsi8+LlIvBecTQ=; b=LtGqV9OCFD6gddYmp4uh3xQ1hZe7xpSM/uPP1lZWmO0Ym/PVwMPeRpnTwJsvLg/Q/o 08d2Pv2d8j5wEpVlHvBuZDl2eWL8t8ryzEOPR/fQv/qMalq+uvB6qlKi0CXZDJ6SGJpf JJhXkCo7HqrjjHgQBugwqiLe9Kb1I3Og+kEq7F70Gr04au54mnnRtD1zFMPUcYxWiYv6 HFbn4MaeFj9UBxr4HsoPBw3OvRWDH/YJi7oJfna5/4YFKfAeSHmGXR9AZHd9Kyymk8e7 RekmMofA2fGQ+PJ44RtI/+ZQWlXT8DawBEpQqsIV4Xf9iir9je/MdOivu0GeZWWCMWxB J6fw== X-Gm-Message-State: AOJu0Yz22hZV4yFicFeM7OkQF4RWZYQkg3qNqwfMu8eBwnUV6m39i62w RfgbZo43QqWAd3ivozJt+IcjnGA14FvEx8239pf6tmWUJVGYAACsgxLsnPQGt9v4Oel1h63VcIR KDWU/ X-Gm-Gg: ASbGnctIUCwVJTCZXDmXV6p/+dwt5cfnZ3V3eKmiZwrw8ZlyNYea0VajYSYIHRP7dmF jdMzmc5tNDaknjxRBFzsaqiPA+o0IbG/L2wvu2BYoHLMnIXhHyWk5/0eWEV8fktiZvCb0dy7C6q LTp978Y/tqAfpJCg2eI7mqEWkpDBFM08567SgkNY9zn85hD8k2s5+aj6C5FLBqiaZJrknYNx5t0 fJYpiiboDysAAqD11Vrmu+KDcSgHwf68eVXx7lDkp07/khMJEY6RrgakPkeMOZRI07N69opFzz6 w8A/Sun3AF2SwsHkwlWI4Rd7XDLHClom6mNpp28w6VUDaBHuvTlph1wUz4PYYUgcokuknWlnSs/ YACg= X-Received: by 2002:a05:6a00:f8b:b0:742:da7c:3f30 with SMTP id d2e1a72fcca58-7489cfde786mr22910468b3a.19.1750226097296; Tue, 17 Jun 2025 22:54:57 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-74890006294sm10046351b3a.47.2025.06.17.22.54.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:54:56 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 3/9] gdb, gdbarch: Introduce gdbarch method to get the shadow stack pointer. Date: Wed, 18 Jun 2025 02:54:39 -0300 Message-ID: <20250618055445.709416-4-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org From: Christina Schimpe This patch is required by the following commit. Reviewed-by: Thiago Jung Bauermann --- gdb/arch-utils.c | 10 ++++++++++ gdb/arch-utils.h | 5 +++++ gdb/gdbarch-gen.c | 22 ++++++++++++++++++++++ gdb/gdbarch-gen.h | 10 ++++++++++ gdb/gdbarch_components.py | 15 +++++++++++++++ 5 files changed, 62 insertions(+) This is exactly: [PATCH v4 10/11] gdb, gdbarch: Introduce gdbarch method to get the shadow stack pointer. https://inbox.sourceware.org/gdb-patches/20250617121147.1956686-11-christina.schimpe@intel.com/ diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index be0494fba1e3..c86df72a6d84 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -1218,6 +1218,16 @@ default_gdbarch_return_value readbuf, writebuf); } +/* See arch-utils.h. */ + +std::optional +default_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache, + bool &shadow_stack_enabled) +{ + shadow_stack_enabled = false; + return {}; +} + obstack *gdbarch_obstack (gdbarch *arch) { return &arch->obstack; diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index 1509cb7441e6..14a84b747332 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -414,4 +414,9 @@ extern enum return_value_convention default_gdbarch_return_value struct regcache *regcache, struct value **read_value, const gdb_byte *writebuf); +/* Default implementation of gdbarch default_get_shadow_stack_pointer + method. */ +extern std::optional default_get_shadow_stack_pointer + (gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled); + #endif /* GDB_ARCH_UTILS_H */ diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c index 3ca19c427a31..4490d53a940a 100644 --- a/gdb/gdbarch-gen.c +++ b/gdb/gdbarch-gen.c @@ -263,6 +263,7 @@ struct gdbarch 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; + gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer = default_get_shadow_stack_pointer; }; /* Create a new ``struct gdbarch'' based on information provided by @@ -537,6 +538,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* 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. */ + /* Skip verify of get_shadow_stack_pointer, invalid_p == 0. */ if (!log.empty ()) internal_error (_("verify_gdbarch: the following are invalid ...%s"), log.c_str ()); @@ -1414,6 +1416,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) gdb_printf (file, "gdbarch_dump: shadow_stack_push = <%s>\n", host_address_to_string (gdbarch->shadow_stack_push)); + gdb_printf (file, + "gdbarch_dump: get_shadow_stack_pointer = <%s>\n", + host_address_to_string (gdbarch->get_shadow_stack_pointer)); if (gdbarch->dump_tdep != NULL) gdbarch->dump_tdep (gdbarch, file); } @@ -5583,3 +5588,20 @@ set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch, { gdbarch->shadow_stack_push = shadow_stack_push; } + +std::optional +gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->get_shadow_stack_pointer != NULL); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_get_shadow_stack_pointer called\n"); + return gdbarch->get_shadow_stack_pointer (gdbarch, regcache, shadow_stack_enabled); +} + +void +set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, + gdbarch_get_shadow_stack_pointer_ftype get_shadow_stack_pointer) +{ + gdbarch->get_shadow_stack_pointer = get_shadow_stack_pointer; +} diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index c276cd66d716..b8d1df94f598 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -1806,6 +1806,8 @@ extern void set_gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, gdbarc technologies. For example, the Intel Control-Flow Enforcement Technology (Intel CET) on x86 provides a shadow stack and indirect branch tracking. To enable inferior calls the function shadow_stack_push has to be provided. + The method get_shadow_stack_pointer has to be provided to enable displaced + stepping. Push the address NEW_ADDR on the shadow stack and update the shadow stack pointer. */ @@ -1815,3 +1817,11 @@ 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); + +/* If possible, return the shadow stack pointer. On some architectures, the + shadow stack pointer is available even if the feature is disabled. To + return the shadow stack enablement state configure SHADOW_STACK_ENABLED. */ + +typedef std::optional (gdbarch_get_shadow_stack_pointer_ftype) (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled); +extern std::optional gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled); +extern void set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer); diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index ab685b14ec7d..ccbdcaf07c97 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -2855,6 +2855,8 @@ 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 inferior calls the function shadow_stack_push has to be provided. +The method get_shadow_stack_pointer has to be provided to enable displaced +stepping. Push the address NEW_ADDR on the shadow stack and update the shadow stack pointer. @@ -2864,3 +2866,16 @@ pointer. params=[("CORE_ADDR", "new_addr"), ("regcache *", "regcache")], predicate=True, ) + +Method( + comment=""" +If possible, return the shadow stack pointer. On some architectures, the +shadow stack pointer is available even if the feature is disabled. To +return the shadow stack enablement state configure SHADOW_STACK_ENABLED. +""", + type="std::optional", + name="get_shadow_stack_pointer", + params=[("regcache *", "regcache"), ("bool &", "shadow_stack_enabled")], + predefault="default_get_shadow_stack_pointer", + invalid=False, +) From patchwork Wed Jun 18 05:54:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897538 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp135098wrb; Tue, 17 Jun 2025 22:56:57 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXYzWxLqaYO+FQuHmsGEdpX4cjMZ1a/kOoY0v4bU6uv8mkO164McLDx4bT+Tk/n1ha09YuSKA==@linaro.org X-Google-Smtp-Source: AGHT+IHyuMlinZNSe/CQ/HFrwivYhisIGnw/JtxyvYUObI+v2xg9D4mq5QkOy9MAzPi3uwfXehu7 X-Received: by 2002:a05:622a:1a29:b0:476:6cd3:d898 with SMTP id d75a77b69052e-4a73c4ca299mr261903141cf.18.1750226217478; Tue, 17 Jun 2025 22:56:57 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226217; cv=pass; d=google.com; s=arc-20240605; b=O5M3Uu+m6xdVwmvYzT4Vzx8aZx889paoCWCf+l5dXwBcCyf9jUtI5e2HRJ7qDqCyIh z9QmDaMh/v3tM4+YsciO6LIHXL7tJN6UxhJnCPQg7US3i1OPqCNmQ8Ff8dlNrXCxDMf/ I+E8pPdG1cBnlf/t+0WWIt6SOqOw4yHSjSNKQgP2Af2296O6Bmyhx86fbSFCWHayMdKi 1F25XN8tU03J7gtB2pfq841Ts6PlslEdL9R/6/HPqqrD0vZql3/KHNuLFgt+Rd0yn2VN cmH4bPU2w0JGU2pDUvSanSVBEmrG9OYaJACLLbB8Wjb1l4IOZVbHOJJ1HRV9gIZM/CXX +nSg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=dC/gdUBYsPBie02kiVh/wPxgse3D0P0UeG9BqAg/Ep0=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=ORFKGfpO0spfJUAEWcbYyNlMS3zXEtTDQ2FVTMtXde2hubLH+EurTVWdUryaIBgWHZ J+R2hK3JhxwZAV/DsGmS9c9st1/qlsMJ48UULGVP5YCvpogjQwQhSQLlMEjf5dnzNIHQ 6cRx7oaNhuvL+RYujY78HfcBCUnLKrEarp+d7kNl8JOwDZ4KZ2gJl7D1PhxQq4cge1RH t4tChE4idJgB56/U/npDnokr7EEV1iF1BZSI64wm0RZSi+Vi24mJ9kMBB8VoBsS3gq7d SjlIjBAsl0d/WREOGXj6aVekMAbm6fANY0ZbtP7EwxrXJdLnjiks9QbRTp2SbFztX4KU 1jlQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xfJ8Kh01; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id d75a77b69052e-4a72a51fbc8si132524191cf.559.2025.06.17.22.56.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:56:57 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xfJ8Kh01; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 08A44381694D for ; Wed, 18 Jun 2025 05:56:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 08A44381694D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=xfJ8Kh01 X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id 151E1386075B for ; Wed, 18 Jun 2025 05:55:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 151E1386075B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 151E1386075B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226101; cv=none; b=AY4vglp6hL66N6SnOAdG2C2cBqNdkvRBdffMC/c2eqUQoW8kxWfkTsE5nBmL+TRodHwPndBUdirMHIzw7nAjGkvGMOMN+qXyyAdSaEkqbgPw3A+cPDue7CQ5Q4rg+uRj2VuttBvLnBsv5KIVkGMqJ5Y5IUqnjOoYdxdDrYj7xUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226101; c=relaxed/simple; bh=9u6JkoogCVuHj2c7DHklfjGDmftetJxm8e6Lf/2YuMM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Ud82C4vRqogScyp6oC10OibkMb+QiMTnMwdvF2yQmjhgEWXHUltIZMOc6I5PdJNwTaroNBMZ8p6T9Ealbof5MbQAHzDENgOsGW7732TT141TyfZFA0XlD+lwoxuxeDjjrI/cs9bbulF8mNFO+pAirGfhbjkeIqyFxjVbY3hATcA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 151E1386075B Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-235e1d4cba0so59190875ad.2 for ; Tue, 17 Jun 2025 22:55:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226100; x=1750830900; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dC/gdUBYsPBie02kiVh/wPxgse3D0P0UeG9BqAg/Ep0=; b=xfJ8Kh01BXV6+P40lx16EfTOuh/Bpz3mjB6YHT6IaCXg7LrUd5btT4ocAAupRNxxG4 glXiIyU4/uxHi7tS5DbaepMXezOpQKPU7yXf8xxgt2gwxIhCP2lApP4oPCFzzbwPXCbh FzuyK2OfbUa6RrveTeyJITJ4OXZEWSvEWztTMymRkLs+xap7A7pQ35v4z+bR5aQ0I2h5 tU8gkTNlIL/JKgAvYzff7kKrg22C3VRhMJLsxG7wjfJ5jVPQc8kpqn0AvTI4XNh2WbZO dcWQL9COzswEWeshpMtGd8DXtbybN8rWmRtfaI20djXQwvdnnCbWZodv3Qq3b/dIWKD3 wkvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226100; x=1750830900; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dC/gdUBYsPBie02kiVh/wPxgse3D0P0UeG9BqAg/Ep0=; b=vEqKzW0Z2qeCKEv6eEyXfPsoL03UnNUPXrRwge9t7+Ojm+MP+cwJVmpjtZkVbzbPk0 QfLHy16sOztLsGXEsUiIfofU5bUOfwEga1IPxc+wGzYHg/6alzMWFxb51c0CGw9qXGoO DCjTJiafaj7WD1sRQjz1Li/LFH4F423TUDgvhoWqFdfZnBXQhSUN5/iIbnWEEHcNusCb Va09BnH5n7sl63PslL7a8ycFlQnunx9U3wKqcJBasEhgHp5r1y9UuOyaN4XUc0RXl8IN npEeYjLVAwbRh61nfb12ZBJqPsk+y+PZlCnFXbwj+mw11wAWzpwgLJ+4TjHXiPOsfPlu vxkw== X-Gm-Message-State: AOJu0Ywhm5btAWShgkiLV8gnCNdMXIdRwrw2GqVsBp2WXFHP3KtVMcWz 6zcdfBkGAI3bYLRXFE0oGpqe1B14MEZ08/gUayNJjpKqLB8dRVHwLkt6M3gtxyb3R4XJ6aC53vt p96Wl X-Gm-Gg: ASbGnctKeZkjJns/UTLLmzJd8VwNo7FVmeKV4dt67EgAB5h1S9VOU8xjlEZA5X8EV/F 22/h+L2iAxK56dM+Evzwr36QripOKRrQi/QOdLik5x2D8BDl9B4Ysf8nIwdQ3bn/J6NMxv7NDXK YZu99hTk8JaT05FhD8CEAqOYUVASMLvMZWDW8wPubHJcFabkrJXrWhdqe4cB0aS4sPwTixJ9IZY M7Z0DNyvvuith1H3uBSB1AB96zZwOTGoU20y4Rt68r0VCBpSaVUoyROhi1tulxbmsF2ElZKLBrO GX+/1UCzdSql+nGykPSiPw8mpClh/8eD8VPd7WOjtl7W8NWFs1ewrP3JmL19senti+4nuAPx8aa wCeA= X-Received: by 2002:a17:903:94c:b0:235:f70:fd37 with SMTP id d9443c01a7336-2366b006110mr243667455ad.19.1750226099999; Tue, 17 Jun 2025 22:54:59 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2365dea903dsm90691925ad.158.2025.06.17.22.54.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:54:59 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 4/9] bfd/aarch64-linux: Support reading and writing the GCS core file note Date: Wed, 18 Jun 2025 02:54:40 -0300 Message-ID: <20250618055445.709416-5-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org Reviewed-By: Luis Machado --- bfd/elf.c | 31 +++++++++++++++++++++++++++++++ include/elf/common.h | 3 +++ 2 files changed, 34 insertions(+) No change from v1 and from what was posted to the Binutils mailing list. diff --git a/bfd/elf.c b/bfd/elf.c index 14ce15c72545..f943cc489ba3 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -10661,6 +10661,15 @@ elfcore_grok_aarch_zt (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-aarch-zt", note); } +/* Convert NOTE into a bfd_section called ".reg-aarch-gcs". Return TRUE if + successful, otherwise return FALSE. */ + +static bool +elfcore_grok_aarch_gcs (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-gcs", note); +} + static bool elfcore_grok_arc_v2 (bfd *abfd, Elf_Internal_Note *note) { @@ -11404,6 +11413,12 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return true; + case NT_ARM_GCS: + if (note->namesz == 6 && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_gcs (abfd, note); + else + return true; + case NT_GDB_TDESC: if (note->namesz == 4 && strcmp (note->namedata, "GDB") == 0) @@ -13074,6 +13089,20 @@ elfcore_write_aarch_zt (bfd *abfd, size); } +/* Write the buffer of GCS register values in AARCH_GCS (length SIZE) into + the note buffer BUF and update *BUFSIZ. ABFD is the bfd the note is being + written into. Return a pointer to the new start of the note buffer, to + replace BUF which may no longer be valid. */ + +static char * +elfcore_write_aarch_gcs (bfd *abfd, char *buf, int *bufsiz, + const void *aarch_gcs, int size) +{ + const char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, note_name, NT_ARM_GCS, + aarch_gcs, size); +} + char * elfcore_write_arc_v2 (bfd *abfd, char *buf, @@ -13263,6 +13292,8 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_aarch_za (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-aarch-zt") == 0) return elfcore_write_aarch_zt (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-gcs") == 0) + return elfcore_write_aarch_gcs (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-arc-v2") == 0) return elfcore_write_arc_v2 (abfd, buf, bufsiz, data, size); if (strcmp (section, ".gdb-tdesc") == 0) diff --git a/include/elf/common.h b/include/elf/common.h index fd032d1e03ed..f4b543b353ac 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -740,6 +740,9 @@ /* Note: name must be "LINUX". */ #define NT_ARM_ZT 0x40d /* AArch64 SME2 ZT registers. */ /* Note: name must be "LINUX". */ +#define NT_ARM_GCS 0x410 /* AArch64 Guarded Control Stack + registers. */ + /* Note name must be "LINUX". */ #define NT_ARC_V2 0x600 /* ARC HS accumulator/extra registers. */ /* note name must be "LINUX". */ #define NT_LARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */ From patchwork Wed Jun 18 05:54:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897542 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp135669wrb; Tue, 17 Jun 2025 22:59:40 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWT9GCdUhgiDBsTOB/yezNZ58qkTO5nwtijpSJmTrSAnjMT1S9whkFmoSK7oT55zr/w9iWrCw==@linaro.org X-Google-Smtp-Source: AGHT+IHJZ/aDCh9G0jQXsyZ/oaflgUatfbQIVrSd1XckahCcudbYEpKRr66di6NjQtCyjB8k4qDn X-Received: by 2002:a05:6214:4ec4:b0:6fb:59de:f8ab with SMTP id 6a1803df08f44-6fb59def8b0mr97838826d6.10.1750226380188; Tue, 17 Jun 2025 22:59:40 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226380; cv=pass; d=google.com; s=arc-20240605; b=MJDr8Duka6wuL2GAMzBePd7/NpseNITRQB259TE+vivoy7kkXRd9YFptU2yH5Dgmv5 rWLSaRAMvvY9/Y0HvROYzG+NTurny1UMYYYoi1jD13EjcW+tH8U/rTzIoPCRBNOn6bnJ oN5VleyLuqj8CD7pMDQ6xP7+f6Vv0NAfE40zQCCL5oPDI1toLuG3fsF+CDXAHODYo+MO DY58CKbx17AjMQCPQ1BSMQ0ZFNAeLY5hxHHIvWWttQTf5xKKHssj1uNdflO6mkmjFJmw cFt3HR4kqHegz3v2N4BEJ0Y1ZlFK+/lBi7MORm0FhEpYs0WWhCYnccUV4WvRatAqXXqa RzLA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=7duG//2jIW951zMleRKZtXDoV7x7q5a2bZTegMmhxsQ=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=O4I8zHZKjxrQZKB8sdMUnAHKkby8YDUQuImxceFUrlybZbEY8RT/1jd9nmCCvv9uK0 h2ZgWfBpq0jG5z9GJ0svJ4WCNSH4N/Pdyv61FYUU+mEHTqzTbCKql2+OX2EHGwuSJKsp bYcmEkqGwV+LRT2iahXicHNaNzvzzNNQ6nUooVMwMKQUNBLQyEsExbdkDGNOa2ljXUoF VGGWQKIpY1hAwj/4+DHV+mQk0TMFbHj69V0sKsHZlCeHUpNjxDrT6Lj9QXlH3l4V8JdB auFelHmhlA7q529GxMb/2vFhp5MUvT2Vi4np3HyVcgWjSEuAx0CsZZ0nPe5vABfr+Sur QWZA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=LPrJSjoh; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id 6a1803df08f44-6fb5179c355si80664916d6.95.2025.06.17.22.59.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:59:40 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=LPrJSjoh; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BBA9A381696E for ; Wed, 18 Jun 2025 05:59:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BBA9A381696E Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=LPrJSjoh X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id 4DA8B3816966 for ; Wed, 18 Jun 2025 05:55:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4DA8B3816966 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4DA8B3816966 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226105; cv=none; b=x2YD8b3PulpcBaq+Tk/KONWeBPKMm1BVBqt/8W1OA4WHjI5XIvlkhxLUwXkrOiGqPNcdJ9TmSDfBgCeCwUK7gF6uPtR04PxdK0WHT1yuBf7M/StDdSgL40y3eG8E81imuIom5HwUGl270G8MrT5hXFK8SrC2lbIOBTCQzRtNC0A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226105; c=relaxed/simple; bh=xrHR7V9rNdQmLxEStvHh0/24ll2xlcSJIGgUReVw7zM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=BFjLXqZG05ZEb1gb12vEfGmUw3uAz1eVACrU8T++9mkUfWRa+ZAaK/b+6YoYizMrFIvw6BTsaCazF18lWHuG+7Q8TocfqphF/bFHKJpXesiJZ3Be2OMrE9Yet+RlZo4HKOd2wnfzChb/IoZ+UBsXQcOsqWm0+Xq/Kx9cKjXuw48= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4DA8B3816966 Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-235e1d4cba0so59191335ad.2 for ; Tue, 17 Jun 2025 22:55:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226104; x=1750830904; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7duG//2jIW951zMleRKZtXDoV7x7q5a2bZTegMmhxsQ=; b=LPrJSjohJJbZ24b/l1nKddIsqYeIeW8y6lJZHLJ8LY0cUrj4q5Xx90Uh8jbDgz+7NJ 21lYEZ6f4K6FkOgEyOb8UbL+pnF3niAkXJd1iaN315aQTvxtw7Xohb2EP+q8i9c8xZl7 iRTr5945V9vhfKkeEh3ERgwrwZxx9eE2veUrkO4V/q2Q0b0qYD8doF2FnvwnOU6dJ9k9 96a4WhQg1RPkLCvPXlKo3Qwc4bGqhPzEDPtPqfklL02eV/+INo2XHCcRnqU8ey1RL9TB oNV01FCQDhlsXJFA3/CBJAi5gpUIeSHgGNfLbT/G575pBynUPkpP1PraSBfsbsAtQvPp FVxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226104; x=1750830904; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7duG//2jIW951zMleRKZtXDoV7x7q5a2bZTegMmhxsQ=; b=Ti/1y1ClPAs/+LSG+/rH33cxNtTE++z+DncbkzkRxdsL1XVYGv9cwOlYYRj4Nzzbej 8jt+D8VJ0sgoG15RJGlSWdrFkbUrh73TdcXUwmiiuETA+CHOwQ/2r6CGujdeZT8eiO8c pNP5Cqij1Hm9e9ixLGecNV1gVgAiD58tPrgp+GKbPQRmue56zaIWMsKSbgMeAaHt4S88 4TIFMLUx9sBG9PYQrgfepA5N00ZbCe2XLg7nuQrLljk7ooxCnsIu80HZiIy94Zpd3fLp STiwK15epp065Ohxv4rZrNLVkpYibKjTfHsYU5+p1sFPnfKGbbP9x/bKzSW+tJ9/Wn++ LGtg== X-Gm-Message-State: AOJu0Yw86ZimlDld1DrWtVcj5MiuKYyQWyzVq1YGmOnBXbQsrmoEipQX CG3HTre5M6ID99cniZoHBhRpxhSl/ddcqg42q0rdshMVzpzjclap6L3x8Pm88vTqdlaJJj24IgG 8hLOP X-Gm-Gg: ASbGncuvjta3dSX7xuXerxcgojmGYkm6BfJNtx0NGjgzu/Fs4v7vLKvUSWgo6wdhe19 V4dg7+WK1kcsEKePY0Q6H/ChU3lWJc8so0YRB0jtg3S41PkYSPetipbqR7hcBI08Teq+Oe04luf aQIrN33C5yj5Rn8KEVx/jft+4hzDAJuZupwEc2mXUZF3YR6fP4vRFlffzjwuWRrKz0dDA5MLj2U ZAXI4cMB8FjaSCvhxk859VZ7gtsJ3JibvVC7EgmykKzT2aDI8cNoXC1MVGL+YpABt3pSmIhMPFV dM+LlRPaEChX7DjHAY7H4f1ZOMukznv9ihQL3m0NxkLcLeR632DLqXmrgPR0Hw2ditCx X-Received: by 2002:a17:902:fc8f:b0:235:6e7:8df2 with SMTP id d9443c01a7336-2366b14e74cmr265299015ad.41.1750226103550; Tue, 17 Jun 2025 22:55:03 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2365d58ed5asm91057345ad.0.2025.06.17.22.55.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:55:02 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 5/9] GDB, gdbserver: aarch64-linux: Initial Guarded Control Stack support Date: Wed, 18 Jun 2025 02:54:41 -0300 Message-ID: <20250618055445.709416-6-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org Add the org.gnu.gdb.aarch64.gcs feature with the GCSPR register, and the org.gnu.gdb.aarch64.gcs.linux feature with "registers" to represent the Linux kernel ptrace and prctl knobs that enable and lock specific GCS functionality. This code supports GCS only in Linux userspace applications, so the GCSPR that is exposed is the one at EL0. Also, support for calling inferior functions is enabled by adding an implementation for the shadow_stack_push gdbarch method. Testcases gdb.arch/aarch64-gcs.exp and gdb.arch/aarch64-gcs-core.exp are included to cover the added functionality. The change in the core_find procedure allows aarch64-gcs-core.exp to recover the output from the crashed program. It's needed because the test program in this testcase prints to stdout the value of the GCSPR right before crashing, and the testcase needs it to check whether GDB got it right. --- gdb/aarch64-linux-nat.c | 79 +++++++++ gdb/aarch64-linux-tdep.c | 26 +++ gdb/aarch64-tdep.c | 103 ++++++++++++ gdb/aarch64-tdep.h | 21 +++ gdb/arch/aarch64-gcs-linux.h | 44 +++++ gdb/arch/aarch64.c | 8 + gdb/arch/aarch64.h | 10 +- gdb/features/Makefile | 2 + gdb/features/aarch64-gcs-linux.c | 21 +++ gdb/features/aarch64-gcs-linux.xml | 18 +++ gdb/features/aarch64-gcs.c | 14 ++ gdb/features/aarch64-gcs.xml | 11 ++ gdb/testsuite/gdb.arch/aarch64-gcs-core.c | 124 +++++++++++++++ gdb/testsuite/gdb.arch/aarch64-gcs-core.exp | 105 ++++++++++++ gdb/testsuite/gdb.arch/aarch64-gcs.c | 168 ++++++++++++++++++++ gdb/testsuite/gdb.arch/aarch64-gcs.exp | 73 +++++++++ gdb/testsuite/lib/gdb.exp | 68 +++++++- gdbserver/linux-aarch64-low.cc | 46 ++++++ 18 files changed, 938 insertions(+), 3 deletions(-) create mode 100644 gdb/arch/aarch64-gcs-linux.h create mode 100644 gdb/features/aarch64-gcs-linux.c create mode 100644 gdb/features/aarch64-gcs-linux.xml create mode 100644 gdb/features/aarch64-gcs.c create mode 100644 gdb/features/aarch64-gcs.xml create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-core.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-core.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs.exp Changes since v1: - Mention EL0 register in commit message (suggested by Christina). - Mention enabling support for calling inferior functions (suggested by Christina). - Don't use "struct" keyword when declaring variables (suggested by Christina). - Fix some whitespace issues (spotted by Christina). - Add aarch64_gdbarch_tdep::has_gcs_linux and use it in aarch64-linux tdep and native code since it implies tdep->has_gcs () to address Christina's review comment. - Add check in aarch64_linux_init_abi to make sure the target description has both the GCS and Linux GCS features to address Christina's review comment. - Add i18n for a couple of error strings (suggested by Christina). - In aarch64_gdbarch_init, return a bit earlier if the Linux GCS feature is present but GCS isn't (suggested by Christina). - Also dump tdep->gcs_linux_reg_base in aarch64_dump_tdep (suggested by Luis). - Moved documentation changes to its own patch. - Moved aarch64-gcs.exp and aarch64-gcs-core.exp to this patch. - Document change to core_find proc in lib/gdb.exp (suggested by Luis). diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index d7869f42e825..093206baff5c 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -51,6 +51,7 @@ #include "gdb_proc_service.h" #include "arch-utils.h" +#include "arch/aarch64-gcs-linux.h" #include "arch/aarch64-mte-linux.h" #include "nat/aarch64-mte-linux-ptrace.h" @@ -542,6 +543,67 @@ store_tlsregs_to_thread (struct regcache *regcache) perror_with_name (_("unable to store TLS register")); } +/* Fill GDB's register array with the GCS register values from + the current thread. */ + +static void +fetch_gcsregs_from_thread (regcache *regcache) +{ + aarch64_gdbarch_tdep *tdep + = gdbarch_tdep (regcache->arch ()); + + gdb_assert (tdep->gcs_reg_base != -1); + gdb_assert (tdep->gcs_linux_reg_base != -1); + + user_gcs user_gcs; + iovec iovec; + + iovec.iov_base = &user_gcs; + iovec.iov_len = sizeof (user_gcs); + + int tid = get_ptrace_pid (regcache->ptid ()); + if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_GCS, &iovec) != 0) + perror_with_name (_("unable to fetch GCS registers")); + + regcache->raw_supply (tdep->gcs_reg_base, &user_gcs.gcspr_el0); + regcache->raw_supply (tdep->gcs_linux_reg_base, &user_gcs.features_enabled); + regcache->raw_supply (tdep->gcs_linux_reg_base + 1, + &user_gcs.features_locked); +} + +/* Store to the current thread the valid GCS register set in the GDB's + register array. */ + +static void +store_gcsregs_to_thread (regcache *regcache) +{ + aarch64_gdbarch_tdep *tdep + = gdbarch_tdep (regcache->arch ()); + + gdb_assert (tdep->gcs_reg_base != -1); + gdb_assert (tdep->gcs_linux_reg_base != -1); + + if (REG_VALID != regcache->get_register_status (tdep->gcs_reg_base) + || REG_VALID != regcache->get_register_status (tdep->gcs_linux_reg_base) + || REG_VALID + != regcache->get_register_status (tdep->gcs_linux_reg_base + 1)) + return; + + user_gcs user_gcs; + regcache->raw_collect (tdep->gcs_reg_base, &user_gcs.gcspr_el0); + regcache->raw_collect (tdep->gcs_linux_reg_base, &user_gcs.features_enabled); + regcache->raw_collect (tdep->gcs_linux_reg_base + 1, + &user_gcs.features_locked); + + iovec iovec; + iovec.iov_base = &user_gcs; + iovec.iov_len = sizeof (user_gcs); + + int tid = get_ptrace_pid (regcache->ptid ()); + if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_GCS, &iovec) != 0) + perror_with_name (_("unable to store GCS registers")); +} + /* The AArch64 version of the "fetch_registers" target_ops method. Fetch REGNO from the target and place the result into REGCACHE. */ @@ -577,6 +639,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) if (tdep->has_sme2 ()) fetch_zt_from_thread (regcache); + + if (tdep->has_gcs_linux ()) + fetch_gcsregs_from_thread (regcache); } /* General purpose register? */ else if (regno < AARCH64_V0_REGNUM) @@ -609,6 +674,11 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) && regno >= tdep->tls_regnum_base && regno < tdep->tls_regnum_base + tdep->tls_register_count) fetch_tlsregs_from_thread (regcache); + /* GCS register? */ + else if (tdep->has_gcs_linux () + && (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base + || regno == tdep->gcs_linux_reg_base + 1)) + fetch_gcsregs_from_thread (regcache); } /* A version of the "fetch_registers" target_ops method used when running @@ -680,6 +750,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) if (tdep->has_sme2 ()) store_zt_to_thread (regcache); + + if (tdep->has_gcs_linux ()) + store_gcsregs_to_thread (regcache); } /* General purpose register? */ else if (regno < AARCH64_V0_REGNUM) @@ -706,6 +779,11 @@ aarch64_store_registers (struct regcache *regcache, int regno) && regno >= tdep->tls_regnum_base && regno < tdep->tls_regnum_base + tdep->tls_register_count) store_tlsregs_to_thread (regcache); + /* GCS register? */ + else if (tdep->has_gcs_linux () + && (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base + || regno == tdep->gcs_linux_reg_base + 1)) + store_gcsregs_to_thread (regcache); /* PAuth registers are read-only. */ } @@ -881,6 +959,7 @@ aarch64_linux_nat_target::read_description () active or not. */ features.vq = aarch64_sve_get_vq (tid); features.pauth = hwcap & AARCH64_HWCAP_PACA; + features.gcs = features.gcs_linux = hwcap & HWCAP_GCS; features.mte = hwcap2 & HWCAP2_MTE; features.tls = aarch64_tls_register_count (tid); /* SME feature check. */ diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index a194ac809c23..ee3f7bfd9928 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -50,6 +50,7 @@ #include "record-full.h" #include "linux-record.h" +#include "arch/aarch64-gcs-linux.h" #include "arch/aarch64-mte.h" #include "arch/aarch64-mte-linux.h" #include "arch/aarch64-scalable-linux.h" @@ -1604,6 +1605,27 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, cb (".reg-aarch-tls", sizeof_tls_regset, sizeof_tls_regset, &aarch64_linux_tls_regset, "TLS register", cb_data); } + + /* Handle GCS registers. */ + if (tdep->has_gcs_linux ()) + { + /* Create this on the fly in order to handle the variable regnums. */ + const regcache_map_entry gcs_regmap[] = + { + { 1, tdep->gcs_linux_reg_base, 8 }, /* features_enabled */ + { 1, tdep->gcs_linux_reg_base + 1, 8 }, /* features_locked */ + { 1, tdep->gcs_reg_base, 8 }, /* GCSPR */ + { 0 } + }; + + const regset aarch64_linux_gcs_regset = + { + gcs_regmap, regcache_supply_regset, regcache_collect_regset + }; + + cb (".reg-aarch-gcs", sizeof (user_gcs), sizeof (user_gcs), + &aarch64_linux_gcs_regset, "GCS registers", cb_data); + } } /* Implement the "core_read_description" gdbarch method. */ @@ -1628,6 +1650,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch, length. */ features.vq = aarch64_linux_core_read_vq_from_sections (gdbarch, abfd); features.pauth = hwcap & AARCH64_HWCAP_PACA; + features.gcs = features.gcs_linux = hwcap & HWCAP_GCS; features.mte = hwcap2 & HWCAP2_MTE; /* Handle the TLS section. */ @@ -2765,6 +2788,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) NULL }; aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + if (tdep->has_gcs () && !tdep->has_gcs_linux ()) + error (_("Incomplete GCS support in the target: missing Linux feature")); + tdep->lowest_pc = 0x8000; linux_init_abi (info, gdbarch, 1); diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 8d54e59f332a..0e9e6644dd0a 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -159,6 +159,18 @@ static const char *const aarch64_mte_register_names[] = "tag_ctl" }; +static const char *const aarch64_gcs_register_names[] = { + /* Guarded Control Stack Pointer Register. */ + "gcspr" +}; + +static const char *const aarch64_gcs_linux_register_names[] = { + /* Field in struct user_gcs. */ + "gcs_features_enabled", + /* Field in struct user_gcs. */ + "gcs_features_locked", +}; + static int aarch64_stack_frame_destroyed_p (struct gdbarch *, CORE_ADDR); /* AArch64 prologue cache structure. */ @@ -1875,6 +1887,39 @@ pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache, } } +/* Push LR_VALUE to the Guarded Control Stack. */ + +static void +aarch64_push_gcs_entry (regcache *regs, CORE_ADDR lr_value) +{ + gdbarch *arch = regs->arch (); + aarch64_gdbarch_tdep *tdep = gdbarch_tdep (arch); + CORE_ADDR gcs_addr; + + enum register_status status = regs->cooked_read (tdep->gcs_reg_base, + &gcs_addr); + if (status != REG_VALID) + error (_("Can't read $gcspr.")); + + gcs_addr -= 8; + gdb_byte buf[8]; + store_integer (buf, gdbarch_byte_order (arch), lr_value); + if (target_write_memory (gcs_addr, buf, sizeof (buf)) != 0) + error (_("Can't write to Guarded Control Stack.")); + + /* Update GCSPR. */ + regcache_cooked_write_unsigned (regs, tdep->gcs_reg_base, gcs_addr); +} + +/* Implement the "shadow_stack_push" gdbarch method. */ + +static void +aarch64_shadow_stack_push (gdbarch *gdbarch, CORE_ADDR new_addr, + regcache *regcache) +{ + aarch64_push_gcs_entry (regcache, new_addr); +} + /* Implement the "push_dummy_call" gdbarch method. */ static CORE_ADDR @@ -4046,6 +4091,14 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc) features.sme2 = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sme2") != nullptr); + /* Check for the GCS feature. */ + features.gcs = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs") + != nullptr); + + /* Check for the GCS Linux feature. */ + features.gcs_linux = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs.linux") + != nullptr); + return features; } @@ -4590,6 +4643,46 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) int first_w_regnum = num_pseudo_regs; num_pseudo_regs += 31; + const tdesc_feature *feature_gcs + = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs"); + int first_gcs_regnum = -1; + /* Add the GCS registers. */ + if (feature_gcs != nullptr) + { + first_gcs_regnum = num_regs; + /* Validate the descriptor provides the mandatory GCS registers and + allocate their numbers. */ + for (i = 0; i < ARRAY_SIZE (aarch64_gcs_register_names); i++) + valid_p &= tdesc_numbered_register (feature_gcs, tdesc_data.get (), + first_gcs_regnum + i, + aarch64_gcs_register_names[i]); + + num_regs += i; + } + + if (!valid_p) + return nullptr; + + const tdesc_feature *feature_gcs_linux + = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs.linux"); + int first_gcs_linux_regnum = -1; + /* Add the GCS Linux registers. */ + if (feature_gcs_linux != nullptr && feature_gcs == nullptr) + /* This feature depends on the GCS feature. */ + return nullptr; + else if (feature_gcs_linux != nullptr) + { + first_gcs_linux_regnum = num_regs; + /* Validate the descriptor provides the mandatory GCS Linux registers + and allocate their numbers. */ + for (i = 0; i < ARRAY_SIZE (aarch64_gcs_linux_register_names); i++) + valid_p &= tdesc_numbered_register (feature_gcs_linux, tdesc_data.get (), + first_gcs_linux_regnum + i, + aarch64_gcs_linux_register_names[i]); + + num_regs += i; + } + if (!valid_p) return nullptr; @@ -4611,6 +4704,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->mte_reg_base = first_mte_regnum; tdep->tls_regnum_base = first_tls_regnum; tdep->tls_register_count = tls_register_count; + tdep->gcs_reg_base = first_gcs_regnum; + tdep->gcs_linux_reg_base = first_gcs_linux_regnum; /* Set the SME register set details. The pseudo-registers will be adjusted later. */ @@ -4733,6 +4828,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_get_pc_address_flags (gdbarch, aarch64_get_pc_address_flags); + if (tdep->has_gcs ()) + set_gdbarch_shadow_stack_push (gdbarch, aarch64_shadow_stack_push); + tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data)); /* Fetch the updated number of registers after we're done adding all @@ -4905,6 +5003,11 @@ aarch64_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file) pulongest (tdep->sme_tile_pseudo_base)); gdb_printf (file, _("aarch64_dump_tdep: sme_svq = %s\n"), pulongest (tdep->sme_svq)); + + gdb_printf (file, _("aarch64_dump_tdep: gcs_reg_base = %d\n"), + tdep->gcs_reg_base); + gdb_printf (file, _("aarch64_dump_tdep: gcs_linux_reg_base = %d\n"), + tdep->gcs_linux_reg_base); } #if GDB_SELF_TEST diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index 3b8dcc26545b..54ca641a35a3 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -182,6 +182,27 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base { return sme2_zt0_regnum > 0; } + + /* First GCS register. This is -1 if no GCS registers are available. */ + int gcs_reg_base = -1; + + /* First GCS Linux-specific register. This is -1 if no GCS Linux feature is + available. */ + int gcs_linux_reg_base = -1; + + /* Returns true if the target supports GCS. */ + bool + has_gcs () const + { + return gcs_reg_base != -1; + } + + /* Returns true if the target supports the Linux GCS feature. */ + bool + has_gcs_linux () const + { + return gcs_linux_reg_base != -1; + } }; const target_desc *aarch64_read_description (const aarch64_features &features); diff --git a/gdb/arch/aarch64-gcs-linux.h b/gdb/arch/aarch64-gcs-linux.h new file mode 100644 index 000000000000..9366caa7289a --- /dev/null +++ b/gdb/arch/aarch64-gcs-linux.h @@ -0,0 +1,44 @@ +/* Common Linux target-dependent definitions for AArch64 GCS + + Copyright (C) 2025 Free Software Foundation, Inc. + + 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 . */ + +#ifndef ARCH_AARCH64_GCS_LINUX_H +#define ARCH_AARCH64_GCS_LINUX_H + +#include + +/* Feature check for Guarded Control Stack. */ +#ifndef HWCAP_GCS +#define HWCAP_GCS (1UL << 32) +#endif + +/* Make sure we only define these if the kernel header doesn't. */ +#ifndef GCS_MAGIC + +/* GCS state (NT_ARM_GCS). */ + +struct user_gcs +{ + uint64_t features_enabled; + uint64_t features_locked; + uint64_t gcspr_el0; +}; + +#endif /* GCS_MAGIC */ + +#endif /* ARCH_AARCH64_GCS_LINUX_H */ diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c index 3e1ca0547340..dff2bc16003a 100644 --- a/gdb/arch/aarch64.c +++ b/gdb/arch/aarch64.c @@ -26,6 +26,8 @@ #include "../features/aarch64-sme.c" #include "../features/aarch64-sme2.c" #include "../features/aarch64-tls.c" +#include "../features/aarch64-gcs.c" +#include "../features/aarch64-gcs-linux.c" /* See arch/aarch64.h. */ @@ -65,6 +67,12 @@ aarch64_create_target_description (const aarch64_features &features) if (features.sme2) regnum = create_feature_aarch64_sme2 (tdesc.get (), regnum); + if (features.gcs) + regnum = create_feature_aarch64_gcs (tdesc.get (), regnum); + + if (features.gcs_linux) + regnum = create_feature_aarch64_gcs_linux (tdesc.get (), regnum); + return tdesc.release (); } diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index ee18b74b80f5..679d845df74e 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -51,6 +51,12 @@ struct aarch64_features /* Whether SME2 is supported. */ bool sme2 = false; + + /* Whether Guarded Control Stack is supported. */ + bool gcs = false; + + /* Whether Guarded Control Stack Linux features are supported. */ + bool gcs_linux = false; }; inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs) @@ -60,7 +66,9 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs) && lhs.mte == rhs.mte && lhs.tls == rhs.tls && lhs.svq == rhs.svq - && lhs.sme2 == rhs.sme2; + && lhs.sme2 == rhs.sme2 + && lhs.gcs == rhs.gcs + && lhs.gcs_linux == rhs.gcs_linux; } namespace std diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 7a8c7999733a..92fd8085d478 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -203,6 +203,8 @@ FEATURE_XMLFILES = aarch64-core.xml \ aarch64-fpu.xml \ aarch64-pauth.xml \ aarch64-mte.xml \ + aarch64-gcs.xml \ + aarch64-gcs-linux.xml \ arc/v1-core.xml \ arc/v1-aux.xml \ arc/v2-core.xml \ diff --git a/gdb/features/aarch64-gcs-linux.c b/gdb/features/aarch64-gcs-linux.c new file mode 100644 index 000000000000..6b0d25b4518c --- /dev/null +++ b/gdb/features/aarch64-gcs-linux.c @@ -0,0 +1,21 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: aarch64-gcs-linux.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_aarch64_gcs_linux (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.gcs.linux"); + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_flags (feature, "features_flags", 8); + tdesc_add_flag (type_with_fields, 0, "PR_SHADOW_STACK_ENABLE"); + tdesc_add_flag (type_with_fields, 1, "PR_SHADOW_STACK_WRITE"); + tdesc_add_flag (type_with_fields, 2, "PR_SHADOW_STACK_PUSH"); + + tdesc_create_reg (feature, "gcs_features_enabled", regnum++, 1, "system", 64, "features_flags"); + tdesc_create_reg (feature, "gcs_features_locked", regnum++, 1, "system", 64, "features_flags"); + return regnum; +} diff --git a/gdb/features/aarch64-gcs-linux.xml b/gdb/features/aarch64-gcs-linux.xml new file mode 100644 index 000000000000..8d9d2ceb9260 --- /dev/null +++ b/gdb/features/aarch64-gcs-linux.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/gdb/features/aarch64-gcs.c b/gdb/features/aarch64-gcs.c new file mode 100644 index 000000000000..2b2caf29cc8c --- /dev/null +++ b/gdb/features/aarch64-gcs.c @@ -0,0 +1,14 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: aarch64-gcs.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_aarch64_gcs (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.gcs"); + tdesc_create_reg (feature, "gcspr", regnum++, 1, "system", 64, "data_ptr"); + return regnum; +} diff --git a/gdb/features/aarch64-gcs.xml b/gdb/features/aarch64-gcs.xml new file mode 100644 index 000000000000..bbee5e001722 --- /dev/null +++ b/gdb/features/aarch64-gcs.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-core.c b/gdb/testsuite/gdb.arch/aarch64-gcs-core.c new file mode 100644 index 000000000000..87ee7842f71b --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-core.c @@ -0,0 +1,124 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2025 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 . */ + +#include +#include +#include +#include +#include + +/* Feature check for Guarded Control Stack. */ +#ifndef HWCAP_GCS +#define HWCAP_GCS (1UL << 32) +#endif + +#ifndef PR_GET_SHADOW_STACK_STATUS +#define PR_GET_SHADOW_STACK_STATUS 74 +#define PR_SET_SHADOW_STACK_STATUS 75 +#define PR_SHADOW_STACK_ENABLE (1UL << 0) +#endif + +/* We need to use a macro to call prctl because after GCS is enabled, it's not + possible to return from the function which enabled it. This is because the + return address of the calling function isn't on the GCS. */ +#define my_syscall2(num, arg1, arg2) \ + ({ \ + register long _num __asm__("x8") = (num); \ + register long _arg1 __asm__("x0") = (long)(arg1); \ + register long _arg2 __asm__("x1") = (long)(arg2); \ + register long _arg3 __asm__("x2") = 0; \ + register long _arg4 __asm__("x3") = 0; \ + register long _arg5 __asm__("x4") = 0; \ + \ + __asm__ volatile ("svc #0\n" \ + : "=r"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "r"(_arg5), "r"(_num) \ + : "memory", "cc"); \ + _arg1; \ + }) + +#define get_gcspr(void) \ + ({ \ + unsigned long *gcspr; \ + \ + /* Get GCSPR_EL0. */ \ + asm volatile ("mrs %0, S3_3_C2_C5_1" : "=r"(gcspr) : : "cc"); \ + \ + gcspr; \ + }) + +/* Corrupt the return address to see if GDB will report a SIGSEGV with the + expected + $_siginfo.si_code. */ +static void __attribute__ ((noinline)) +function (unsigned long *gcspr) +{ + /* x30 holds the return address. */ + register long x30 __asm__("x30") __attribute__ ((unused)); + + /* Print GCSPR to stdout so that the testcase can capture it. */ + printf ("%p\n", get_gcspr ()); + fflush (stdout); + + /* Cause a GCS exception. */ + x30 = 0xbadc0ffee; + __asm__ volatile ("ret\n"); +} + +int +main (void) +{ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + fprintf (stderr, "GCS support not found in AT_HWCAP\n"); + return EXIT_FAILURE; + } + + /* Force shadow stacks on, our tests *should* be fine with or + without libc support and with or without this having ended + up tagged for GCS and enabled by the dynamic linker. We + can't use the libc prctl() function since we can't return + from enabling the stack. Also lock GCS if not already + locked so we can test behaviour when it's locked. */ + unsigned long gcs_mode; + int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to read GCS state: %d\n", ret); + return EXIT_FAILURE; + } + + if (!(gcs_mode & PR_SHADOW_STACK_ENABLE)) + { + gcs_mode = PR_SHADOW_STACK_ENABLE; + ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to configure GCS: %d\n", ret); + return EXIT_FAILURE; + } + } + + unsigned long *gcspr = get_gcspr (); + + /* Pass gscpr to function just so it's used for something. */ + function (gcspr); /* Break here. */ + + /* Avoid returning, in case libc doesn't understand GCS. */ + exit (EXIT_SUCCESS); +} diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp new file mode 100644 index 000000000000..ef7e507407a4 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp @@ -0,0 +1,105 @@ +# Copyright 2025 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 . + +# Test reading and writing the core dump of a binary that uses a Guarded +# Control Stack. + +require allow_aarch64_gcs_tests + +standard_testfile + +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } { + return +} + +set linespec ${srcfile}:[gdb_get_line_number "Break here"] + +if ![runto $linespec] { + return +} + +# Continue until a crash. The line with the hex number is optional because +# it's printed by the test program, and doesn't appear in the Expect buffer +# when testing a remote target. +gdb_test "continue" \ + [multi_line \ + "Continuing\\." \ + "($hex\r\n)?" \ + "Program received signal SIGSEGV, Segmentation fault\\." \ + "function \\(gcspr=$hex\\) at .*aarch64-gcs-core.c:$decimal" \ + {.*__asm__ volatile \("ret\\n"\);}] \ + "continue to SIGSEGV" + +set gcspr_in_gcore [get_valueof "/x" "\$gcspr" "*unknown*"] + +# Generate the gcore core file. +set gcore_filename [standard_output_file "${testfile}.gcore"] +set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"] + +# Obtain an OS-generated core file. Save test program output to +# ${binfile}.out. +set core_filename [core_find $binfile {} {} "${binfile}.out"] +set core_generated [expr {$core_filename != ""}] +set os_core_name "${binfile}.core" +remote_exec build "mv $core_filename $os_core_name" +set core_filename $os_core_name + +# At this point we have a couple of core files, the gcore one generated by +# GDB and the one generated by the operating system. Make sure GDB can +# read both correctly. + +proc check_core_file {core_filename saved_gcspr} { + global decimal hex + + # Load the core file. + if [gdb_test "core $core_filename" \ + [multi_line \ + "Core was generated by .*\\." \ + "Program terminated with signal SIGSEGV, Segmentation fault\\." \ + "#0 function \\(gcspr=$hex\\) at .*aarch64-gcs-core.c:$decimal" \ + "$decimal.*__asm__ volatile \\(\"ret\\\\n\"\\);"] \ + "load core file"] { + return -1 + } + + # Check the value of GCSPR in the core file. + gdb_test "print/x \$gcspr" "\\$\[0-9\]+ = $saved_gcspr" \ + "gcspr contents from core file" +} + +if {$gcore_generated} { + clean_restart $binfile + + with_test_prefix "gcore corefile" { + check_core_file $gcore_filename $gcspr_in_gcore + } +} else { + fail "gcore corefile not generated" +} + +if {$core_generated} { + clean_restart $binfile + + with_test_prefix "OS corefile" { + # Read GCSPR value from saved output of the test program. + set out_id [open ${binfile}.out "r"] + set gcspr_in_core [gets $out_id] + + close $out_id + check_core_file $core_filename $gcspr_in_core + } +} else { + untested "OS corefile not generated" +} diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs.c b/gdb/testsuite/gdb.arch/aarch64-gcs.c new file mode 100644 index 000000000000..1e00a010a9f1 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs.c @@ -0,0 +1,168 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2025 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 . */ + +#include +#include +#include +#include +#include +#include + +/* Feature check for Guarded Control Stack. */ +#ifndef HWCAP_GCS +#define HWCAP_GCS (1UL << 32) +#endif + +#ifndef PR_GET_SHADOW_STACK_STATUS +#define PR_GET_SHADOW_STACK_STATUS 74 +#define PR_SET_SHADOW_STACK_STATUS 75 +#define PR_SHADOW_STACK_ENABLE (1UL << 0) +#endif + +/* We need to use a macro to call prctl because after GCS is enabled, it's not + possible to return from the function which enabled it. This is because the + return address of the calling function isn't on the GCS. */ +#define my_syscall2(num, arg1, arg2) \ + ({ \ + register long _num __asm__("x8") = (num); \ + register long _arg1 __asm__("x0") = (long)(arg1); \ + register long _arg2 __asm__("x1") = (long)(arg2); \ + register long _arg3 __asm__("x2") = 0; \ + register long _arg4 __asm__("x3") = 0; \ + register long _arg5 __asm__("x4") = 0; \ + \ + __asm__ volatile ("svc #0\n" \ + : "=r"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "r"(_arg5), "r"(_num) \ + : "memory", "cc"); \ + _arg1; \ + }) + +#define get_gcspr(void) \ + ({ \ + unsigned long *gcspr; \ + \ + /* Get GCSPR_EL0. */ \ + asm volatile ("mrs %0, S3_3_C2_C5_1" : "=r"(gcspr) : : "cc"); \ + \ + gcspr; \ + }) + +static unsigned long *handler_gcspr = 0; + +static void +handler (int sig) +{ + handler_gcspr = get_gcspr (); +} + +static int __attribute__ ((unused)) +called_from_gdb (int val) +{ + return val + 1; +} + +/* Corrupt the return address to see if GDB will report a SIGSEGV with the expected + $_siginfo.si_code. */ +static void __attribute__ ((noinline)) +normal_function2 (void) +{ + /* x30 holds the return address. */ + register unsigned long x30 __asm__("x30") __attribute__ ((unused)); + + /* Cause a GCS exception. */ + x30 = 0xbadc0ffee; + __asm__ volatile ("ret\n"); +} + +static inline void __attribute__ ((__always_inline__)) +inline_function2 (void) +{ + normal_function2 (); +} + +/* Corrupt the return address to see if GDB will report a GCS error in this + function's frame . */ +static void __attribute__ ((noinline)) +normal_function1 (void) +{ + /* x30 holds the return address. */ + register unsigned long x30 __asm__ ("x30") __attribute__ ((unused)); + x30 = 0xbadc0ffee; + inline_function2 (); +} + +static inline void __attribute__ ((__always_inline__)) +inline_function1 (void) +{ + normal_function1 (); +} + +int +main (void) +{ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + fprintf (stderr, "GCS support not found in AT_HWCAP\n"); + return EXIT_FAILURE; + } + + /* Force shadow stacks on, our tests *should* be fine with or + without libc support and with or without this having ended + up tagged for GCS and enabled by the dynamic linker. We + can't use the libc prctl() function since we can't return + from enabling the stack. Also lock GCS if not already + locked so we can test behaviour when it's locked. */ + unsigned long gcs_mode; + int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to read GCS state: %d\n", ret); + return EXIT_FAILURE; + } + + if (!(gcs_mode & PR_SHADOW_STACK_ENABLE)) + { + gcs_mode = PR_SHADOW_STACK_ENABLE; + ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to configure GCS: %d\n", ret); + return EXIT_FAILURE; + } + } + + /* This is used by GDB. */ + __attribute__((unused)) unsigned long *gcspr = get_gcspr (); + + struct sigaction act = { 0 }; + + act.sa_handler = &handler; /* Break here. */ + if (sigaction (SIGUSR1, &act, NULL) == -1) + { + perror ("sigaction"); + exit (EXIT_FAILURE); + } + + raise (SIGUSR1); + + inline_function1 (); + + /* Avoid returning, in case libc doesn't understand GCS. */ + exit (EXIT_SUCCESS); +} diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs.exp b/gdb/testsuite/gdb.arch/aarch64-gcs.exp new file mode 100644 index 000000000000..ea70cc6ef2e9 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs.exp @@ -0,0 +1,73 @@ +# Copyright 2025 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 . + +# Test a binary that uses a Guarded Control Stack. + +require allow_aarch64_gcs_tests + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return +} + +set linespec ${srcfile}:[gdb_get_line_number "Break here"] + +if ![runto ${linespec}] { + return +} + +gdb_test "print \$gcs_features_enabled" \ + [string_to_regexp { = [ PR_SHADOW_STACK_ENABLE ]}] \ + "GCS is enabled" + +gdb_test "print \$gcspr" ". = \\(void \\*\\) $hex" "GDB knows about gcspr" +gdb_test "print \$gcspr == gcspr" ". = 1" "GDB has the correct gcspr value" +gdb_test_no_output "set \$gcspr_in_main = \$gcspr" \ + "save gcspr value in main for later" + +# If the inferior function call fails, we don't want the tests following it +# to be affected. +gdb_test_no_output "set unwindonsignal on" +gdb_test "print called_from_gdb (41)" ". = 42" "call inferior function" + +gdb_test "break handler" "Breakpoint \[0-9\]+ .*aarch64-gcs.c, line \[0-9\]+\\." +gdb_test "handle SIGUSR1 nostop" \ + ".*\r\nSIGUSR1\\s+No\\s+Yes\\s+Yes\\s+User defined signal 1" \ + "let the inferior receive SIGUSR1 uninterrupted" +gdb_test "continue" \ + ".*\r\nBreakpoint \[0-9\]+, handler \\(sig=10\\) at .*aarch64-gcs.c.*handler_gcspr = get_gcspr \\(\\);" \ + "continue to signal handler" + +# Select the frame above the frame, which makes GDB +# unwind the gcspr from the signal frame GCS context. +gdb_test "frame 2" "#2 ($hex in )?\\S+ \\(.*\\) (at|from) \\S+.*" \ + "reached frame 2" +gdb_test "print \$gcspr" ". = \\(void \\*\\) $hex" "gcspr in frame level 2" + +gdb_test "continue" \ + [multi_line \ + "Continuing\\." \ + "" \ + "Program received signal SIGSEGV, Segmentation fault\\." \ + "normal_function2 \\(\\) at .*aarch64-gcs.c:$decimal" \ + "${decimal}\\s+__asm__ volatile \\(\"ret\\\\n\"\\);"] \ + "continue to SIGSEGV" + +gdb_test "print \$_siginfo.si_code" ". = 10" \ + "test value of si_code when GCS SIGSEGV happens" +# The GCS grows down, and there are two real frames until main. +gdb_test "print \$gcspr == \$gcspr_in_main - 16" ". = 1" \ + "test value of gcspr when GCS SIGSEGV happens" diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index ef46e8f58c0f..45cf7b48d015 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -5032,6 +5032,64 @@ gdb_caching_proc allow_aarch64_mops_tests {} { return $allow_mops_tests } +# Run a test on the target to see if it supports AArch64 GCS extensions. +# Return 0 if so, 1 if it does not. Note this causes a restart of GDB. + +gdb_caching_proc allow_aarch64_gcs_tests {} { + global srcdir subdir gdb_prompt inferior_exited_re + + set me "allow_aarch64_gcs_tests" + + if { ![is_aarch64_target]} { + return 0 + } + + # Compile a program that tests the GCS feature. + set src { + #include + #include + + /* Feature check for Guarded Control Stack. */ + #ifndef HWCAP_GCS + #define HWCAP_GCS (1UL << 32) + #endif + + int main (void) { + bool gcs_supported = getauxval (AT_HWCAP) & HWCAP_GCS; + + /* Return success if GCS is supported. */ + return !gcs_supported; + } + } + + if {![gdb_simple_compile $me $src executable]} { + return 0 + } + + # Compilation succeeded so now run it via gdb. + clean_restart $obj + gdb_run_cmd + gdb_expect { + -re ".*$inferior_exited_re with code 01.*${gdb_prompt} $" { + verbose -log "\n$me gcs support not detected" + set allow_gcs_tests 0 + } + -re ".*$inferior_exited_re normally.*${gdb_prompt} $" { + verbose -log "\n$me: gcs support detected" + set allow_gcs_tests 1 + } + default { + warning "\n$me: default case taken" + set allow_gcs_tests 0 + } + } + gdb_exit + remote_file build delete $obj + + verbose "$me: returning $allow_gcs_tests" 2 + return $allow_gcs_tests +} + # A helper that compiles a test case to see if __int128 is supported. proc gdb_int128_helper {lang} { return [gdb_can_simple_compile "i128-for-$lang" { @@ -9322,7 +9380,13 @@ proc remove_core {pid {test ""}} { } } -proc core_find {binfile {deletefiles {}} {arg ""}} { +# Runs ${binfile} expecting it to crash and generate a core file. +# If DELETEFILES is provided, remove these files after running the program. +# If ARG is provided, pass it as a command line argument to the program. +# If OUTPUT_FILE is provided, save the program output to it. +# Returns the name of the core dump, or empty string if not found. + +proc core_find {binfile {deletefiles {}} {arg ""} {output_file "/dev/null"}} { global objdir subdir set destcore "$binfile.core" @@ -9344,7 +9408,7 @@ proc core_find {binfile {deletefiles {}} {arg ""}} { set found 0 set coredir [standard_output_file coredir.[getpid]] file mkdir $coredir - catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >/dev/null 2>&1\"" + catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >${output_file} 2>&1\"" # remote_exec host "${binfile}" set binfile_basename [file tail $binfile] foreach i [list \ diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 2eb3af659ad1..e086a0a54b0b 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -39,6 +39,7 @@ #include "gdb_proc_service.h" #include "arch/aarch64.h" +#include "arch/aarch64-gcs-linux.h" #include "arch/aarch64-mte-linux.h" #include "arch/aarch64-scalable-linux.h" #include "linux-aarch32-tdesc.h" @@ -321,6 +322,42 @@ aarch64_store_tlsregset (struct regcache *regcache, const void *buf) supply_register (regcache, *regnum, tls_buf + sizeof (uint64_t)); } +/* Fill BUF with GCS register from the regcache. */ + +static void +aarch64_fill_gcsregset (regcache *regcache, void *buf) +{ + user_gcs *regset = (user_gcs *) buf; + int gcspr_regnum = find_regno (regcache->tdesc, "gcspr"); + int features_enabled_regnum = find_regno (regcache->tdesc, + "gcs_features_enabled"); + int features_locked_regnum = find_regno (regcache->tdesc, + "gcs_features_locked"); + + collect_register (regcache, gcspr_regnum, ®set->gcspr_el0); + collect_register (regcache, features_enabled_regnum, + ®set->features_enabled); + collect_register (regcache, features_locked_regnum, ®set->features_locked); +} + +/* Store GCS register to regcache. */ + +static void +aarch64_store_gcsregset (regcache *regcache, const void *buf) +{ + const user_gcs *regset = (const user_gcs *) buf; + int gcspr_regnum = find_regno (regcache->tdesc, "gcspr"); + int features_enabled_regnum = find_regno (regcache->tdesc, + "gcs_features_enabled"); + int features_locked_regnum = find_regno (regcache->tdesc, + "gcs_features_locked"); + + supply_register (regcache, gcspr_regnum, ®set->gcspr_el0); + supply_register (regcache, features_enabled_regnum, + ®set->features_enabled); + supply_register (regcache, features_locked_regnum, ®set->features_locked); +} + bool aarch64_target::low_supports_breakpoints () { @@ -846,6 +883,10 @@ static struct regset_info aarch64_regsets[] = { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TLS, 0, OPTIONAL_REGS, aarch64_fill_tlsregset, aarch64_store_tlsregset }, + /* Guarded Control Stack registers. */ + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_GCS, + 0, OPTIONAL_REGS, + aarch64_fill_gcsregset, aarch64_store_gcsregset }, NULL_REGSET }; @@ -909,6 +950,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features) if (features.sme2) regset->size = AARCH64_SME2_ZT0_SIZE; break; + case NT_ARM_GCS: + if (features.gcs_linux) + regset->size = sizeof (user_gcs); + break; default: gdb_assert_not_reached ("Unknown register set found."); } @@ -940,6 +985,7 @@ aarch64_target::low_arch_setup () /* A-profile MTE is 64-bit only. */ features.mte = linux_get_hwcap2 (pid, 8) & HWCAP2_MTE; features.tls = aarch64_tls_register_count (tid); + features.gcs = features.gcs_linux = linux_get_hwcap (pid, 8) & HWCAP_GCS; /* Scalable Matrix Extension feature and size check. */ if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME) From patchwork Wed Jun 18 05:54:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897543 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp136279wrb; Tue, 17 Jun 2025 23:01:01 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVvaJP1t0yd0HhH0SAj70fPMJ7RfasHEPUYVxuWlAdqz+26Cayx1VWyFypV+rEIBxCRKTOnxg==@linaro.org X-Google-Smtp-Source: AGHT+IGaHWO+NfJMnajuQnlEmLvAwO8DS6NV8nD049J3Ocs+QBu0Ypn7TnGJvaHHT9WSPoMTZRL2 X-Received: by 2002:a05:6122:469a:b0:530:7e05:3839 with SMTP id 71dfb90a1353d-53149c0d1ddmr11566566e0c.11.1750226461244; Tue, 17 Jun 2025 23:01:01 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226461; cv=pass; d=google.com; s=arc-20240605; b=lqTAKnGXLU6BCrntY9LROYtgolaB4nl6XsubsezIj/pKspco1cdUCj7xSdZl873XgM 1Hy6eUD3fx9FU9azU4BnBoA2pf9avDBQ3Ohxr+ac/7vxcMJdiVoOOTXieybRbjrZBWm3 bTC6pDsxhXS/5E00GzF3f0EA7EuBGTFrqcXZ2M0QmHIHDhFlTol79Cd2VqKp+JY3Vtu5 Eg6Fc8GhefZQSEornvm54ez3kqA9OlR2XRHgdNBFgA7V5duYiiDMPy/53ZF39gXAnx36 lN2r6sFjo/Wn5GhHf5wT+oQVxzgc+7VzHH9Xx/GEPL7P5CPU6UEbw2LDtlB3wEDNk3C3 dNLQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=7gMHT+QuBNqwx8wE3rHEKapX7dO5bAysWX7HkETHjFY=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=gHw+u6XzU3bJQ6QXI6UwlANy2fUhC30czfIPOVzodzuRJzlDM2hKwDmd8NgOQKYyhu D7LeYuftST7e/NXGObsBypHRkLq9R3iejHSCrhpimhvhhcNZROWA+Yvn6J7zAJ1AJPdH 63U+EzWN6yqMdLI9+PuotZgBlzm6Qh4rmn6j5n2nhykoTlskO3n1o9EIEYPeNKnQ9vFs sqgYwb+4RxZOWp/2SbdJc7npRHCWTQo6hhOzAcy+r8FpNmDQEl/rujE89n+UiXow4z+g 1lykbl+75pi+XZu48Fn/mCSjvCO//mlsJs66Dnp97ZOJgA4bHAIHIcyMX/9hkWB1F7gg XsWA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="saT/XPoT"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id 71dfb90a1353d-5313e0e9281si2746526e0c.213.2025.06.17.23.01.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 23:01:01 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="saT/XPoT"; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B35473816969 for ; Wed, 18 Jun 2025 06:01:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B35473816969 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=saT/XPoT X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by sourceware.org (Postfix) with ESMTPS id 6D442388BA6C for ; Wed, 18 Jun 2025 05:55:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6D442388BA6C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6D442388BA6C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226107; cv=none; b=sHkng606jnoG8GS84jShoxVRoGAGM0YrgwcdaZCbfeBqyDkMxLX/XpxoIp4OWRS8i5AGN4nWhIENal+zgcTq1bMZoIMJGtDlDt0S7lV5BSdpIyDZZ0L86zZKkZEZ6agqPXrePVrhGl1axdhbua9kjfXUkG7k9PZuym0KH7rCrLo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226107; c=relaxed/simple; bh=3FmdXal1N5zP73/YIMAC9gqv9TIhRjPnpIf8VthEjOI=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Q+ZOyZgwfD/v7GlmTT9ecY+SspIGtesDusY2FfDEY48XnUJFBcEZDXyi8lDQazHVT8ZSQfXv4H9GOtCL6W4wkdEcTz061wbT71z3JBCw7slWkunF9bijApe8+olPObTsUFE5lOMSeGYVI+LeS2xo+6Q3ItsoG+nlAQ1FWrqGmk0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6D442388BA6C Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-73c17c770a7so7240292b3a.2 for ; Tue, 17 Jun 2025 22:55:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226106; x=1750830906; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7gMHT+QuBNqwx8wE3rHEKapX7dO5bAysWX7HkETHjFY=; b=saT/XPoTakXC/0/ppKpfNRIotzEnetXFurL+m3UJzX2YZE8v11CmV2/nZ6moe30Dw0 eChHvgkFPWxC765UK9KsPkkzL/4+P86L+BqFSuBcSs9NoxU8JxyltDm6eEOpLpSY01vg FYjwGo8qq/BhOKxXRVSlPJ7HmL8abiIsk0DGD6UMrh7jW3bPBlBVWP8DRR60hAdugrOA ViOqv+pY5+YgJl56kd3lW06cO/FMeZWFTVz1JgZhcQAnPVD85RIBhkkIELrEMmXBChrL CSMMi/799mT55Bbjgs/CxCzWDW1reRE9DVASVc4GI/V2RKpjBUdwYoJDX6lvyV+uitRc XxeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226106; x=1750830906; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7gMHT+QuBNqwx8wE3rHEKapX7dO5bAysWX7HkETHjFY=; b=vm1FGgVrS91/kPvgHz4Bxe16uqU3+PAvVBejEtDF4uH8y2w5+PZRlrzMYo30+QGI6e voZ2IDuqWPX/0P3rKjJUEvsnQUMYYyhUOebTp0t+VWONq9plXCdcm3HXaFFOmdiTIDn5 M6Yzp+reDOC0y9JMHVgags0mdyrIrBRWZReMSHNOj9+8XdF/wnFv7ziTUHi2fn/hWXfC yJjRzm/B54vjvfF006ODDSlbLXR5V3cJqjnDG3PCz3yUw9llbqv8NPRbehSZ+Ok4V6ef LOYI0RVEjdoZjaasgd4dw669qfW+N25nQ9PCBqlqOcuVvPS68VUWj3UgAC/1HapCmEvm iF4w== X-Gm-Message-State: AOJu0Yyfw0M57nuen1YFjPQqL89LY73oAbvURs4k9OQdZIJJ5RXyLp6X HaEVIv9MeuF2yJTHCBoNDpm3+38k5vCcCKiu/07wLm8q4sv4ey8ZgW7IhxUt8lxeHAaMqGxp2cH eMPRp X-Gm-Gg: ASbGncvOvlp6Bs54nEnxUASRLppr1h5TEIJk6MHnYI4QWhOnQlvV+SmQf7j8ycZvlBd WrBQSypGNsRgVAWDMbXpotWBfmgvQjL9RP0AjSvuYeiVd0Y79gjsslSasawcWwzPMbSPOo7NB/y vdJ+gk285RfkUv961N4EVyxjDHZDJDaI4Zgy8ctqbe6oqj3B6i6r5EguXtiJITTyli16BnSNOdq M4IqlwgOn3jSAyymPPcR4C1pfGSx2JIlFvzPSQeadkdawjANlEWZO592Jp4Vg7Xz9KCAstaYsfh asRo+d5zj9q6NsGm/TEKr0TNeodMjTskYaLv5DX1FQGwdTB6LUbR5AC1SPILgF+bywHZ X-Received: by 2002:a05:6a00:8510:b0:748:2cbb:be51 with SMTP id d2e1a72fcca58-7489cfde777mr12745488b3a.17.1750226106277; Tue, 17 Jun 2025 22:55:06 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-748900d7340sm10434935b3a.179.2025.06.17.22.55.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:55:05 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 6/9] GDB: aarch64-linux: GCS support in Linux signals Date: Wed, 18 Jun 2025 02:54:42 -0300 Message-ID: <20250618055445.709416-7-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org The signal frame can have a GCS context, so teach GDB how to use it. Also, there's a new SEGV sigcode when the inferior does an illegal memory access in the Guarded Control Stack, so display a message when that is the case. --- gdb/aarch64-linux-tdep.c | 83 ++++++++++++++++++--- gdb/linux-tdep.h | 4 + gdb/testsuite/gdb.arch/aarch64-gcs-core.exp | 6 +- gdb/testsuite/gdb.arch/aarch64-gcs.exp | 7 +- 4 files changed, 88 insertions(+), 12 deletions(-) Changes since v1: - Adopt Luis' suggested wording for warning about error reading GCSPR from the signal frame context. - Use aarch64_gdbarch_tdep::has_gcs_linux in aarch64_linux_sigframe_init instead of has_gcs. - Moved SEGV_CPERR definition from gdb/arch/aarch64-gcs-linux.h to gdb/linux-tdep.h (suggested by Christina). - Moved documentation changes to its own patch. - Add the testcase changes related to the code in this patch. diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index ee3f7bfd9928..6bd9dfc47d81 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -165,6 +165,7 @@ #define AARCH64_ZA_MAGIC 0x54366345 #define AARCH64_TPIDR2_MAGIC 0x54504902 #define AARCH64_ZT_MAGIC 0x5a544e01 +#define AARCH64_GCS_MAGIC 0x47435300 /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC. */ #define AARCH64_EXTRA_DATAP_OFFSET 8 @@ -206,6 +207,11 @@ the signal context state. */ #define AARCH64_SME2_CONTEXT_REGS_OFFSET 16 +/* GCSPR register value offset in the GCS signal frame context. */ +#define AARCH64_GCS_CONTEXT_GCSPR_OFFSET 8 +/* features_enabled value offset in the GCS signal frame context. */ +#define AARCH64_GCS_CONTEXT_FEATURES_ENABLED_OFFSET 16 + /* Holds information about the signal frame. */ struct aarch64_linux_sigframe { @@ -246,6 +252,13 @@ struct aarch64_linux_sigframe bool za_payload = false; /* True if we have a ZT entry in the signal context, false otherwise. */ bool zt_available = false; + + /* True if we have a GCS entry in the signal context, false otherwise. */ + bool gcs_availabe = false; + /* The Guarded Control Stack Pointer Register. */ + uint64_t gcspr; + /* Flags indicating which GCS features are enabled for the thread. */ + uint64_t gcs_features_enabled; }; /* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the @@ -526,6 +539,39 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame, signal_frame.zt_section = section; signal_frame.zt_available = true; + section += size; + break; + } + case AARCH64_GCS_MAGIC: + { + gdb_byte buf[8]; + + /* Extract the GCSPR. */ + if (target_read_memory (section + AARCH64_GCS_CONTEXT_GCSPR_OFFSET, + buf, 8) != 0) + { + warning (_("Failed to read the GCS pointer from the GCS signal" + " frame context.")); + section += size; + break; + } + + signal_frame.gcspr = extract_unsigned_integer (buf, byte_order); + + /* Extract the features_enabled field. */ + if (target_read_memory (section + + AARCH64_GCS_CONTEXT_FEATURES_ENABLED_OFFSET, + buf, sizeof (buf)) != 0) + { + warning (_("Failed to read the enabled features from the GCS" + " signal frame context.")); + section += size; + break; + } + + signal_frame.gcs_features_enabled + = extract_unsigned_integer (buf, byte_order); + signal_frame.gcs_availabe = true; section += size; break; } @@ -703,6 +749,19 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self, + AARCH64_TPIDR2_CONTEXT_TPIDR2_OFFSET); } + /* Restore the GCS registers, if the target supports it and if there is + an entry for them. */ + if (signal_frame.gcs_availabe && tdep->has_gcs_linux ()) + { + /* Restore GCSPR. */ + trad_frame_set_reg_value (this_cache, tdep->gcs_reg_base, + signal_frame.gcspr); + /* Restore gcs_features_enabled. */ + trad_frame_set_reg_value (this_cache, tdep->gcs_linux_reg_base, + signal_frame.gcs_features_enabled); + /* gcs_features_locked isn't present in the GCS signal context. */ + } + trad_frame_set_id (this_cache, frame_id_build (signal_frame.sp, func)); } @@ -2486,17 +2545,18 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (!tdep->has_mte () || siggnal != GDB_SIGNAL_SEGV) + if (!(tdep->has_mte () || tdep->has_gcs ()) || siggnal != GDB_SIGNAL_SEGV) return; CORE_ADDR fault_addr = 0; - long si_code = 0; + long si_code = 0, si_errno = 0; try { /* Sigcode tells us if the segfault is actually a memory tag violation. */ si_code = parse_and_eval_long ("$_siginfo.si_code"); + si_errno = parse_and_eval_long ("$_siginfo.si_errno"); fault_addr = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr"); @@ -2507,13 +2567,18 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, return; } - /* If this is not a memory tag violation, just return. */ - if (si_code != SEGV_MTEAERR && si_code != SEGV_MTESERR) + const char *meaning; + + if (si_code == SEGV_MTEAERR || si_code == SEGV_MTESERR) + meaning = _("Memory tag violation"); + else if (si_code == SEGV_CPERR && si_errno == 0) + meaning = _("Guarded Control Stack error"); + else return; uiout->text ("\n"); - uiout->field_string ("sigcode-meaning", _("Memory tag violation")); + uiout->field_string ("sigcode-meaning", meaning); /* For synchronous faults, show additional information. */ if (si_code == SEGV_MTESERR) @@ -2539,7 +2604,7 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, uiout->field_string ("logical-tag", hex_string (ltag)); } } - else + else if (si_code != SEGV_CPERR) { uiout->text ("\n"); uiout->text (_("Fault address unavailable")); @@ -2841,9 +2906,6 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Register a hook for checking if an address is tagged or not. */ set_gdbarch_tagged_address_p (gdbarch, aarch64_linux_tagged_address_p); - set_gdbarch_report_signal_info (gdbarch, - aarch64_linux_report_signal_info); - /* Core file helpers. */ /* Core file helper to create a memory tag section for a particular @@ -2860,6 +2922,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) aarch64_linux_decode_memtag_section); } + if (tdep->has_mte () || tdep->has_gcs ()) + set_gdbarch_report_signal_info (gdbarch, aarch64_linux_report_signal_info); + /* Initialize the aarch64_linux_record_tdep. */ /* These values are the size of the type that will be used in a system call. They are obtained from Linux Kernel source. */ diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h index 7083635b976c..0bee4b34845d 100644 --- a/gdb/linux-tdep.h +++ b/gdb/linux-tdep.h @@ -26,6 +26,10 @@ struct inferior; struct regcache; +#ifndef SEGV_CPERR +#define SEGV_CPERR 10 /* Control protection error. */ +#endif + /* Enum used to define the extra fields of the siginfo type used by an architecture. */ enum linux_siginfo_extra_field_values diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp index ef7e507407a4..581abf2e06e9 100644 --- a/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-core.exp @@ -37,7 +37,8 @@ gdb_test "continue" \ [multi_line \ "Continuing\\." \ "($hex\r\n)?" \ - "Program received signal SIGSEGV, Segmentation fault\\." \ + "Program received signal SIGSEGV, Segmentation fault" \ + "Guarded Control Stack error\\." \ "function \\(gcspr=$hex\\) at .*aarch64-gcs-core.c:$decimal" \ {.*__asm__ volatile \("ret\\n"\);}] \ "continue to SIGSEGV" @@ -67,7 +68,8 @@ proc check_core_file {core_filename saved_gcspr} { if [gdb_test "core $core_filename" \ [multi_line \ "Core was generated by .*\\." \ - "Program terminated with signal SIGSEGV, Segmentation fault\\." \ + "Program terminated with signal SIGSEGV, Segmentation fault" \ + "Guarded Control Stack error\\." \ "#0 function \\(gcspr=$hex\\) at .*aarch64-gcs-core.c:$decimal" \ "$decimal.*__asm__ volatile \\(\"ret\\\\n\"\\);"] \ "load core file"] { diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs.exp b/gdb/testsuite/gdb.arch/aarch64-gcs.exp index ea70cc6ef2e9..907dcb43e78b 100644 --- a/gdb/testsuite/gdb.arch/aarch64-gcs.exp +++ b/gdb/testsuite/gdb.arch/aarch64-gcs.exp @@ -51,17 +51,22 @@ gdb_test "continue" \ ".*\r\nBreakpoint \[0-9\]+, handler \\(sig=10\\) at .*aarch64-gcs.c.*handler_gcspr = get_gcspr \\(\\);" \ "continue to signal handler" +gdb_test_no_output "set \$gcspr_in_handler = \$gcspr" \ + "save gcspr value in handler for later" # Select the frame above the frame, which makes GDB # unwind the gcspr from the signal frame GCS context. gdb_test "frame 2" "#2 ($hex in )?\\S+ \\(.*\\) (at|from) \\S+.*" \ "reached frame 2" gdb_test "print \$gcspr" ". = \\(void \\*\\) $hex" "gcspr in frame level 2" +gdb_test "print \$gcspr == \$gcspr_in_handler + 8" ". = 1" \ + "gcspr unwound from signal context is correct" gdb_test "continue" \ [multi_line \ "Continuing\\." \ "" \ - "Program received signal SIGSEGV, Segmentation fault\\." \ + "Program received signal SIGSEGV, Segmentation fault" \ + "Guarded Control Stack error\\." \ "normal_function2 \\(\\) at .*aarch64-gcs.c:$decimal" \ "${decimal}\\s+__asm__ volatile \\(\"ret\\\\n\"\\);"] \ "continue to SIGSEGV" From patchwork Wed Jun 18 05:54:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897541 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp135566wrb; Tue, 17 Jun 2025 22:59:16 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVdDEu8GuT5FZKUARRUsi8UR9PP1OM8w0XwkDRh1214Ji2uhxujvkoX+OKRhLZK4afWF8ovLA==@linaro.org X-Google-Smtp-Source: AGHT+IHEIZFxcEXPlrdpDLefY/SwNO1c/qIh+KxfmnhvF9xCmBMWwGTyjpjc86pdNWGGp89McVJi X-Received: by 2002:a05:620a:2795:b0:7d3:8df3:f5b1 with SMTP id af79cd13be357-7d3c6cf570dmr2480517385a.39.1750226356233; Tue, 17 Jun 2025 22:59:16 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226356; cv=pass; d=google.com; s=arc-20240605; b=gQA1sRLbOagofDfLa/sz0CXX0PKhO39AVG5LHwEh/7LtIbRX24PxuZOc1ieXGwbNBT 8W0PgpKjBYt0P85AnppRxbdF7B+AGXNdt+uI1SfxqdaMgnO+FTe5VRfiLyXp1ZtBAsy0 y98bkd/Ht5S0gDNMjpvHdmosO/BOZ9OpFHPMzTF7Wbfk7YyLGv4NzZaDqeE2U0EoE4Nw s7N2r3Dze1BiL1nrHUUiNMSWIcXsuAYiVm7tEdA++d1g9cAoDUEsr0I/d65eA/PkyQO3 mz3gOpWFddXJ/FSlb0x7wFAw74dNq/sFpe48b6qAzXZBVFtvbRG3t25DtA+jt/mRQaca NVlQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=LhJ2xVcbJ7uF0ZlLI8MauJ6Au62sj2wFfTPN6Ke3Pwo=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=OTPBOPGTCVHUe+7FI1u6gyZxFg0EsdsUrry3ZNV5yHDE1Tz7sXiTDv+6WOCMYOquB8 eD1DTPqRoee9jzQZit9AiN6KTkXZH+ry4IsQRChvEw9+nw1jQNegMKgEFJrFIumh+FlY mSHYaEmG9T1XiJx7of0Ly/8jQ6BnwBXiSJTJxB/L15IEO3C1Ureb+3t+JgG03S6XS092 Mrd7BpFwCjQ5xW4i8CNdn0sooyb/zyF2+smNSMAD5wNs6joFyHUmJTb2bhwIv43qTiyr c6dji6YP5VeRxB+FBzGcliIU85kR5/5en1y+sKpjOYCnMVtcybnKHMeI+cxrliqwk47B Qi1A==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Q2AYTv91; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7d3b8f3a55bsi1297378485a.554.2025.06.17.22.59.16 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:59:16 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Q2AYTv91; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C6CDE3816944 for ; Wed, 18 Jun 2025 05:59:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C6CDE3816944 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=Q2AYTv91 X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by sourceware.org (Postfix) with ESMTPS id E36133816949 for ; Wed, 18 Jun 2025 05:55:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E36133816949 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E36133816949 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::102e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226112; cv=none; b=VzXcERMc7/hBJVfcaq/4EpM6vNcgOkxPzK1UNqXliEZ6ISm3t0APPHtUnMK+/mbR6+uvUUeRUyKHbO+sQNW0gUFtlDEq44pHQ2jeQkWliYkIP5+EP5gLIkztBPP98XSifj82gBzq3L/7rZkNKOB/1xlCP49SQjVQxrm95MLrN8w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226112; c=relaxed/simple; bh=54N2IPMM31s2EB6cPeWbxIAsG0izz/qzsiAexnDiyIU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=jbFyxmC1rmf0vdNb6+WZ9WAtM2+Gn77aFw/yY67YaG/F0Lzxuw2Fh4DJ1zXLdIT/f4GM30X2WlXMuaPExSB5NAaBRexdeIIM+c0RP+AM1GEeBl4APQLFuHD86YS751hpbuoMKDw42XZ6McdINzE1EUY4Rs7VccgJqRAJRCQME4I= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E36133816949 Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-313910f392dso5779410a91.2 for ; Tue, 17 Jun 2025 22:55:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226110; x=1750830910; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LhJ2xVcbJ7uF0ZlLI8MauJ6Au62sj2wFfTPN6Ke3Pwo=; b=Q2AYTv91CBCnU+3eClz4oJz8GydJdNDS7ciXPUkveq87ygDI9oiZfMNpS1IfqQfvQD bnbibKHMTLy1l6Mk0Gmt+h8dsCEMqzJnvY0F+W9InDBF3I6Z8CWsxCDfhLsH3SvGyK/p 6dYVFgY3C/P8UgdcVeLRYiEXUA9fHRaGpKuUoAPK9Vwt23PYHYzyXNvnn+Lmrb3fSA9g ZLtElKW02nBNfM3B5YxE31u4mDvStUgJD1WhA5mpaw69yjokC0L8JDsFNnj6yIg02WBO HhgB5TqEwnXRJ4ffcGqrRKU6GOJTG/uo8KKrCfB7iycm6A6cy/Czz0yLcEjfnQ5vWJbf 7mBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226110; x=1750830910; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LhJ2xVcbJ7uF0ZlLI8MauJ6Au62sj2wFfTPN6Ke3Pwo=; b=JzlQqgIRgVK+hnOdAb5a+hOoel7b78TPCpCIZDGHe1DLlcBJq224FI+hkPU4mdOoC5 Y48ACN8M4LROOi4A61DHxXXdOizGFLFoq+JKz6sBF9019MxrSbrZAUgTd3nIyapmOvvI 67ljmSBXUGJT3vUxNDIyYAHzZLiUwBjbnU3UmRi4032fVhyA4fXQWMgI9muXkKnpxGVL lMgNM8VyPhSr4msJDXJGt546Eoo2opDyyGnpGLnjDjuQpnJ6YK+7Y64ZWNR3r/hWVMsM l96Xoi+YpfrlpLfU0wp8jYlNBL8L+1hm5M8uAIhXzBr7UOYY4gyQCdof/GmjQaVE3tmf R1qA== X-Gm-Message-State: AOJu0YyH1fF23D4zjzeikFpZAL6HHkVtlCwEUiIa6lju1IxOkuuY/umd rHW+lYaE0CgGLZDrN2yEeH0Z17hsQB6ijEkb8FDYYLVPi2P8ShpSGq38k1snfZANt7yMqepKZvd o1E08 X-Gm-Gg: ASbGnct5OeWIHK6yWdCIH1rRzGc2Uv5A5TlCa2ZDSfGIhocqdHlVSOdsKOdwP+j1GYn HxKpMYqH5sJwE+FHdDd9PyVkFA+RSuLbDspk5FxyGhpYGqV9qkAe8yaxGdnPapRJKE6nvwHy97a Komm4QzRzYFb7AasfV2Uy9JissM0k2xZJeOi64uUumz/Ptf+Am1VVHf2I/SUisCWrGq2nsavO6P yWGISftY/kx7XDADrX91Zrs31etHOOoKT3OJ2eywLjJcTRMmr59jHzYmwBLITgOtd91VS6fN1LI X1CWjEUjjIyDf5oHgg0ITIleznK1Eu+lUVsP/aLx/ecu6RId//be2vNsA9+qnmtzp5Xo X-Received: by 2002:a17:90b:4cce:b0:312:639:a058 with SMTP id 98e67ed59e1d1-313f1d96ee5mr24784865a91.27.1750226109543; Tue, 17 Jun 2025 22:55:09 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-313c1c5feebsm13283850a91.41.2025.06.17.22.55.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:55:09 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 7/9] GDB: aarch64-linux: Implement GCS support in displaced stepping Date: Wed, 18 Jun 2025 02:54:43 -0300 Message-ID: <20250618055445.709416-8-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org When doing displaced step on a branch and link instruction with the Guarded Control Stack enabled, it's necessary to manually push and pop the GCS entry for the function call since GDB writes a simple branch instruction rather than a branch and link instruction in the displaced step buffer. The testcase exercises GCS with displaced stepping by putting the breakpoint on the bl instruction to force GDB to copy it to the displaced stepping buffer. In this situation GDB needs to manually manage the Guarded Control Stack. --- gdb/aarch64-linux-tdep.c | 30 ++++ gdb/aarch64-tdep.c | 47 +++++- gdb/linux-tdep.h | 7 + .../gdb.arch/aarch64-gcs-disp-step.c | 140 ++++++++++++++++++ .../gdb.arch/aarch64-gcs-disp-step.exp | 90 +++++++++++ 5 files changed, 309 insertions(+), 5 deletions(-) create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp Changes since v1: - Use aarch64_gdbarch_tdep::has_gcs_linux in aarch64_linux_get_shadow_stack_pointer and aarch64_linux_init_abi instead of has_gcs. - Moved aarch64-gcs-disp-step.exp to this patch. diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 6bd9dfc47d81..63c6f6b76b92 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -2534,6 +2534,32 @@ aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address) return true; } +/* Implement the "get_shadow_stack_pointer" gdbarch method. */ + +static std::optional +aarch64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache, + bool &shadow_stack_enabled) +{ + aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + shadow_stack_enabled = false; + + if (!tdep->has_gcs_linux ()) + return {}; + + uint64_t features_enabled; + enum register_status status = regcache->cooked_read (tdep->gcs_linux_reg_base, + &features_enabled); + if (status != REG_VALID) + error (_("Can't read $gcs_features_enabled.")); + + CORE_ADDR gcspr; + status = regcache->cooked_read (tdep->gcs_reg_base, &gcspr); + if (status != REG_VALID) + error (_("Can't read $gcspr.")); + + shadow_stack_enabled = features_enabled & PR_SHADOW_STACK_ENABLE; + return gcspr; +} /* AArch64 Linux implementation of the report_signal_info gdbarch hook. Displays information about possible memory tag violations. */ @@ -3106,6 +3132,10 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) sections. */ set_gdbarch_use_target_description_from_corefile_notes (gdbarch, aarch64_use_target_description_from_corefile_notes); + + if (tdep->has_gcs_linux ()) + set_gdbarch_get_shadow_stack_pointer (gdbarch, + aarch64_linux_get_shadow_stack_pointer); } #if GDB_SELF_TEST diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 0e9e6644dd0a..e21c4a8e9ae1 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1911,6 +1911,24 @@ aarch64_push_gcs_entry (regcache *regs, CORE_ADDR lr_value) regcache_cooked_write_unsigned (regs, tdep->gcs_reg_base, gcs_addr); } +/* Remove the newest entry from the Guarded Control Stack. */ + +static void +aarch64_pop_gcs_entry (regcache *regs) +{ + gdbarch *arch = regs->arch (); + aarch64_gdbarch_tdep *tdep = gdbarch_tdep (arch); + CORE_ADDR gcs_addr; + + enum register_status status = regs->cooked_read (tdep->gcs_reg_base, + &gcs_addr); + if (status != REG_VALID) + error ("Can't read $gcspr."); + + /* Update GCSPR. */ + regcache_cooked_write_unsigned (regs, tdep->gcs_reg_base, gcs_addr + 8); +} + /* Implement the "shadow_stack_push" gdbarch method. */ static void @@ -3602,6 +3620,9 @@ struct aarch64_displaced_step_copy_insn_closure /* PC adjustment offset after displaced stepping. If 0, then we don't write the PC back, assuming the PC is already the right address. */ int32_t pc_adjust = 0; + + /* True if it's a branch instruction that saves the link register. */ + bool linked_branch = false; }; /* Data when visiting instructions for displaced stepping. */ @@ -3653,6 +3674,12 @@ aarch64_displaced_step_b (const int is_bl, const int32_t offset, /* Update LR. */ regcache_cooked_write_unsigned (dsd->regs, AARCH64_LR_REGNUM, data->insn_addr + 4); + dsd->dsc->linked_branch = true; + bool gcs_is_enabled; + gdbarch_get_shadow_stack_pointer (dsd->regs->arch (), dsd->regs, + gcs_is_enabled); + if (gcs_is_enabled) + aarch64_push_gcs_entry (dsd->regs, data->insn_addr + 4); } } @@ -3811,6 +3838,12 @@ aarch64_displaced_step_others (const uint32_t insn, aarch64_emit_insn (dsd->insn_buf, insn & 0xffdfffff); regcache_cooked_write_unsigned (dsd->regs, AARCH64_LR_REGNUM, data->insn_addr + 4); + dsd->dsc->linked_branch = true; + bool gcs_is_enabled; + gdbarch_get_shadow_stack_pointer (dsd->regs->arch (), dsd->regs, + gcs_is_enabled); + if (gcs_is_enabled) + aarch64_push_gcs_entry (dsd->regs, data->insn_addr + 4); } else aarch64_emit_insn (dsd->insn_buf, insn); @@ -3907,20 +3940,24 @@ aarch64_displaced_step_fixup (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs, bool completed_p) { + aarch64_displaced_step_copy_insn_closure *dsc + = (aarch64_displaced_step_copy_insn_closure *) dsc_; CORE_ADDR pc = regcache_read_pc (regs); - /* If the displaced instruction didn't complete successfully then all we - need to do is restore the program counter. */ + /* If the displaced instruction didn't complete successfully then we need + to restore the program counter, and perhaps the Guarded Control Stack. */ if (!completed_p) { + bool gcs_is_enabled; + gdbarch_get_shadow_stack_pointer (gdbarch, regs, gcs_is_enabled); + if (dsc->linked_branch && gcs_is_enabled) + aarch64_pop_gcs_entry (regs); + pc = from + (pc - to); regcache_write_pc (regs, pc); return; } - aarch64_displaced_step_copy_insn_closure *dsc - = (aarch64_displaced_step_copy_insn_closure *) dsc_; - displaced_debug_printf ("PC after stepping: %s (was %s).", paddress (gdbarch, pc), paddress (gdbarch, to)); diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h index 0bee4b34845d..fd4d060412e5 100644 --- a/gdb/linux-tdep.h +++ b/gdb/linux-tdep.h @@ -30,6 +30,13 @@ struct regcache; #define SEGV_CPERR 10 /* Control protection error. */ #endif +/* Flag which enables shadow stack in PR_SET_SHADOW_STACK_STATUS prctl. */ +#ifndef PR_SHADOW_STACK_ENABLE +#define PR_SHADOW_STACK_ENABLE (1UL << 0) +#define PR_SHADOW_STACK_WRITE (1UL << 1) +#define PR_SHADOW_STACK_PUSH (1UL << 2) +#endif + /* Enum used to define the extra fields of the siginfo type used by an architecture. */ enum linux_siginfo_extra_field_values diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c new file mode 100644 index 000000000000..3d895350ae42 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.c @@ -0,0 +1,140 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2025 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 . */ + +#include +#include +#include +#include +#include + +/* Feature check for Guarded Control Stack. */ +#ifndef HWCAP_GCS +#define HWCAP_GCS (1UL << 32) +#endif + +#ifndef PR_GET_SHADOW_STACK_STATUS +#define PR_GET_SHADOW_STACK_STATUS 74 +#define PR_SET_SHADOW_STACK_STATUS 75 +#define PR_SHADOW_STACK_ENABLE (1UL << 0) +#endif + +/* We need to use a macro to call prctl because after GCS is enabled, it's not + possible to return from the function which enabled it. This is because the + return address of the calling function isn't on the GCS. */ +#define my_syscall2(num, arg1, arg2) \ + ({ \ + register long _num __asm__("x8") = (num); \ + register long _arg1 __asm__("x0") = (long)(arg1); \ + register long _arg2 __asm__("x1") = (long)(arg2); \ + register long _arg3 __asm__("x2") = 0; \ + register long _arg4 __asm__("x3") = 0; \ + register long _arg5 __asm__("x4") = 0; \ + \ + __asm__ volatile("svc #0\n" \ + : "=r"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "r"(_arg5), "r"(_num) \ + : "memory", "cc"); \ + _arg1; \ + }) + +#define get_gcspr(void) \ + ({ \ + unsigned long *gcspr; \ + \ + /* Get GCSPR_EL0. */ \ + asm volatile("mrs %0, S3_3_C2_C5_1" : "=r"(gcspr) : : "cc"); \ + \ + gcspr; \ + }) + +static int __attribute__ ((noinline)) +function2 (void) +{ + return EXIT_SUCCESS; +} + +/* Put branch and link instructions being tested into their own functions so + that the program returns one level up in the stack after the displaced + stepped instruction. This tests that GDB doesn't leave the GCS out of sync + with the regular stack. */ + +static int __attribute__ ((noinline)) +function_bl (void) +{ + register int x0 __asm__("x0"); + + __asm__ ("bl function2\n" + : "=r"(x0) + : + : "x30"); + + return x0; +} + +static int __attribute__ ((noinline)) +function_blr (void) +{ + register int x0 __asm__("x0"); + + __asm__ ("blr %1\n" + : "=r"(x0) + : "r"(&function2) + : "x30"); + + return x0; +} + +int +main (void) +{ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + fprintf (stderr, "GCS support not found in AT_HWCAP\n"); + return EXIT_FAILURE; + } + + /* Force shadow stacks on, our tests *should* be fine with or + without libc support and with or without this having ended + up tagged for GCS and enabled by the dynamic linker. We + can't use the libc prctl() function since we can't return + from enabling the stack. */ + unsigned long gcs_mode; + int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to read GCS state: %d\n", ret); + return EXIT_FAILURE; + } + + if (!(gcs_mode & PR_SHADOW_STACK_ENABLE)) + { + gcs_mode = PR_SHADOW_STACK_ENABLE; + ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to configure GCS: %d\n", ret); + return EXIT_FAILURE; + } + } + + int ret1 = function_bl (); + int ret2 = function_blr (); + + /* Avoid returning, in case libc doesn't understand GCS. */ + exit (ret1 + ret2); +} diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp new file mode 100644 index 000000000000..10b09a4d980e --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-disp-step.exp @@ -0,0 +1,90 @@ +# Copyright 2025 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 . + +# Test displaced stepping in a program that uses a Guarded Control Stack. + +require allow_aarch64_gcs_tests + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return +} + +if ![runto_main] { + return +} + +gdb_test_no_output "set breakpoint auto-hw off" +gdb_test_no_output "set displaced-stepping on" + +# Get address of the branch and link instructions of interest. +set addr_bl 0 +set test "get address of bl instruction" +gdb_test_multiple "disassemble function_bl" $test -lbl { + -re "\r\n\\s+($hex) <\\+${decimal}>:\\s+bl\\s+${hex} (?=\r\n)" { + set addr_bl $expect_out(1,string) + exp_continue + } + -re "$::gdb_prompt \$" { + gdb_assert { $addr_bl != 0 } $test + } +} + +set addr_blr 0 +set test "get address of blr instruction" +gdb_test_multiple "disassemble function_blr" $test -lbl { + -re "\r\n\\s+($hex) <\\+${decimal}>:\\s+blr\\s+x${decimal}(?=\r\n)" { + set addr_blr $expect_out(1,string) + exp_continue + } + -re "$::gdb_prompt \$" { + gdb_assert { $addr_blr != 0 } $test + } +} + +if { $addr_bl == 0 || $addr_blr == 0 } { + return +} + +gdb_test "break *$addr_bl" \ + "Breakpoint $decimal at $hex: file .*aarch64-gcs-disp-step.c, line ${decimal}." \ + "set breakpoint at bl instruction" + +gdb_test "break *$addr_blr" \ + "Breakpoint $decimal at $hex: file .*aarch64-gcs-disp-step.c, line ${decimal}." \ + "set breakpoint at blr instruction" + +gdb_test "continue" \ + [multi_line \ + {Continuing\.} \ + "" \ + "Breakpoint $decimal, function_bl \\(\\) at .*aarch64-gcs-disp-step.c:${decimal}(?: \\\[GCS error\\\])?" \ + {[^\r\n]+"bl function2\\n"}] \ + "continue to breakpoint at bl" + +gdb_test "continue" \ + [multi_line \ + {Continuing\.} \ + "" \ + "Breakpoint $decimal, $hex in function_blr \\(\\) at .*aarch64-gcs-disp-step.c:${decimal}(?: \\\[GCS error\\\])?" \ + {[^\r\n]+"blr %1\\n"}] \ + "continue to breakpoint at blr" + +gdb_test "continue" \ + [multi_line \ + "Continuing\\." \ + "\\\[Inferior 1 \\(process $decimal\\) exited normally\\\]"] \ + "continue until inferior exits" From patchwork Wed Jun 18 05:54:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897544 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp136783wrb; Tue, 17 Jun 2025 23:02:00 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCX1ye4JQI9OqEPr/rJ5/XoxDOTdRyNezs0x1M3EZMBtZvn3IbXLoSa2ca8ks25/qzhXhNM0SQ==@linaro.org X-Google-Smtp-Source: AGHT+IFFzRRXQoGx0EILFEdkFi0X5HIf/a6JG1XHNMwDqT4Q6VaYxtMTNmzXoAArdDf/CBoUkIg7 X-Received: by 2002:a05:6102:4bc3:b0:4e5:996d:f23c with SMTP id ada2fe7eead31-4e7f61f1150mr12322162137.20.1750226520207; Tue, 17 Jun 2025 23:02:00 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226520; cv=pass; d=google.com; s=arc-20240605; b=czuDjjW+eYXhnl43Rn+m3L4IIL4dygMlFPdNAlVWDGEeJLcMyIc6hfXLecAC7HKejH qFIy9i8NnuRZhzt0AwoDebvDZ07Vz4yxxYCMfhvaXQ4g+Lvl5Jk9fCWygW5RdJZLT+dn g+4YL9mq8SdObegVIFAWy2BGDNkQiTWwtvEsKP15hws7SyBNISJTBce1hKW0uwNW2PlY I3awQvYUJbQ6VL6NyWUCQ9eH1ya9n1vTVVvAXf6AQuhBdF4VvVU0OC9RpWNboDshetwW hXdlEnbObpogMcQ96K/EiCpX9Hmw0DKqnRJR8j5V2q7ex6T4Dlu7QW/cMe8fYvlRJ6zC 4gfg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=MhUqNCE6cYIx7WzuNKIg+n1jjyKZEmm3GfiThxLvxrs=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=iwU4D4/6aWQJwYXHjijoCyd5xdMvDJZp9bwhsZk6jv7UGDQeCz3dtJwdCuFG/AfYov t2BOgc04SW4kT2hCO6yMkH4E/MQyfSlZzelt7IOBJJu87oOn27GqGz4eKpED78ZfOiiP uMqZBJAlNKHvy4LxwOtskMTn29gSPaaHzoczR1iiC4QJqVuULb6v6kpvKjv1jCrfXV8C PG8gaARUoRheeFcGpU2aAxasezgPrvPm4FYvZzHzvSSCIm0KVwqFNu+wxvkBFmT/XVpu xfTTIxU4k/YrpN0GgKeZlbp9J3863/pi8juyQTS+L1+sY7If1pZp7LZoXb+RuMADHvXu dAtQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EpRa4qef; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id ada2fe7eead31-4e7e710797bsi2765242137.515.2025.06.17.23.02.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 23:02:00 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EpRa4qef; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9C515381695B for ; Wed, 18 Jun 2025 06:01:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9C515381695B Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=EpRa4qef X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634]) by sourceware.org (Postfix) with ESMTPS id A1DDF389A094 for ; Wed, 18 Jun 2025 05:55:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A1DDF389A094 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A1DDF389A094 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::634 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226113; cv=none; b=dXxCr51cp4Q5Jkk5X1zvtVTm7ykPoojJMSjApZHFWc/jcQHE3i216rF7i2Hp0oNEyajaQW6dITZiH3RnEzLFe1gCChRuB/wScToUteunpOpBOA4IhhDKO/v2wozhFEYW7Qmnaw2S1vgrVBBg/4KAiH6z4xTRaTd26zWrYdRncGM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226113; c=relaxed/simple; bh=DktTPmIiLZzbMILoPRrl5fMbGNj3uDbirKBeyqukvY8=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=qacd07lLVTKa8IS7LOWGFkntk9xc6a5vV7oX4PE4Tcst31imOex8hlUlC4m4mhix2bolI/Yr6WGeb393M8YG8d8O425uO/qpISMBtk1PpUNtLhI3iG5aL5VBw2qks/n6OwrRee6n806VaQokGzlcIowI9GkmiqzmzBW7bl/2V44= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A1DDF389A094 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-2349f096605so87680305ad.3 for ; Tue, 17 Jun 2025 22:55:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226112; x=1750830912; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MhUqNCE6cYIx7WzuNKIg+n1jjyKZEmm3GfiThxLvxrs=; b=EpRa4qefrTQ+d0y2qEBHtDtGnAtP5KgpN1wcgvnkTV8eQaEH8s98EiT+hKAl2yTHG/ 0vSgU/obzsjLrAQyHHq5HlScEahB653GY3FS0AmmqdTOZXVk8No+TaZkDXRcJoh9oPqt Yxb73eEfc5akCgaA0+G//Q1yh5ZYcL5FFV9K0et0wiZ9kCE1NpI5qgV5v2UkEKzqMOwu BqdqEjoVUvxt+qwP18T7x8YdAExEdgBkpYTp2DFuwTTyIq+G/aFosXDcYhwLUJEei9sI i6sdPdapBbGn6b4rN7Dw8l9ZyLtqo6pa3Hfrav7nOPS6Pr0anwuXBhUSs8Q8OtDS9/xR iP4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226112; x=1750830912; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MhUqNCE6cYIx7WzuNKIg+n1jjyKZEmm3GfiThxLvxrs=; b=hIVZ2xPJLRqRGf45z1p6+UrVfjSGrudUXICCC7YMZcDoerhR7nCS3wT9jFfNDjL/7w RfYdQRD+7+6gMDGOhIgWTF7D0lsJHGKFLfGVqUm76o8IzfFkuKXLd+jdGDkzZnTCWJme MzLFRSjmSJ+LZk8Zz22tI4/VC8AJxiJlp7D30aLaY0+kRJV6VOox+sWrIQn3UNA35qdI MpX8c4pZV4JCWJcDPz+igapAcoOqL/vPaY+u6qFgqKlqNASpn289RpQ4bGIqsdW5kPC/ I/0ZCpxNw6tMkbW/wq8t4OlFlXfqIbPYzf+x7Xb3acQ7LQ51bHwOqF1xXaiOm5h96LNd u2gA== X-Gm-Message-State: AOJu0YxUQlmbx/7BmG42J00yRsovusKc3MjNR5ZBw//LBXjn8KINrG2u w/XJOs6EvleFWhEkSocUEFSiYBvgYFoYZ3v7cbWaBX3RdN4qkPyc1wStuEvcz+VJSe4QFjAyrHY lWS7L X-Gm-Gg: ASbGncsLBR24N5VSSIOIAXmtKY2dtjIpQCof08bbKEsIqjRqcDdWP7hZLhPcR0t4ECW SWT4dMX9zA/PbAQIruAdxQ5s9uQr7fhDiorGfV5rcaxp+01mh09P7IQpUpKvdX/HfN1QHE0kyfw rvkdxgMXEtoceIDeGZ6OJ0bQOqFg3+vNlRIjKwUcMLcm3HLBzAAmMztSfhuHlVCaOdb+LlXMkWA CCBA1Z8vMx4f6WncoOA6j7wiZycLBN4fSjfH81kmMQ9QFG/FWHZzE+UpQRTvVloF5KhPF7j09sb lJUQRYf+ymA4NcsWSQk0bPtAijGEMVLYDp7grxPWR+y+EBNITRZiBflcGUCibmQIGDbTH6LQ6W8 A9dk= X-Received: by 2002:a17:903:19cc:b0:235:f078:4733 with SMTP id d9443c01a7336-2366b3135f2mr211510815ad.8.1750226112478; Tue, 17 Jun 2025 22:55:12 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2365d8a1a89sm91481125ad.81.2025.06.17.22.55.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:55:11 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 8/9] GDB: aarch64-linux: Support unwinding the GCSPR Date: Wed, 18 Jun 2025 02:54:44 -0300 Message-ID: <20250618055445.709416-9-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org The GCSPR is almost always updated implicitly by the hardware, so the compiler doesn't generate DWARF unwind information for it. Therefore add an unwinding function that calculates the value of the GCSPR in the previous frame based on its value in this frame. Some sanity checking is done by confirming that the calculated value is within a Guarded Control Stack memory area. This function is the same as amd64_linux_dwarf2_prev_ssp, written by Christina Schimpe to unwind Intel's SSP register. The gdb.arch/aarch64-gcs-return.exp testcase is lightly adapted from gdb.arch/amd64-shadow-stack-cmds.exp. --- gdb/aarch64-linux-tdep.c | 54 ++++++- gdb/aarch64-tdep.c | 6 + gdb/aarch64-tdep.h | 4 + gdb/testsuite/gdb.arch/aarch64-gcs-return.c | 105 ++++++++++++++ gdb/testsuite/gdb.arch/aarch64-gcs-return.exp | 132 ++++++++++++++++++ 5 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-return.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-return.exp The patch is new in this series. The code and testcase are lightly adapted from: [PATCH v4 07/11] gdb: Handle shadow stack pointer register unwinding for amd64 linux. https://inbox.sourceware.org/gdb-patches/20250617121147.1956686-8-christina.schimpe@intel.com/ diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 63c6f6b76b92..2257b33d1e5f 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -32,6 +32,7 @@ #include "symtab.h" #include "tramp-frame.h" #include "trad-frame.h" +#include "dwarf2/frame.h" #include "target.h" #include "target/target.h" #include "expop.h" @@ -2561,6 +2562,54 @@ aarch64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache, return gcspr; } +/* Implement Guarded Control Stack Pointer Register unwinding. For each + previous GCS pointer check if its address is still in the GCS memory + range. If it's outside the range set the returned value to unavailable, + otherwise return a value containing the new GCS pointer. */ + +static value * +aarch64_linux_dwarf2_prev_gcspr (const frame_info_ptr &this_frame, + void **this_cache, int regnum) +{ + value *v = frame_unwind_got_register (this_frame, regnum, regnum); + gdb_assert (v != nullptr); + + gdbarch *gdbarch = get_frame_arch (this_frame); + + if (v->entirely_available () && !v->optimized_out ()) + { + int size = register_size (gdbarch, regnum); + bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR gcspr = extract_unsigned_integer (v->contents_all ().data (), + size, byte_order); + + /* Starting with v6.13, the Linux kernel supports Guarded Control + Stack. Using /proc/PID/smaps we can only check if the current + GCSPR points to GCS memory. Only if this is the case a valid + previous GCS pointer can be calculated. */ + std::pair range; + if (linux_address_in_shadow_stack_mem_range (gcspr, &range)) + { + /* The GCS grows downwards. To compute the previous GCS pointer, + we need to increment the GCSPR. */ + CORE_ADDR new_gcspr = gcspr + 8; + + /* If NEW_GCSPR points to the end of or before (<=) the current + GCS memory range we consider NEW_GCSPR as valid. */ + if (new_gcspr <= range.second) + return frame_unwind_got_address (this_frame, regnum, new_gcspr); + } + } + + /* Return a value which is marked as unavailable in case we could not + calculate a valid previous GCS pointer. */ + value *retval + = value::allocate_register (get_next_frame_sentinel_okay (this_frame), + regnum, register_type (gdbarch, regnum)); + retval->mark_bytes_unavailable (0, retval->type ()->length ()); + return retval; +} + /* AArch64 Linux implementation of the report_signal_info gdbarch hook. Displays information about possible memory tag violations. */ @@ -3134,8 +3183,11 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) aarch64_use_target_description_from_corefile_notes); if (tdep->has_gcs_linux ()) - set_gdbarch_get_shadow_stack_pointer (gdbarch, + { + set_gdbarch_get_shadow_stack_pointer (gdbarch, aarch64_linux_get_shadow_stack_pointer); + tdep->fn_prev_gcspr = aarch64_linux_dwarf2_prev_gcspr; + } } #if GDB_SELF_TEST diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index e21c4a8e9ae1..c479a0b70323 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1408,6 +1408,12 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, return; } } + if (tdep->has_gcs () && tdep->fn_prev_gcspr != nullptr + && regnum == tdep->gcs_reg_base) + { + reg->how = DWARF2_FRAME_REG_FN; + reg->loc.fn = tdep->fn_prev_gcspr; + } } /* Implement the execute_dwarf_cfa_vendor_op method. */ diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index 54ca641a35a3..99e7d26ce4ab 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -23,6 +23,7 @@ #define GDB_AARCH64_TDEP_H #include "arch/aarch64.h" +#include "dwarf2/frame.h" #include "displaced-stepping.h" #include "infrun.h" #include "gdbarch.h" @@ -190,6 +191,9 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base available. */ int gcs_linux_reg_base = -1; + /* Function to unwind the GCSPR from the given frame. */ + fn_prev_register fn_prev_gcspr = nullptr; + /* Returns true if the target supports GCS. */ bool has_gcs () const diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-return.c b/gdb/testsuite/gdb.arch/aarch64-gcs-return.c new file mode 100644 index 000000000000..c6ade8af7e9f --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-return.c @@ -0,0 +1,105 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2025 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 . */ + +#include +#include +#include +#include +#include + +/* Feature check for Guarded Control Stack. */ +#ifndef HWCAP_GCS +#define HWCAP_GCS (1UL << 32) +#endif + +#ifndef PR_GET_SHADOW_STACK_STATUS +#define PR_GET_SHADOW_STACK_STATUS 74 +#define PR_SET_SHADOW_STACK_STATUS 75 +#define PR_SHADOW_STACK_ENABLE (1UL << 0) +#endif + +/* We need to use a macro to call prctl because after GCS is enabled, it's not + possible to return from the function which enabled it. This is because the + return address of the calling function isn't on the GCS. */ +#define my_syscall2(num, arg1, arg2) \ + ({ \ + register long _num __asm__("x8") = (num); \ + register long _arg1 __asm__("x0") = (long)(arg1); \ + register long _arg2 __asm__("x1") = (long)(arg2); \ + register long _arg3 __asm__("x2") = 0; \ + register long _arg4 __asm__("x3") = 0; \ + register long _arg5 __asm__("x4") = 0; \ + \ + __asm__ volatile("svc #0\n" \ + : "=r"(_arg1) \ + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ + "r"(_arg5), "r"(_num) \ + : "memory", "cc"); \ + _arg1; \ + }) + +static int __attribute__ ((noinline)) +call2 () +{ + return 42; /* Break call2. */ +} + +static int __attribute__ ((noinline)) +call1 () +{ + return call2 (); /* Break call1. */ +} + +int +main () +{ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + fprintf (stderr, "GCS support not found in AT_HWCAP\n"); + return EXIT_FAILURE; + } + + /* Force shadow stacks on, our tests *should* be fine with or + without libc support and with or without this having ended + up tagged for GCS and enabled by the dynamic linker. We + can't use the libc prctl() function since we can't return + from enabling the stack. Also lock GCS if not already + locked so we can test behaviour when it's locked. */ + unsigned long gcs_mode; + int ret = my_syscall2 (__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to read GCS state: %d\n", ret); + return EXIT_FAILURE; + } + + if (!(gcs_mode & PR_SHADOW_STACK_ENABLE)) + { + gcs_mode = PR_SHADOW_STACK_ENABLE; + ret = my_syscall2 (__NR_prctl, PR_SET_SHADOW_STACK_STATUS, gcs_mode); + if (ret) + { + fprintf (stderr, "Failed to configure GCS: %d\n", ret); + return EXIT_FAILURE; + } + } + + call1 (); /* Break main. */ + + /* Avoid returning, in case libc doesn't understand GCS. */ + exit (EXIT_SUCCESS); +} diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-return.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-return.exp new file mode 100644 index 000000000000..717cc305c25c --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-return.exp @@ -0,0 +1,132 @@ +# Copyright 2025 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 . + +# Test the GDB return command in a program that uses a Guarded Control Stack. +# Based on the return tests in gdb.arch/amd64-shadow-stack-cmds.exp. + +require allow_aarch64_gcs_tests + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return +} + +set main_line [gdb_get_line_number "Break main"] +set call1_line [gdb_get_line_number "Break call1"] +set call2_line [gdb_get_line_number "Break call2"] + +if { ![runto ${main_line}] } { + return +} + +proc restart_and_run_infcall_call2 {} { + global binfile call2_line + clean_restart ${binfile} + if { ![runto_main] } { + return + } + set inside_infcall_str "The program being debugged stopped while in a function called from GDB" + gdb_breakpoint ${call2_line} + gdb_continue_to_breakpoint "Break call2" ".*Break call2.*" + gdb_test "call (int) call2()" \ + "Breakpoint \[0-9\]*, call2.*$inside_infcall_str.*" +} + +with_test_prefix "test inferior call and continue" { + gdb_breakpoint ${call1_line} + gdb_continue_to_breakpoint "Break call1" ".*Break call1.*" + + gdb_test "call (int) call2()" "= 42" + + gdb_continue_to_end +} + +with_test_prefix "test return inside an inferior call" { + restart_and_run_infcall_call2 + + gdb_test "return" "\#0.*call2.*" \ + "Test GCS return inside an inferior call" \ + "Make.*return now\\? \\(y or n\\) " "y" + + gdb_continue_to_end +} + +with_test_prefix "test return 'above' an inferior call" { + restart_and_run_infcall_call2 + + gdb_test "frame 2" "call2 ().*" "move to frame 'above' inferior call" + + gdb_test "return" "\#0.*call1.*" \ + "Test GCS return 'above' an inferior call" \ + "Make.*return now\\? \\(y or n\\) " "y" + + gdb_continue_to_end +} + +clean_restart ${binfile} +if { ![runto ${main_line}] } { + return +} + +# Extract GCS pointer inside main, call1 and call2 function. +gdb_breakpoint ${call1_line} +gdb_breakpoint ${call2_line} +set gcspr_main [get_valueof /x "\$gcspr" 0 "get value of gcspr in main"] +gdb_continue_to_breakpoint "Break call1" ".*Break call1.*" +set gcspr_call1 [get_valueof /x "\$gcspr" 0 "get value of gcspr in call1"] +gdb_continue_to_breakpoint "Break call2" ".*Break call2.*" +set gcspr_call2 [get_valueof /x "\$gcspr" 0 "get value of gcspr in call2"] + +with_test_prefix "test frame level update" { + gdb_test "up" "call1.*" "move to frame 1" + gdb_test "print /x \$gcspr" "= $gcspr_call1" "check gcspr of frame 1" + gdb_test "up" "main.*" "move to frame 2" + gdb_test "print /x \$gcspr" "= $gcspr_main" "check gcspr of frame 2" + gdb_test "frame 0" "call2.*" "move to frame 0" + gdb_test "print /x \$gcspr" "= $gcspr_call2" "check gcspr of frame 0" +} + +with_test_prefix "test return from current frame" { + gdb_test "return (int) 1" "#0.*call1.*" \ + "Test GCS return from current frame" \ + "Make.*return now\\? \\(y or n\\) " "y" + + # Potential GCS violations often only occur after resuming normal + # execution. Therefore, it is important to test normal program + # continuation after testing the return command. + gdb_continue_to_end +} + +clean_restart ${binfile} +if { ![runto_main] } { + return +} + +with_test_prefix "test return from past frame" { + gdb_breakpoint ${call2_line} + gdb_continue_to_breakpoint "Break call2" ".*Break call2.*" + + gdb_test "frame 1" ".*in call1.*" + + gdb_test "return (int) 1" "#0.*main.*" \ + "Test GCS return from past frame" \ + "Make.*return now\\? \\(y or n\\) " "y" + + # Potential GCS violations often only occur after resuming normal + # execution. Therefore, it is important to test normal program + # continuation after testing the return command. + gdb_continue_to_end +} From patchwork Wed Jun 18 05:54:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 897545 Delivered-To: patch@linaro.org Received: by 2002:a5d:5f54:0:b0:3a4:ee3f:8f15 with SMTP id cm20csp137191wrb; Tue, 17 Jun 2025 23:02:57 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVYSf0G1BZVRtI8bVsV5AHS3boj0wxpsiwSBVd9NU83UnN9SXAkcJNTQqAZ5ab4bOLiSkxwIQ==@linaro.org X-Google-Smtp-Source: AGHT+IGRgsx2APTOiKpe5R1wYs3COL9/MWOIAF4pcQk11NTjk56ebKZvPh96QBX4m7k7uFO7ndbv X-Received: by 2002:a05:620a:2983:b0:7d3:8cc5:8a45 with SMTP id af79cd13be357-7d3c6cfef18mr2344742085a.53.1750226577167; Tue, 17 Jun 2025 23:02:57 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750226577; cv=pass; d=google.com; s=arc-20240605; b=dmZI8UUe54yZ2kTMlhBdb/Ig9qnd6A+K1xGG0ofkjrcOCYiM4tKKR+ihxrVhEK1WKh XLOP1za6BuIU/xsnfcZREopl67htOtZWmMRscKkYgbVszJcCB1C4VLnpW03GAAgzI9Vw /GcFiLOteC7qiaQJyhwO4O6w3QbBDUmoLLmkQ8zMT0jvf4Q5VrkOR0or695KDlolLmcq COTrGL+xtFI2zxn4EnP3ro3aHokOV/szgKTquBZqjNcNX1x/t8hftuPqUKFZHOQBP7m/ nnanV1YxYKFAu0kvsFTX+n66z4ADPqrtvuguVbyciBVRk/3Ucm6DKpdj5I2LBCpe7dXY 2cKw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=9Ou6zKEWxaGKcDekUYW1XQ50CLlsTLyBSQ42IYqbBRA=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=J6sgBC3ClW+Z7m9AsYsVRJDm1qEQg9tRI19tPoeHQJpB2MXn9/QVZgwio+dfH+Iv8B EBL2zOC4NhV6soh6QzLtOv6wYkP46CwejbTRpCweHFwRjcHlk0on6NjD2l2uZK41zPJL 67rjo//hWACZ1HsNpS/cCGbMCIUSLMoaUZXuskIZNNv0HEjy6Scwoh10k2PwF5rXzNjT BBJd9qdz71gLHNsc0euxnGjD8zhnkNRzfdDSh1FuaDnIKx92pmh+m3RY9dlkt0T654bR mJaFtI4EqQ4FSS5d25tupZgMsdOygg8Zm66vgKIZ4OYDTGheIXLvpBBJ0/sfjs3EjxUW PO1g==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=RbDj2Ozn; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7d3b8dc7745si1428118685a.21.2025.06.17.23.02.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 23:02:57 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=RbDj2Ozn; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B867838110BC for ; Wed, 18 Jun 2025 06:02:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B867838110BC Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=RbDj2Ozn X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id CBC13382893C for ; Wed, 18 Jun 2025 05:55:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CBC13382893C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CBC13382893C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226117; cv=none; b=QcAfAZNnPTKVrfNswoTGilSdEK3bch8T60NSm21VXasE7aWF/yJw0kLfkmLklqtyETc8C7FTJpkmiU1RfoOhaB/pdKXDdUFpG3E0uBtZ5dc5NdD03j1QE9v6u0nEzH+zUGF4/OwhPIL6jWAoS19g/Bf63DMmmkaFMcUWJhbpnHc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750226117; c=relaxed/simple; bh=7p6P/50MfMkAaeRRDibaZt8eiptXcPEl1Kr1kkiK334=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=pp8wwLkGMCN6F8f0stBM6ebmWiYIqWW6HbSa+KzNPuMulz6vWa+N9XTPT5fe/YE8ItZTZwRZQrJc5Ro3beQCwjxu6g8fkiUpJjZdz1DAwtWSiUziO4JF2FkXYC9Uc3DwsdjCSRYs/8vyfOJemgTef5e3Fa1M40HwiXOdMRz0IyQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CBC13382893C Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-235ef62066eso99308585ad.3 for ; Tue, 17 Jun 2025 22:55:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750226116; x=1750830916; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9Ou6zKEWxaGKcDekUYW1XQ50CLlsTLyBSQ42IYqbBRA=; b=RbDj2OznlbSv1NMeP2E6kSPcVNe8k+wj9KKOrpMMfBbhhiv7JeKAj+151Rv34LcuiC 2m3YfMIdbVGBAqB2MXuaH9po79PnqCWfH9/4qqQsqZEcamoacUeXKLXY1CM2HxDnF7Pn J8DebkOCyHfk3HgtMApYogn2qgSZwiiVMBrNT7ATgCqb+EwX9NBpxzO7ocJU2pUp5u0W N7sm0R8t6MyyVA1hZ2557WsVgnkWZOG5ZFVUSB4H+WYSKYbNtMQbfiVITH1SsA1kQ+Kv gwUlMXo76ed72F9c7ywb6IN/8OiHk5GeW/epllVWkfob2VZxdsRAVO55nOmzyq60kCA+ GWUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750226116; x=1750830916; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9Ou6zKEWxaGKcDekUYW1XQ50CLlsTLyBSQ42IYqbBRA=; b=Gh9Zuk+kfJXtkt678kZ8g7lB8qXGXBiaFnjmACljvdCuOakAwepp8oXBuIza/PBtjM liwR1ju/BhTcxEfcyAZVXngjNILEpRXAOKpr1lMfkRPRXnVH4ZIAtXPmCvaspcPVCzHu MMS8wxWFSifOmqgGeSyt+x2+wHCLX6aq2KSw4cPSH/hA9OkukZM8i/Xsfqat0asnLANR x4DGTg3ljjce/WEK9NBXlAZJtjcUnne7ZhvJ6jI6LTYJ4N2kmZXLOi4xk43B9XoOawqu KsBOYmbsoawj9xFHP0KNPnX5sDc5trMYB3x9yUYdUukyljaMBkKfSrOL11qXEwlNsDyG kyYg== X-Gm-Message-State: AOJu0Yx+WeSvtW02fLIWEfNbMELZ0xUwZiIIxjfUtFX71jvbCCqUc0rL Jboyxbxgvjz/fWtXp0hyzRm/6A83YKLoaCmdIB+jy1UeP4dbMKHEUcKa6J84DuSty39KpulgqQ3 J/8Mt X-Gm-Gg: ASbGnctRRoLiQFr40PPCLos0cdbpwvjWTdnrCtpSr/FkiLLbWUPMo27fZxO0UnpHWjL m/pA5Q8WkACoeBC8JmXH8A0fCFhD889h9wbeMg7XfUjiUpzZqLAtZf4C+PvelsKPbRo4O73ARKb IBNc40kGbu6urY+DOehodxvlRR1oUmd4MIojwc+M3PJ7gnDP9zqpjHkQM5qtuILbytJzIoyKKIV 5h7wkyB3DzWJ4/8Bzl9M5ZkThIJPI3IArR9QYItCe0BJ6u7YZn5x6k8MCAxILbmvpSXB6v2f4Ww GG7BzWs5ZOgY6giATfmClUOF51W72x5aM19N3dlHKXZUJqdiFsoYCq1/jN0yFsrOBHGK X-Received: by 2002:a17:902:c404:b0:235:c9ef:c9e1 with SMTP id d9443c01a7336-2366b337dfbmr246061965ad.5.1750226115826; Tue, 17 Jun 2025 22:55:15 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:ae12:97ab:a9:43c]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-237c57c63efsm2800805ad.172.2025.06.17.22.55.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 22:55:15 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v2 9/9] GDB: doc: Document Linux AArch64 support for Guarded Control Stacks Date: Wed, 18 Jun 2025 02:54:45 -0300 Message-ID: <20250618055445.709416-10-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250618055445.709416-1-thiago.bauermann@linaro.org> References: <20250618055445.709416-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 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~patch=linaro.org@sourceware.org Add NEWS entry and new sections to the "Configuration-Specific Information" and "Standard Target Features" parts of the manual. Reviewed-By: Eli Zaretskii --- gdb/NEWS | 3 ++ gdb/doc/gdb.texinfo | 83 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) I didn't include Eli's Reviewed-by in this version because there were a few additions to the manual since v1. Changes since v1: - Reword 1st paragraph of GCS configuration-specific section to make it clear that the special registers are only available on the Linux kernel (suggested by Luis). - Describe flags in the custom flags type used for the GCSPR in the GCS feature section (suggested by Luis). - Fix NEWS wording from "are now supported" to "is now supported". diff --git a/gdb/NEWS b/gdb/NEWS index 4dcc344b0727..54a61f0e87b3 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -48,6 +48,9 @@ * Add record full support for rv64gc architectures +* Debugging Linux programs that use AArch64 Guarded Control Stacks is now + supported. + * New commands maintenance check psymtabs diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c41aa89a3c48..2bf20ad06230 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -26992,6 +26992,32 @@ information automatically from the core file, and will show one of the above messages depending on whether the synchronous or asynchronous mode is selected. @xref{Memory Tagging}. @xref{Memory}. +@subsubsection AArch64 Guarded Control Stack +@cindex Guarded Control Stack, AArch64 +@cindex GCS, AArch64 + +When @value{GDBN} is debugging the AArch64 architecture, the program is +using the feature Guarded Control Stack (GCS), the operating system kernel +is Linux and it supports GCS, @value{GDBN} will make a couple of special +registers --- @code{gcs_features_enabled} and @code{gcs_features_locked} +--- available through the @code{org.gnu.gdb.aarch64.gcs.linux} feature. +These registers expose some options that can be controlled at runtime and +emulate the @code{prctl} option @code{PR_SET_SHADOW_STACK_STATUS}. For +further information, see the +@uref{https://www.kernel.org/doc/html/latest/arch/arm64/gcs.html,ignored, +documentation} in the Linux kernel. + +Naturally the Guarded Control Stack pointer at EL0 is also available, +as the @code{gcspr} register. + +To aid debugging, @value{GDBN} will note when SIGSEGV signals are generated +as a result of a Guarded Control Stack error: + +@smallexample +Program received signal SIGSEGV, Segmentation fault +Guarded Control Stack error. +@end smallexample + @node x86 @subsection x86 @@ -49505,6 +49531,63 @@ of bytes. Extra registers are allowed in this feature, but they will not affect @value{GDBN}. +@subsubsection AArch64 GCS registers feature + +The @samp{org.gnu.gdb.aarch64.gcs} feature is optional. If present, it +means the target supports Guarded Control Stacks and must contain the +following register: + +@itemize @minus + +@item +@code{gcspr}, which points to the thread's Guarded Control Stack. It is 64 +bits in size and has a type of @samp{data_ptr}. + +@end itemize + +The @samp{org.gnu.gdb.aarch64.gcs.linux} feature is optional. If present, +then the @samp{org.gnu.gdb.aarch64.gcs} feature must also be present. The +@samp{org.gnu.gdb.aarch64.gcs.linux} feature represents facilities provided +by the Linux kernel for GCS support and should contain the following: + +@itemize @minus + +@item +@code{gcs_features_enabled} shows the features currently enabled via the +prctl or ptrace system calls. It is represented as if it were a 64-bit +register with a custom flags type. + +@item +@code{gcs_features_locked} shows the features currently locked via the +prctl or ptrace system calls. It is represented as if it were a 64-bit +register with a custom flags type. + +@end itemize + +The custom flags type allows GDB to print a human-friendly +representation of the contents of @code{gcs_features_enabled} and +@code{gcs_features_locked} and should contain: + +@itemize @minus + +@item +@code{PR_SHADOW_STACK_ENABLE} + +@item +@code{PR_SHADOW_STACK_WRITE} + +@item +@code{PR_SHADOW_STACK_PUSH} + +@end itemize + +For further information, see the +@uref{https://www.kernel.org/doc/html/latest/arch/arm64/gcs.html,ignored, +documentation} in the Linux kernel. + +Extra registers are allowed in these features, but they will not affect +@value{GDBN}. + @node ARC Features @subsection ARC Features @cindex target descriptions, ARC Features