From patchwork Sun Jun 22 01:18:03 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: 899060 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp367599wrm; Sat, 21 Jun 2025 20:53:36 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCV+65HlKMbIV3GwJB0379mh0ArbpPBGv5eyzEQY31hwz9rcgrL26MiLPvOpTBKg+jNoaPYp+g==@linaro.org X-Google-Smtp-Source: AGHT+IFhtYVoU0KSFZ+Zn+SH/PsvLu8OgRnnvjkcIm76c1aMWTRxDeretQWeHD0+xannE1mgF0Ae X-Received: by 2002:a05:620a:2912:b0:7d3:b8eb:b32f with SMTP id af79cd13be357-7d3f9932a32mr1259223885a.37.1750564416248; Sat, 21 Jun 2025 20:53:36 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750564416; cv=pass; d=google.com; s=arc-20240605; b=ckQpgzzLAocqKZYSFhG/X+haNNJa9VoG0KWvKiIjZiZRbSEaPXKIzZkXK0BSSOoXGY GW1C1lcYXQ6MWnynXaclTuENRTkOaP4K1WLmKS5Z9nmYl0lGsftgt3VMhyqOb+Zt2DMj GXRCunV/JaVWWG+7g92Oply/OOOHf2YzjxYNcP6bEsAw1aOWWJTqVcQxMRSwbuoZn0BA gWg1CAcRR/3h7CKBV8xLT2WUTMbn0+GRfXg0HOc8TtMWoUMsfLRzq1XO25LshHB6526o WRE4aOkXQzdXV+oHtdPk85Xo9A52tfPgaTLYGRhaKv9l3LZwL2ea6E3Cdr33lWpvbesb ulFw== 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=qm2oEogMH45aLriN0GnRcPVv74IkK2aTWxPdSLxpt3M=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=am9vUQF6W7HYKi4S63HkG5AHHeqfVLbc1AI7O4XGlI3ItMLEQKPZKiNa33qMDfgvPm jlMb+2vVPtZQKEUwz7Vhu8FzsI8lAR8U2KY2uAtrcp7CrNo8I+UtjA+nbSGC2p1Ezxvv NRgBilrJMsg7qBFHQXiSrqPZzNJOuCcBnXGf6XzpmjWNOYbG91UCFF5/+u7B4HaIceKG ++VDDvol5BenVm2VouztT1p19sUaBFfoFjjC76M8FO0EmfkjhDSFRUz2a8xTkzfai4V7 4ky8VEn46P9Iwf/DqB5cP8Nr6fmoF/bjvZLdxWoQwgpGCfye0SSpdo0szoXX7VeTUwBn yUaA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=OAMIVJX7; 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-7d3f9a18557si498360085a.505.2025.06.21.20.53.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 20:53: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=OAMIVJX7; 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 3EB2E39AA0B2 for ; Sun, 22 Jun 2025 02:33:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3EB2E39AA0B2 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=OAMIVJX7 X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pg1-x52e.google.com (mail-pg1-x52e.google.com [IPv6:2607:f8b0:4864:20::52e]) by sourceware.org (Postfix) with ESMTPS id 2F5C13821770 for ; Sun, 22 Jun 2025 01:18:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2F5C13821770 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 2F5C13821770 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::52e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555098; cv=none; b=flepbUb8HV30zBmNLAJCeFgCWOY+J2Fw+i4HuXwkpZs0aVq3AhXBUluDwhR01EX8TXFgO/k/6Vu/Gf2pqkYlITWsC+hYSbsSruv91Sc+/+8F6bCYLeLcEdtGzfQDj8LE1WzjTA3dapyaLdd+HMvuHTtB+kN07hNY+DsnKU5njRw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555098; c=relaxed/simple; bh=J1bEPWjVL2LI4Va5IjVAVq7aqbad+03Su5PDF61aFu4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=UeUMdR3pWIyNRBD8v5o1lKd7ikaLqpOOqspf7MmYzmZWuceFFgn0B5VzLZE+uXR6peLHUMsAaiw9fp+NhqJ1V2IAbuJWkPIF95Z+mD4jwjerv6Q2zGfJ+I4lGTRsJJEDSK4q0YGwh6A2B7YwjMvZaebl0C+JFKEHWPFBvRUgGNU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2F5C13821770 Received: by mail-pg1-x52e.google.com with SMTP id 41be03b00d2f7-b31bca0a32bso2167507a12.2 for ; Sat, 21 Jun 2025 18:18:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555097; x=1751159897; 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=qm2oEogMH45aLriN0GnRcPVv74IkK2aTWxPdSLxpt3M=; b=OAMIVJX74NnzASetFdvA93fw5ICnjtqLSfNYMJS78ao0cKNhByBwr3vsjvn84MS06P GRBHh6rA8SG23+AzobsDgEFLnPPpMW/5OOpmWb4m1Kmiju5+zZpkyCzw4Y3P9rxn8PUF eWkuY7Tb+kXZOBY8ivjQ4gN8tj+TkaTftNjO5iwupuXjKPpNztj70aKxQktWPK2a/8A1 hNte7W7xPElIuaNPP/mnorRbODHNp63OqletrCLLGsgD9rV5mgPPMns0CTwM+VDHtf8i zmrpjbZ8eGXXbw6kmf8QLdAWhH+SmjbLp7LRxdl9Nj1wysCSIRvJzO39XRBLLqtc1G8R i19Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555097; x=1751159897; 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=qm2oEogMH45aLriN0GnRcPVv74IkK2aTWxPdSLxpt3M=; b=H1JPALcQ2vwHktWw66OpiIiKCw8yeqwf2PSZduUFU5ZLnyzolroAMljUYCjhg3OMr/ 6H/CKo2xEXxsbHm1UO5rLqf0gvE4WZwD/f4IQJdesTSYlPIeHfoYCGp7wo9KSOSCog54 evgs89XzKQW2vsCQMtvCmUTc8LInl0xAlC3FdEvTcCeY+A+SSCGXRCNQ4nWBEnktb63U W6daxWFYM7rgvEJHN/OyefJdq5WFtGbz5KGliuaYuOvk3vXnzM8+0aptKHVeFyaH6sug VrINMmjwspvdbIP9ToxLIjkcc9K884OtvRHfgR6Q/Tp53xxb2x61Uk/0vbAEYmDlQS2Z FU7g== X-Gm-Message-State: AOJu0YyMGRsn9H+vO+R3hahQg1osOGxocuZVJdgYw7ps1dxRUU+hDmhS f4KkRjGAoeaPy63LmbZGuL+1BlkUtBYYhPm3N9hKpV4Rkfz6NxB826RSLK9FAVNWX7S6mYDD3QM svrG6 X-Gm-Gg: ASbGncuYb1Pt/Hqs3z32roISAAijsXPBrBRZLpgrLWimCfZBdcmQeaOWcTyaa+KdOe3 /yCPIt3HLogJ4m5vGNejm7z7OzNOU1HaXlsAKX9QP8pWuIewWJXDhFdnmcQ+z2D1Q6X7nQoxsCI GfECWiIPUjPVVI187woh5oCj7gCiWJsKzCDRSJ5f8LCyJWBp/m53erp6YxHxi5u8cuSTUn+O8Fj ECzYgWQD3LHJ5XNb85EFu7z+caxjb/fVxwnZo3/o16MW965FWPJY3WNiMmMvKZogc2tPd39IvPp /aIXCRdrHkEa34KtIaMaWKB1nIbnFT84COI2UX3mA6G8B9hxvclFpSVZ2uYgiV/n26DIePWSb6J F9WQ+y7w= X-Received: by 2002:a17:90b:4d:b0:311:ff02:3fcc with SMTP id 98e67ed59e1d1-3159d6440b0mr12335425a91.14.1750555097039; Sat, 21 Jun 2025 18:18:17 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-237d8393275sm50782875ad.39.2025.06.21.18.18.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:16 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 1/9] GDB: Linux: Add function linux_address_in_shadow_stack_mem_range Date: Sat, 21 Jun 2025 22:18:03 -0300 Message-ID: <20250622011811.371949-2-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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 --- 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. gdb/linux-tdep.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/linux-tdep.h | 7 +++++++ 2 files changed, 54 insertions(+) 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 Sun Jun 22 01:18:04 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: 899055 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp359413wrm; Sat, 21 Jun 2025 20:11:41 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVXh8kDyTIAGVJh36if7qofE+5gLOdGnFtisq63LIna3f4mjBQ7sPyU32bVs6CrOL63qOT+Lw==@linaro.org X-Google-Smtp-Source: AGHT+IHa5pvpc+b5zq66MpO3i6r113ZtFkMEYmdmPBHooUln05GeHOkvEU2eje4GF+rSGFBHy49L X-Received: by 2002:a05:622a:1826:b0:4a7:14c4:2385 with SMTP id d75a77b69052e-4a77a278f91mr101494131cf.42.1750561900750; Sat, 21 Jun 2025 20:11:40 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750561900; cv=pass; d=google.com; s=arc-20240605; b=kr6bgQGp4um8BHpUPqSkv5BupqRHD9zB1MEkC+oNt1I4dFvetCNMwan8z1cR0nl17m 2rPJBmJCwTGpdNsG7GR61lIWQHQlyX1oCkxlNNE9FNsPpkPUOzn5SKN3OqIcCaqnb1aP BTQYUfdBBhIZPcsv5LTpyZvv0khddU3mesdTeCgb+6X2oQIn/u+fmlbaUvoh12uJwQCs wS0J1Z2bhZatfjAdHzNhMavkHT8t+J1Q3/br1S7sFBbd2H+P8Lt3vSRKCxyArnLxVwsx b7eK3F3s2/BpLX/rc04FPFxUDlZtiYttr3iFyQHWu2TEvbC6AvK0eSxmvgyXe0QseM8a BdfQ== 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=heJraxPPQcX8gQPtjSGrKEPiK7ZZx0Qs98Fe1wvX9jI=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=cCjnQ3g9a7Lk2BPFqRWDSJsBTIwxvmAP7jREu1r/3EK5KU5J1ur+L2pxlkfGVnC1G5 lf4jiqt4rSd4gUwfX7VxEPBh9T+E+OGazmHOhNJDkRtV5m+6mRaQK52rr/xum4RLarSw WtEMi8itWVE2gYdQph+UGOvcb2UiC+RsPmi745RbAzESp8bi1xdSCSBVvRiip5LiOTQ6 JTUHZQLnMBlP4OKD/yc3KibDLrId4P2QvjGzCxj8ps7+O//Kg2+FWCnXf55I3wGzgQP1 Qm5nRcy/pNIMLrQaqp1g1JV4GiUofrULIizwQt2o/BEIvunzp0/JgjOsvEpBeJqO5wGo TWVQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JBHYVL5J; 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-4a7807bc452si39205141cf.265.2025.06.21.20.11.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 20:11: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=JBHYVL5J; 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 C040C39A57EC for ; Sun, 22 Jun 2025 02:33:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C040C39A57EC 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=JBHYVL5J X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by sourceware.org (Postfix) with ESMTPS id DE30B3820433 for ; Sun, 22 Jun 2025 01:18:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DE30B3820433 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 DE30B3820433 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::630 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555101; cv=none; b=Ab8fDAdbO6VFdVh4hAK7QJHesJx8GD2jSkSI4MQfQVqWT8nV7sGGXa3wTaBxHDuZa+patOXc703jf504OTnqXHty9E1RwQhYzE/nkDdx8azF0lvhyso6qinaCMPAGDWnmsw3pRh5ygYmC3MobaAUqRHWEQN9zlOmQ4KYIZVEoKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555101; c=relaxed/simple; bh=VxKAbPKnlVNZotmMZTer472JCvUF8Vm/7xjEKWtRM7M=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Q1DFCWu5sKhMHu6Ysn5PUCfp1gZrsg3sw3OsfBt/6qwasLAoGr8N2GzeycZifnOgeMIOMwZYmXKYBl6fIH5w7q9BdQ+3aeciF+F6ZAoWf3NmLBo5nhQKMAqsmij+7tQ8z8CHuAkTzQ+oLzB7LQh62lna4kH4/ZYvot2iPa1fu0M= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DE30B3820433 Received: by mail-pl1-x630.google.com with SMTP id d9443c01a7336-234d366e5f2so40664625ad.1 for ; Sat, 21 Jun 2025 18:18:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555100; x=1751159900; 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=heJraxPPQcX8gQPtjSGrKEPiK7ZZx0Qs98Fe1wvX9jI=; b=JBHYVL5JjU14pt8lo1rJs7M2WDqkR9QJOsrUGP4Qiqf7WXTHlxrKzB6Y+TruilGeqD fXL2SiRhuVFkUKYRvrNlmq0wIymdrYsMnVrlUQ2of66J+xBFE3xaa7jGTeQi2LRjpAnZ 4LJP0X2CwsskYgXJwYHnQA2hvE9GHWPC/nMy7YOtEh4VG3PN6ZAq4ssqpIil8AlLsuY1 YuEpsRrY1AM1j0c71o7rRLA7e9wOjFO4ffDStV4J7ZixaG5gv49KPU77z3F5w4Q4KyLC yorkzE/p+RllGVloNlBnawPo1scCZK6IGy4S1Ck4wzqGk6ox1t818ozz2nLpKIpuMORX fqHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555100; x=1751159900; 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=heJraxPPQcX8gQPtjSGrKEPiK7ZZx0Qs98Fe1wvX9jI=; b=SPCSDwjbqi5DiuQ22w7WVPrXsB8LQi3Chmh2+eUoiIojmeupxrLE7iInIptgkidDZ2 qXgO7B7EP8KoymCuX4rHF+TvigWUH+CeU5RpMmqstS5SLZ0D6XyA5PR+Zuva8KCXabwg PlmXyIDvgPbgz0g/eMEr4udeVlPw4R3akRs4tTObKzsbAemZJng2qqSe8YsZQrct9Ixd UexA1moJ9BPxk0kmYJM6uCCzkEwFV5Xmn3enEUeFRJdnXU8xbN3wk8D9aj9yDCCrfMBR uC9voN8ikmR5cnnfGRqMEC+tFnJiZ2KXYnHAIwOzkEXTc3HPbkSOcPMDdsVf6M1jGkVW mICg== X-Gm-Message-State: AOJu0YxIYGIqNImAblNgzPUXuzA263d50YPDMbhtqw0Lbgkg2R9Gl0dY T/DQNgxBR9ETMsyBzZHs8OMuWAnIfK5yWBzAplleGDs4O3VA8eMnDRpcAGEglZ/AqfvRw2xrV00 bt9/O X-Gm-Gg: ASbGncvzFRpLdMQyouV4Zg9sQbtI9WsIvA7J9jJOCMz96BvuxCXyM1do7c+nV97jon7 FswM6n0yEAIsJV3Bf8dFiwUS+TDZbtglFUVXPXC4c1PIzt5Fv5GadjDf4u9FIfZkoUGzQvZ22Uj ix9fwd6S9rRUzw9Rn6fRAYcz87ViK96Nt6WQtm5h1nfiKnKvULncDu8ukMstztp0zD25K6T9D/J DKmGMjZPezPN6cj/HsfexXSp7F6WpboKBS/3ixOK0GpJqqPsJUPi0XKqrcG4Z0nX+WY9mvCqovo rQ7rXRRx6CHJmmtctfT30hpQKAvBBgYfPAJE/O4en3GPeCG4vYz3Yo7tgX9WiRW4adr+AuQ6 X-Received: by 2002:a17:903:40ca:b0:235:f4f7:a633 with SMTP id d9443c01a7336-237d9917e38mr126995155ad.28.1750555099739; Sat, 21 Jun 2025 18:18:19 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-237d83cddb0sm50055265ad.58.2025.06.21.18.18.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:19 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 2/9] gdb, gdbarch: Enable inferior calls for shadow stack support. Date: Sat, 21 Jun 2025 22:18:04 -0300 Message-ID: <20250622011811.371949-3-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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 --- 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/ gdb/gdbarch-gen.c | 32 ++++++++++++++++++++++++++++++++ gdb/gdbarch-gen.h | 14 ++++++++++++++ gdb/gdbarch_components.py | 16 ++++++++++++++++ gdb/infcall.c | 14 ++++++++++---- 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c index 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 Sun Jun 22 01:18:05 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: 899061 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp367710wrm; Sat, 21 Jun 2025 20:54:05 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWpofuJy5+Y7E3k8hufNShoI32v0YOcXcpZ/lIuA0uhc334HbV7I52hFGaFlBiWcb459Fa/Hw==@linaro.org X-Google-Smtp-Source: AGHT+IGVFkkcunWwzBSyApMcv7yRyBdjlFbBPed/eEn4NtlKPe88664UtL7InDbNbr/L6LSax9sb X-Received: by 2002:a05:620a:1994:b0:7d2:2a6:2dec with SMTP id af79cd13be357-7d3f9932beemr1377054685a.30.1750564445322; Sat, 21 Jun 2025 20:54:05 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750564445; cv=pass; d=google.com; s=arc-20240605; b=ENe534LQkkROMyreKs359bdxrCyDwYIvcqal82A6lchNc+INHvX2rBv+91mxkFjg+a pS/FXLgfob7PJjay6ACPGmxw6y6uGTBFw9iRveousKntYdOZj7qs9TZQ00urBDSuQcXK bJ23FmpH+AMrIoSs1hjbJ+o1xEhcSFJJCegFSSdaXoKXTEiwqrEysgN+flWrivtNlIRK EHTbgLOsk4HsV26FnH1pr6u+JwgOpFdT11Agd48f6byn15XUNr+GTxTKzjW1u4cRXQA8 PfjHH5EbjAGA7Y5AOJJRpNrUBvn99FnhyHPcbXwj/+mTKQVOW8KPEvXaCqkJj0DmwbCO DYfw== 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=KBjxxgkElutIc0XXJ4sdD+BBvNnjRy8jf/25rIPZMyk=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=JPQt+bLitLOztQ5hokzZQJmfafzJzRT/Q10raWwZtT7pAoKPk4IV3ixSHCnaGS7UgR 4CQe1DCr0krOO8xdVGsSvl2ZXS0p77gjNAI3VQ7XDCdiGgzAFgsEI37LcR+k2eheYcJn pAP3VpBl7O92GfRaJwa5I9DPBiBLjCInYxJmh1/At3qUFoHSVEe7GIb4cunZnkLQdi3+ oworgJd4FnpJno01YFmcVHggaTaO8KEh4TNGlpdcrVRxLR/QGbJXyeAk0VybNw7PzP2A t4i2Vsgoby5BevGf8DjRR24KnOKP+50qWI9FNJd8+C4H1UCkD4AucTCGWEsIeYcwAwlK CeqA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="fwHGX/Dd"; 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-7d3f99aa939si488880585a.155.2025.06.21.20.54.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 20:54:05 -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="fwHGX/Dd"; 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 AA91639AB4D1 for ; Sun, 22 Jun 2025 02:34:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AA91639AB4D1 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=fwHGX/Dd X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by sourceware.org (Postfix) with ESMTPS id 2875F389377B for ; Sun, 22 Jun 2025 01:18:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2875F389377B 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 2875F389377B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1034 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555104; cv=none; b=LRYZOgDhAgypetJtjJ3rKMwQKEChhjYBSfLkVIwZyDYDU1TPdLFMvocleQIP3WochUjjoULKjMxtKJh9qUi88vIg8J4tsWZwEE3TgKTMd9uuaKe6+8bTzQcuL2AP1pfnvtK/CfCaZZx9cJKFLDVxf+XXt0Ekc1PJ4tTewCiWxI4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555104; c=relaxed/simple; bh=K7noaGLbw7u34zjpiBvUFPTPbrQHhrJb6WTEAAvYL1k=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=paq1ItN2/JssaUBYdvDS0Zvrk4FqoVP7mWMnoXPr/3gnOew5agatJyqlkrBFMH5kNbRua0B0mSsqwATTKnE0sphmyQr2PUvPqwgDkbuAaNW+i+0I+X/jxGrCF782rJ78+ZNOLybssqGJ+VqUclMbe+QzGJNQrTx/099zVDp6d18= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2875F389377B Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-31223a4cddeso2199526a91.1 for ; Sat, 21 Jun 2025 18:18:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555103; x=1751159903; 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=KBjxxgkElutIc0XXJ4sdD+BBvNnjRy8jf/25rIPZMyk=; b=fwHGX/DdDjJKN4JATqDlNpECoV5S0NqgOhSjGS8ez9pnqdgaSS6ZO8K9Bbs5VHRwiX sM7TwqYCSPgWcZ6M/iIXEkxL0aurpjAD0jQRivVTtdG2cEPVK7gOcJThoLJA3G+elmHS I0SK/HOI4A8vf7UsiKpXYvfi8eWU/7pl1KRZTRrmxIl2oL6xZQA1WwnvDoWtijk3CUoE G/w8li6TpTs+aWRvrIAFH/kYrb6UqWe62iCf5BmxqkoyMEssW06GNIIs5Tc6YhHqz/7p LdRZnjJTaSNkSXMx/9AvNoK21/BVuVOb2xgGTPnzM7EHmlVoD7JtnH+NHYizPPFe7dSE fSPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555103; x=1751159903; 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=KBjxxgkElutIc0XXJ4sdD+BBvNnjRy8jf/25rIPZMyk=; b=N+Oiibvkwz9siVefcMJaxMM/ozNAVtbc8bqL87aApZw92UbxukrGoZB8KjzNZpk4av 9wZVd4AXJZXQxK1ABhzG5cYsRfX/sJGYTYLf5JT7FXVu6ObEDU5hnxfK+cm0V0c3lqgW Naiod/4UN1N2jt3kgBs617SoRViEqZmC22LSHAa1oY9NdT7X067q4KFf1CKDdov5UrLk EMpPFRdc1cFafA9KGRNC8qZMEsykNFqJkuyKU00eNfA2oFkrNNbLyVqaCyXrw1psaji2 Pe1nR8zV/fZ2KxJt1MVmOjgAEPtxBGCEfEH01rG+xph0WtH50/mUZgbTk72HmNDKCYMo oDyA== X-Gm-Message-State: AOJu0Ywx3RZuM2QHHG4R+pXS4BwuCHBuJXz2kJc6LknxuJ3q8o80cWbF bbcNB2P285At5jkE4PR+yTKD9VWUGi4SpTT5Re3eEFjNMogUVGjqerqYdJ+D8HPaZoQLqNkRPl9 h5s89 X-Gm-Gg: ASbGncvUAHcQrYEQ07KTB+GXCAYlVDF8ZGuPs6V+Pq0NRKCyyYAb/iBhGcKylKGVQ7s 4Ek6+UhrD6iY2qvPPUTaI+byoH83KhoRkyX8a2BaAcgc8L21772zcsPjFlth6NH7B5SDusG62nK h10ZW0TmT4zbaI0j2euSf5NVskcvWskH3L31z71mTSAQF7CaKM2nUVGuGxCiRMbY0mcIU6rzqm0 J0IpXZV5tjxmMXJlXLqmTywANlF/oCAfM05jusYNzxyfhDE3WMumiWNqWNznVvhcSIF4etRU1DI RArZbWQfOMJZuGyqfnOHnCWg+DCOz7eC8iuAKUu52zOXnGpdDuEGbJ9yy11jp5LgrAeo4wOE X-Received: by 2002:a17:90b:3cc5:b0:312:e9d:3ff2 with SMTP id 98e67ed59e1d1-3159d626574mr13455271a91.7.1750555103063; Sat, 21 Jun 2025 18:18:23 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3159df812bdsm5301832a91.12.2025.06.21.18.18.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:22 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 3/9] gdb, gdbarch: Introduce gdbarch method to get the shadow stack pointer. Date: Sat, 21 Jun 2025 22:18:05 -0300 Message-ID: <20250622011811.371949-4-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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 --- 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/ 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(+) 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 Sun Jun 22 01:18:06 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: 899063 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp370196wrm; Sat, 21 Jun 2025 21:05:45 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWNUSwb2IqkdCEGfNBp0xZ0+ymCyDEYFrIS47ONC1YutbgQpm5pVbrzsY7fpj0ucXLfng23dg==@linaro.org X-Google-Smtp-Source: AGHT+IH1qwha/YOfrJS6Hs3NWkMkqHYa9v+zCgpizmE8UNaiswz9VSquJ3OS8KXYjqHxIMcwoe+b X-Received: by 2002:a05:6214:cc1:b0:6fb:f00:48a9 with SMTP id 6a1803df08f44-6fd0a4df6c6mr154932106d6.19.1750565145738; Sat, 21 Jun 2025 21:05:45 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750565145; cv=pass; d=google.com; s=arc-20240605; b=MRFYLeezg0AYCjPp4ix4jCTO7/PDnXBSv5CPgh7c5/0zVS7D7LfYbeQ62vDVbyrLjc HcF9fgeakzefdb8fdOzqh3TBXwxrUrxFAeyuJ7BK3Wj8vTfUEN60eW00tXdQp7xMdyKo F1U7P6VYkag2d81EesVVecwdCW33E+OLTJHZDDrSYCsjOIRX55uF2EIQLHQspGbjnD/Y s5uU/96FfDHyxYAGmWKEq9B8PPzSlAP1YbzM4okEuVYRsrQkI/2zqpuLMttltylolfkK f5z1C7sbz5gVnhsZbBYthPCVXtlkv80/wZ/J7+/IR7FwUlLPdoo/o6gNWbqO9HAan8be 9RGw== 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=vOPhD0D/bMLgPjWIKIuVayCsZl9PqcdurBKbh8k74Vw=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=QokGbHrHFtFOUrnhqZpQc6RE8sE1V2U/wJW7LVXzodk5vaqtYqIsciNITapy29dV/q uJ16qZlqh+uTGNwAbky1ire9nmwlzKy0GPsTkWPOBo11pWlG/e1jIqnzMpHq8XDezJlP Sh/ZKEFrjyY5k0yR7/qEXdh3ugOAspDajCWWSh+VHp0GyvS5Ljbxd0jWPMz27AsN/cI2 lj56+4SdrX3wcuMe9vWhKksl504rdtaCK2IEjRSr44glTLyBA9H41SczNLnFosKCayUN t7eWRb9T1xN9D5LAWmxbXc2uRR+haXlmpNun7b8sQzK68v+v4L3H2tStlaYZjtoO/Gyw ZwGA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dz8Jg0XP; 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-6fd09530fcfsi59212206d6.231.2025.06.21.21.05.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 21:05:45 -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=dz8Jg0XP; 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 6109038D3D61 for ; Sun, 22 Jun 2025 02:59:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6109038D3D61 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=dz8Jg0XP X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by sourceware.org (Postfix) with ESMTPS id CBBE5381ACC9 for ; Sun, 22 Jun 2025 01:18:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CBBE5381ACC9 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 CBBE5381ACC9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::432 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555107; cv=none; b=QEcfcYIAJVfNd/xTD/N3FQPivrwjse6jRCkZqCSepaEdnk6AuBoLh0W+t0BwAbpfTGU+aSuyZv9TcCHPbEjQjiG00RIJ46cbYyYuXGMCotCJ3ZMAIdFcHMj/V9P3HYqkUU/n0QLwTE5Akksiox2L+3SrfrbYH2Jjms0caegPv/4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555107; c=relaxed/simple; bh=7Slopi9RHSZgBAuipO+2uNyuokpnU7jNrcmapSQtUz4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=i/HRD8gjBJsgddJVieQrzmmA8Gb2y6HZn41Wp/ZSq16thI5U72fv87vCfG/BAu4IHhf3gpLb2Itf5V7Nxy4l2uyTQw1rBqFQmpCjibisluJMZjSXc7SwaYzoY9IZ+tpve5h44vBnqlNzc5D3rDJM+5y3Gh88jxgFUqr/zHtvqcI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CBBE5381ACC9 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-749068b9b63so1407744b3a.0 for ; Sat, 21 Jun 2025 18:18:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555106; x=1751159906; 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=vOPhD0D/bMLgPjWIKIuVayCsZl9PqcdurBKbh8k74Vw=; b=dz8Jg0XPh38zNyZ+xw1TKtjEtlN82b5gLpt0Kow34UEqM4yqO3XD/KNqBYih8Rwa6a YgX9l7kdAS1hHYq6fdTYZIRSDXBb2avRtalK4wGxzQ+SDIuV3O84F4hAVaz+4X08l6eJ lhtRKEJCQbtbhu9+a9VVE5NhWQE1QtGCVpRfshEMmUtI1+J0jkldAvQ+8JcW+7HWP0Cf dmLgEEWCoXxCy3mGoJtGGg7PsSBTi84BI5s/jaovvUTd7X+igVO2WvE0+JejtLUA/l3d RypA/BIfbWleSqedUzSVS3r1mMtFl8D9RNJcmb9CVqnN3iDX+BoB4fMliXIjEdJCwRVc PjDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555106; x=1751159906; 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=vOPhD0D/bMLgPjWIKIuVayCsZl9PqcdurBKbh8k74Vw=; b=ecn4FNXzuxnK7qSmRZhydsdgesWMRrBEraYY5iltZRSkoScpnvSKV5+rs4DKJdWY95 cLQUORSURaudxPoQWQKTNJttfLDFSY/tHj3jhjljPITNvQCgYcAtBio34gd9TFFHfkLL J8lJePSo+qPXrsprFGkHS06u9DAwK+JzC0L7fC/l+wjKU1xoCraeYesYWgcJsj+o2FYB Fl9QUl3Af13xx2sZSVcM94LxH/PRjzXfENBoW/VVfkUcR2ytKI678z+xct6vMaNKZuf+ LYemg4BdxWEeE8ll/dpNTeIRksAVd/lZParVj4gyZIncQSFD3NTJf1X6+QS4J9E9CDvI 3UXg== X-Gm-Message-State: AOJu0YxYGn6oK7ebxMS3jm4Wa1shl1xDx7NFNky1DwM3PAdnbNsC7y9n rGcHLB/lOSrZVoTHcKp+tCFiFOxwiJeDMs4WWqvdPPp2fPECKZDk+hYeC4JZLjKw38oujhX7rVz f1ByM X-Gm-Gg: ASbGncvm25fxfHoRoczmMsVAe333KktMIMsBFO2YZ8bQrGvL4URdHUJUIPg6qoqkU8F tZP5nojDcvz7SjfG+RsfK8AEm/0kNPcE0AUz1jdAOkmdW1vci9kaU/FMNp+tkv98/fw9bPaPTvO UOfnMDXYUPlUWIwD8RgPIjfGv6y529oKsCJyyHk+NZ+VdpF9q5TCRjSjqBOn44CQjiQN6VAFSxU WSa36UOLklBl0nA0GtLwihtzqqjs+u8W6L5ry8SiVXv0OA7Mq+9X9qKR9SKnzlJUQS8YopcS915 0dRhbk5B+j1hSIQQ1ls6kVGORo2rWY+VapKrWPwWQN9wGrTolRVLhGm1Jk7/ynkhUnYPH9bY X-Received: by 2002:a05:6a00:2d08:b0:742:3fe0:8289 with SMTP id d2e1a72fcca58-7490d6f23f2mr11575883b3a.20.1750555105825; Sat, 21 Jun 2025 18:18:25 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7490a49efbcsm5154079b3a.56.2025.06.21.18.18.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:25 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 4/9] bfd/aarch64-linux: Support reading and writing the GCS core file note Date: Sat, 21 Jun 2025 22:18:06 -0300 Message-ID: <20250622011811.371949-5-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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 --- No change from v1 and from what was posted to the Binutils mailing list. bfd/elf.c | 31 +++++++++++++++++++++++++++++++ include/elf/common.h | 3 +++ 2 files changed, 34 insertions(+) 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 Sun Jun 22 01:18:07 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: 899062 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp367791wrm; Sat, 21 Jun 2025 20:54:39 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCX8JV+pPuHkjGbI+U8cXz2icD7l8Frcegt4KpryU3QomjYC/N03yds6E4e+tRoMNaBamfuYow==@linaro.org X-Google-Smtp-Source: AGHT+IHbteN8SrKZa1Lj0fOBQsvc2NfceLZVDfdMcJIWgwlrh9eTAe8ShZMpfMY2CefwIZcaFr9a X-Received: by 2002:a05:622a:120b:b0:4a7:a8a:efd with SMTP id d75a77b69052e-4a77a27afbamr127794891cf.44.1750564478737; Sat, 21 Jun 2025 20:54:38 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750564478; cv=pass; d=google.com; s=arc-20240605; b=Vz2V3Ao5byLx9To0qILOJyWCb1xv8wd+Y8+IC8I5r4OtDx/Sf6wXUcXOvrDGrVt3e3 BOcHFJ76qcS+wErrMIpymrqeElA7g5ohF6CJX3Lm9eSz4pbWrM7GE9A5S9wSYUrzUjgo bFARbzVpN6c1Zr4vICvHQPGG94/Oweou8qKszBwLA1h79+mAdT/1f5DuvYw3bX2ixGjI 5UhAvaBXpE1kxLMLSRciVlrw294QBM0ZYmalCdQgPlMMDRLj6mrA4VhRCl0zvo0ZEWky 7enFF81So4jAkgEjpCkFoLyS64AfM1u2g1Qg8KNgMkrqdqH1V4EfyC3SxcRJvULegPf5 M/Ng== 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=dt4x1XRbSkfj6VM0jRQ/Z6KCzQ73SHBmjAiWZHxOm04=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=KS10Vo2vHI4ny853FOxdmTLGJkkh78t/ijAonWxADnI7gZE7oaDd8oX8KGF5SWVeoB BzOlBIGuu3DcFhN4IN1wa2jmBfAerkom8DDFZ8ncGZjHAJupdCGSYvox392OxdjhRF6g 6q5NsRSmxYlBv1sfb6ZaYmiRtrV87ZkgfyLXZyE4diW+d7PKaeh1GPMLXcOEO8NvB7pZ pZ0RfWw4hHrwv/9eDmhafHKUt2Ef5kvWu/uNz9GaYSDcbH6n08CBpOTLwmhkalFJywBh XUDz+Sl6rd9SYCsL7TRGfDZLBAzctMlnMOYEopO0NlMV63lAn/sE3yQ+PRjHoYGGd8hT BZnQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="BQP4k2/P"; 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-4a779d4ea5dsi52260941cf.40.2025.06.21.20.54.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 20:54:38 -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="BQP4k2/P"; 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 A891B3982035 for ; Sun, 22 Jun 2025 02:35:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A891B3982035 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=BQP4k2/P X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by sourceware.org (Postfix) with ESMTPS id E974E3818ED4 for ; Sun, 22 Jun 2025 01:18:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E974E3818ED4 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 E974E3818ED4 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1034 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555111; cv=none; b=sVjr7Yc6AioIXPZUbuua4eoet5c/PBNPbmqW0GOGvyg4iCe8KT/pdPNgn5pzgiMqvM38sSKw0xGLW2RgzdJ6zCrvyudEXxTEdwkzLNS+ON9lVldGDqnL7Mb/XLJ5cxIQlBVzj280MFoLNtx/XZkMP0UR8lSkV1rSJ9MEcXu4/jQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555111; c=relaxed/simple; bh=kV7LCKwGOZIIkJOcrm36cNHoCtvFt5qWgiW28BHRdWQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=MxdiBU6jAHceSbTcfnBlB4KrnQyBL2vjNJXOmM7UWcK2Z+H6Sb+84RaGDF3EHlISVe4zX9jP86x633Of0kNthYWqxur4Rzke5eK8qkSlkMvN7GTPqU2nnfqOZzjzwGMjoMf88SpCkvdaaatGEGLL26iuCdHT4bD1HfsPlhY7pFI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E974E3818ED4 Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-3138d31e40aso2860095a91.1 for ; Sat, 21 Jun 2025 18:18:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555110; x=1751159910; 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=dt4x1XRbSkfj6VM0jRQ/Z6KCzQ73SHBmjAiWZHxOm04=; b=BQP4k2/P7oUld6kpOlmSylwOZXBnsO4rDGLF1cdbdZ+jHHSZFP4i57wzb80dxYYOg+ e/e0T0WhEVEVoOqfJmKFJ8uY+wmucBvcmp8SRpQTsUoJEIMETUqRTufsZ1xDXgGPLmyu GwtxOBqmy7LP+oY+qxCoAfJhZbWoKJVIvCV2Kds5x83JGoaQ1oPpHJ3iK+vXXPwpAEQO ZcksCrxjjraLx37n5j+mBU/1AZgyIZaCpPjveycQXxJBxZMacY/Mv50QmT0H3FYDRsTE +Ztb0KyBOs90kCGWqYN8p5z/bxvae8T8QENOFfj189OkUe8onPH0KpyeXwcde/q3F4Bw Vnrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555110; x=1751159910; 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=dt4x1XRbSkfj6VM0jRQ/Z6KCzQ73SHBmjAiWZHxOm04=; b=Jqqtq04xUk30JCRwkk7SETLvS+s16q6AWx2Y8Km2GX3LjObvOI3hTU6XWSeuSTE0HG 3/96Fv2DKhwGZCNMzuX9YAuY2c4l0ycUT5g3JgrpLA7HgkRtH2mKyo/pFookiwihcq52 JMLDxTbSOrAK9ebMopKOVf4I7py8f4xWsAhGZoT3Ybn9V180ukvixw9QHcpWYRFf9fZ7 VO+2nirUtolgyYdhYA+NUrS7+h/9USCqpl8pYPXxrNZ3DtgeIB3873mQ2DBZ6cyU50/O kaJGcjchsCdafdwnJBCXfDtr0tC+ZMa3ZsWk6uGp65NS+e2g+nbPKI2oWyerwRmQ8kPs md3Q== X-Gm-Message-State: AOJu0YwYvCNYO+IUUEAZY3c0MpYDX7GvpWLUOHI3+Oj+PBvQi3+5PR/z vrY18AcLM699+ph1Yr1lH5lZSrO6mzTy0O+uVW47knyT/K6F6EJWcDWc+Sh2XT5D75uzOl7Lg7Y hJkWj X-Gm-Gg: ASbGncuHxktkDZLjmEU3hWSTwHZ2gajLCtncL23Eh+5FWPVhGOZ9CKAL2A1eBisnHMa n+c1TgRJsZRUmefOIsUfHiE6x0ltisKo3YA0M+YxunCbA3LTokKxMglQ5vY/g/rHvmBEJ6gvKzw g/Mfuw7py3UorxIyMKEpUz7Zp3utL48+Ds/i8K5kzWdi95G0g4ifY+6QGXRhMS+BorkJ+hGM76C RdzXsWpv1D9h8vjKD7RVTxRw2Yei3kEM/IJSTKowyjEenf2EOMGVmVBVCu0UrRwwYNCtH3wvl3Q 3BCkJOknFNspvjzYeTk9xjP616sUFn8MrDzXNcOHlfQDpJGf7oCm/Pam0cvHFXvx4/hqI3Za X-Received: by 2002:a17:90b:2248:b0:311:eb85:96ea with SMTP id 98e67ed59e1d1-3159d63c82amr13765356a91.9.1750555109375; Sat, 21 Jun 2025 18:18:29 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3158a318733sm7268383a91.38.2025.06.21.18.18.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:28 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 5/9] GDB, gdbserver: aarch64-linux: Initial Guarded Control Stack support Date: Sat, 21 Jun 2025 22:18:07 -0300 Message-ID: <20250622011811.371949-6-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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. If for some reason a target description contains the org.gnu.gdb.aarch64.gcs feature but not the org.gnu.gdb.aarch64.gcs.linux feature then GCS support is disabled and GDB continues the debugging session. Features that need GCS support (for example, calling inferior functions) will not work and the inferior will get a segmentation fault signal instead. There's a testcase for this scenario but it only checks the native debugging case, even though in practice this problem would only occur in remote debugging with a broken stub or gdbserver. I tested manually with a gdbserver hacked to send a broken target description and it worked as described. Testcases gdb.arch/aarch64-gcs.exp, gdb.arch/aarch64-gcs-core.exp and gdb.arch/aarch64-gcs-wrong-tdesc.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. --- Changes since v2: - Change aarch64_linux_init_abi to warn if tdep->has_gcs () but !tdep->has_gcs_linux () and disable GCS for the debugging session (suggested by Luis). - Add gdb.arch/aarch64-gcs-wrong-tdesc.exp to test the scenario above. 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). gdb/aarch64-linux-nat.c | 79 ++++++++ gdb/aarch64-linux-tdep.c | 30 ++++ 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 +++++++++++ .../aarch64-gcs-tdesc-without-linux.xml | 65 +++++++ .../gdb.arch/aarch64-gcs-wrong-tdesc.c | 26 +++ .../gdb.arch/aarch64-gcs-wrong-tdesc.exp | 48 +++++ 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 +++++ 21 files changed, 1081 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-tdesc-without-linux.xml create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs.exp 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..fa5b265014a4 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,13 @@ 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 ()) + { + warning (_("Incomplete GCS support in the target: missing Linux part." + " GCS feature disabled.")); + tdep->gcs_reg_base = -1; + } + 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-tdesc-without-linux.xml b/gdb/testsuite/gdb.arch/aarch64-gcs-tdesc-without-linux.xml new file mode 100644 index 000000000000..056ab58b82a7 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-tdesc-without-linux.xml @@ -0,0 +1,65 @@ + + + + aarch64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c new file mode 100644 index 000000000000..10cf749f3e66 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.c @@ -0,0 +1,26 @@ +/* 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 + +int +main (void) +{ + printf ("Hello, world!\n"); + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp new file mode 100644 index 000000000000..f0508cdc247a --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-gcs-wrong-tdesc.exp @@ -0,0 +1,48 @@ +# 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 that GDB complains when given a target description with the GCS feature +# but not the GCS Linux feature. + +require allow_aarch64_gcs_tests + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return +} + +set xml_path "${srcdir}/${subdir}/aarch64-gcs-tdesc-without-linux.xml" + +gdb_test "set tdesc filename ${xml_path}" \ + "warning: Incomplete GCS support in the target: missing Linux part. GCS feature disabled." \ + "warn about incomplete GCS support" + +# We can't test a debugging session on a remote target because with the +# wrong tdesc, GDB expects a g packet reply with the wrong size. +if {[gdb_protocol_is_remote]} { + return +} + +if ![runto_main] { + return +} + +gdb_test "print \$gcspr" " = " "GCSPR is unavailable" + +# Now check that we can continue the debugging session normally. +gdb_test "next" + +gdb_continue_to_end 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 Sun Jun 22 01:18:08 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: 899056 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp362482wrm; Sat, 21 Jun 2025 20:26:28 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCU1wWhmB14oNtVLuzLBSFsnlVZ+I/RoZSQfwsX2InWkMvWfGJfuN8nNuombyHYhFWUg2Z405Q==@linaro.org X-Google-Smtp-Source: AGHT+IHLqvTJuya9v+hj20H87MGNZSF6aeol+YIXbN9Qu7YxS9sDEg8UDhqzL+9SyLqpigNFR+iC X-Received: by 2002:a05:622a:2cd:b0:4a5:911d:57c8 with SMTP id d75a77b69052e-4a77a1f1abemr126572261cf.1.1750562788450; Sat, 21 Jun 2025 20:26:28 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750562788; cv=pass; d=google.com; s=arc-20240605; b=TfPyawzNvrlNJZBDwlJA2GOLQin3oRcyuO0IlXtAnHuk6IReZA1tPQuTBEJmp4idSn HCkKeFAuMSg7jLEEsFA+jby025SqLJzg9TnqIrmzBNDmfspjnZt9MNpqpCo3QHLCPize NS7vJ1abg/LuLH0Av4QdOv5/YZWt0RbqnZ5XxSrTm65UEXr8gSqnIJkwtwcSnRC1Sn1z 2/RHnQFBt2VprN/d5nZDEdeCTwFU87XcBkV4qHrUmrsbYzkoIsnrQ8nPxHV2qNsHz3yj b9eqdSqB/o/4u9IoPmH42YRoLHZujD/H5DalfIqtO79fIKN2JBCz6KhdJX7JXRPMSfEZ 9R/w== 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=tGXF1zM4NpSixHEzX8A2BznNtrCYoyrOnu5IybnXb3U=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=C5VO/H4/IlJGohniwN7NHVBkHNW6hZyNjF3R4W8ZdQgYxvPcZ+Prjp38B16FCEg99h jyLL7YKydTYjZg3aYgR2fLO9iXzQcCFUktdPCK9iB18/ZWbGG8LRzB76kjjMHsPRVUGo 4Jwgqd1u3J/s2N3VjrZePFgP3a9YVH7dM8n40dQbsj1uWVmGII8nMtaOZsImp46nVEjQ ga0pXwUuA9C/BJvwWB9vyqzv6L3/MEvzSnQMt8++OEYFb+yfspFyg9SFij2/EdjRToRB oTKyeRaKfHGs2rf+m2GcuyfIRpZjL8JTgIlnw9ZmbDTJhgTNWb4bRKJfYeidjTqbcDF+ gEKg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=s7jN7K7E; 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-4a779d4e5adsi53628741cf.14.2025.06.21.20.26.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 20:26:28 -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=s7jN7K7E; 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 EBF1539D36B9 for ; Sun, 22 Jun 2025 02:46:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EBF1539D36B9 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=s7jN7K7E 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 2B900388E111 for ; Sun, 22 Jun 2025 01:18:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2B900388E111 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 2B900388E111 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=1750555113; cv=none; b=CN4HBemOuZTVYWsxtuxHqDllV7vQfPDhNdj6rgJtKaZGOnRQyyyiyIdl1kqWbclRCIZKr06mSzJE6fOf3LeAwLu1VSqX9BlsCOzU2G1RhJ0ctXX3KfJ3RneQoocfDtRKp8zEBP2EDfy5CfF/jizpObzxR1C2fHegSbA8SOdl8nY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555113; c=relaxed/simple; bh=9ekKI8VF41D1/DaRXGjAEquiCwLubOGy5DMH4scFzmI=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Cv5qjGgJ/pprVyyzNiol6ka3xOcfi1p0IKoiLTvXlFBm+QMvqLWYxnzGV9zpgnVCsMCYiPXrWIiZxZsISZNROZ6sqVkQ8Yye7NTjbsFr3c+4UaXQkunIsiOfvbGDrECEpg+J3v7Hlfpzaj4WkatBFRgV57pKm3Plr4g3okJU9bA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2B900388E111 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-73c17c770a7so3516682b3a.2 for ; Sat, 21 Jun 2025 18:18:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555112; x=1751159912; 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=tGXF1zM4NpSixHEzX8A2BznNtrCYoyrOnu5IybnXb3U=; b=s7jN7K7EkkBS9v5ueoSZ/tecqyx/JTlOjMzKpjG5ZSsYPm/pFrd0jo2Xc0mP7VG6d7 h7e5c7tVHtBSAFC6Re3tJ7h5lfwdsPiyezVjoJm/K0afiiBk4rfS/yV3QZ185l8mXh6o BHX5tKOMFKkcG5r03hkflsJlBInUpNv9hDF2m23bcfBcGxEbH51rMVwvmtozd9JXd73W PNalqy7P094LYZKqjiE2dR1PS33KGCB0ERTu0gTXmH2uYKzuBggj5Y43HhiXBSdKQzda sokeI7B7HOZ5skcrPoWmZPrUnrE8LQMkSi9SNy7yKvJoEP5fRfIXqu3rUAJF0GbqQUsr TK7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555112; x=1751159912; 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=tGXF1zM4NpSixHEzX8A2BznNtrCYoyrOnu5IybnXb3U=; b=EyT1I5cz/2XqgMHyCxJnGCv1n3gQvD2ncGtqYDuIWAm/+frmfUlTSuuYPom2VirkAf Qwqi3htQeEQY3IEiWkYX/gvvCXFLLycJffMNOyzb9zw1jc+SPiwInrVxu39YPIwTai3e jEClEcn6rGpsO7qxs+PKblGd67D+8nSujI55tDAO/5LkOub4Bbou+3VbbCdmYByLCpds CRyo3fqqPeCvUOm0H8aVmBeCERgADh+NafgcUtsyp24pC0QwtCVf37AawxTtqF79f7vZ yQ5CkLuKLHQvuGkbibuOMhVopKpqecusuoAlidpi/SqDWUBmlgAtBlLmhUIRJccjEsf8 fTKQ== X-Gm-Message-State: AOJu0Yz31If3uJ3Znbo8vlOwwqRAqFLFFHXKz2/D/IS50+MRqSS8CzXp 9tca+oGXLFq+zzifS9f7FBuTUaSONjvJHY7ZkCDHI6kOd6FzCFyeLi/RWNsFpt/JZmyejAK/EYz ar0p0 X-Gm-Gg: ASbGncsdOojzg0cLtukRorp8PIb0kg6v9MzKmYVbBx2udlaxZtX5K4+YTq2qyWsHx0h vG5D/bLvhmnteVeAFh71MAgNYit/kekh+WT3wj3TldDI5AJquXobCsQInPaWHuTVSCClOIz6Wvx 09Pk1w/1QDgSa/l2YwKnUWS1/9uOKjP+kZuJOcmu8j6EZxASrRwpTbzI8pyrW0qC2ADdOVYjOdx XEYYdt22yKjTlUVQ6TNq/ZB/GkNWvnFh5ilVq8zRULI5zw62OVs+LwaJd8nV+hEhtyxUJm6qaYA UUkxm4+6utEiQfby4d6aZpz9CrsH2L9DMCgtX9Hi2mBUoltKcxxQnHpVuZkD5ZyL1BphAq+/ X-Received: by 2002:a05:6a00:1914:b0:747:ee09:1fd2 with SMTP id d2e1a72fcca58-7490d630890mr11612299b3a.12.1750555112077; Sat, 21 Jun 2025 18:18:32 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7490a64a90csm5044157b3a.119.2025.06.21.18.18.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:31 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 6/9] GDB: aarch64-linux: GCS support in Linux signals Date: Sat, 21 Jun 2025 22:18:08 -0300 Message-ID: <20250622011811.371949-7-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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. Approved-By: Luis Machado --- No change since v2. 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. 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(-) diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index fa5b265014a4..a5a579a90c28 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")); @@ -2845,9 +2910,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 @@ -2864,6 +2926,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 Sun Jun 22 01:18:09 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: 899059 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp364231wrm; Sat, 21 Jun 2025 20:35:35 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXxyBcIy/7qy/slK8aYpRYnEwz3LIdBZE7l2GLULg3O7RZXfwfBlZdfkkEuYRAlITf0cV4Nnw==@linaro.org X-Google-Smtp-Source: AGHT+IH9jcmxCok9/aGQtOVuNioCgD71RiMV9RkSmB2vJa5OPFP5tcB/b6/1dJ3uPB+bRNr1UD7c X-Received: by 2002:a05:6214:5f0d:b0:6f5:106a:270e with SMTP id 6a1803df08f44-6fd0a632c98mr105091146d6.44.1750563334866; Sat, 21 Jun 2025 20:35:34 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750563334; cv=pass; d=google.com; s=arc-20240605; b=hSMiWixkCXc+nyhu9ykwzi2rA3l3LXx9N/8sHn5SIP+LFK+++5CdeQoXlWb/WmVKCw gpO5kCbXEedNEiJydbhyJdDn+cv2CIaZOC9yQ16L8YqF+1rW3sNwfsRSln6iaJqcTtk/ YVrz6dHoYz3g66Vl9meHwmj1VUT14m3cWJcvR6SD3n8YKHGnKLqz3dRtII+mr3XFaGH2 NKzxy4NsDbAOUezcnMSQmd1cyWqarLS9cfaOB3irkg5Rom5TZKpYSjrVdN8KWmlkzTao im9teZ+KP7MnVu/cgdP1P4X9eLrtNRkq4vWb9RCk0LIg+ICCLv2fgGh/Ft1+0DjUZWRz EC1w== 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=0102dUAso2Ty/hiboIgtv/ybLrpC9TjpM+NoCutV7Vc=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=DPhN4tst++amXLn1KDT61cO5M9VU9/MKJYV3PkgeEB85cY7Gkd/9FgXhmdDZbp4L8X SJgXYtN2Az7pyJzujlUIAr4pVFcxiu+vNd0IwYiBaoVvfWodKcuhd+5mIqPz1mhKmVRC LQcikKFdUzyhTlWrKdZj6Kz0dxFMjzPgbfslZXq0l5Q89n1p8FUjrDIlWzySR6d0ic0W sc8B3XsBJfxCz79z406HwKZGphgnkRD/EhEiNylSOgGaTgfr/FFSV5KQSjNNChp90PqS BklgJ3Uh7igakCteErHskIaYM/6qCXLJ/1BNij9WRAs8dR+7Igp4XKRhZxLs3gdFSXZI 79uQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=oWW3gPCk; 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-6fd095e8d54si56447936d6.507.2025.06.21.20.35.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 20:35:34 -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=oWW3gPCk; 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 C5CF339FA364 for ; Sun, 22 Jun 2025 02:55:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C5CF339FA364 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=oWW3gPCk 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 9308D383AD72 for ; Sun, 22 Jun 2025 01:18:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9308D383AD72 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 9308D383AD72 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=1750555116; cv=none; b=S2AX0PsinyggmUe7QRlW7kv9QvhPWZssA/cUStfmfAs9JJcZhTL/8eJfnGBefNpJiyISkmS3r7s7nwSoaDSVGVyLEotrS4Vt6/4s5Y2d6uyH1sACCLUOigoDDVDac9UyXiK1K+a26Jwi9y7hF/R6lsIgl9qKi/lrXSSI7sCSejg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555116; c=relaxed/simple; bh=1LovfY5PS88sLHlh6CXVH6XF1Oo93lWG2vyQoPOQANQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=m+6omTT0RVoglwTM3kPmyv84ZCJE/qolkM6qv4Oq+c4b6vevlIn+rqW18FZaDrJPtUfxcNBXC8Rtz91fc1X5SIgRefUEMqRQzy4I+/zmyReuBgcmsnKkzzIEwYIXFz2QJT4s1QIvfHdv6TVacJ9f18dqwfHBbz5wrzAsffzipiQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9308D383AD72 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-748e63d4b05so1760934b3a.2 for ; Sat, 21 Jun 2025 18:18:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555115; x=1751159915; 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=0102dUAso2Ty/hiboIgtv/ybLrpC9TjpM+NoCutV7Vc=; b=oWW3gPCkmoA78wGoRQoBCEgpkrlcPM3FfSg+ufkQuFqw31W4r04ui/L6uvkIqjXWS8 A2KV3V5SejEM9RxZ3L/FhJBHPHJ7QLqCK3mCCqascAVcOvJPQlVBrF96n62HplyTMHmd r47cATXKFmrXLv+QiR61bJQdM5QOfLRTS5n3fLGhlCjn5OuOEpcZLJD+B00W1FT8/+9B 2xm5xwfcTZ2cdDGbr9iVOJxnGmFOvfmlwiekCaqZ48+GRlQRUTJcCQ0eyFJmXx/Pcx9W 4qp9xCyfGCQI3WvAI/UJ8JPKoEaOgvYnYpPTjvUhzOmtgceow+XIZW/fD4suxo5aSXQ6 poTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555115; x=1751159915; 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=0102dUAso2Ty/hiboIgtv/ybLrpC9TjpM+NoCutV7Vc=; b=tvxID8JBuf9oNfCUF7XzQTFCkOtZvh07S7JyCsJsZL30cQGUuk2WQaN+hVTVhF/fhL lWem7iiViKSOu/L1eJ1c/PCn/WWNiBKf66Ea4lLEh9rLfg2H+qENSajSCcWwuC41AcL9 I9KgGfr1FMs+E1PEnEMkCWpP3z7HeKqhrw6e2AoRkaSxmcf/9FFOlSCjanYNA8u5U+pm pWT9L6oRMibCYZLHfcdYIoi2GSOmIFfjUwDXwMfL2CChV10W/lhletWZ32WH7o6BJ4Nk 9tgmK4yQ/Udu4qoQTuBLhxE7RQZnJzwxVjD+uAXsXaEi3gfHXnxvQGhWWGX2cZblGk/C Uatg== X-Gm-Message-State: AOJu0YyHBqfw8b3wAV4+NA9ddvxVOlKviYJVZvlS9GkH7+niPCz0M9q4 1VhqmgTOySLg4VwJeLzyvPU+uqI24r6NkBqe7PL5KLoNnA7kYi15JYm/NaR2A5ghVYlVRvVIFCD XG2X3 X-Gm-Gg: ASbGnctfzLC4emjzEgL6PkuT66JwVzWQLF/iEt1EAWZrmSgWjeICeWafGE0VOnyq1uE E4TFdKzqHIpEkcdnbx8yyl52ON6KqnFc1bGcetNjUqnl+zRdG14j3on7998Ks/FvpKRzKu23hTY vr8j8QwGGmTMFpnctCm3wNIHWnM01FTJ2Nvi2OI2qOPuSe7eZkzVjUYV9D69SRylt+qHSL0ByHT EkUsSBySJ9XUKTeNH+e+c5RtZQ46bp0XGVKKGBkV4atq/a75JpHCgYeyra8gLke4Bj7yj3q7eQw DrR1p0ApgrQ3RgdE8eHPIVvpY0JQkz93LggzcUjYVYHToQYad/gWB5T2JPoA/xpM1xk03VyK X-Received: by 2002:a05:6a00:3c8f:b0:747:b04e:941a with SMTP id d2e1a72fcca58-7490d72439bmr10802159b3a.17.1750555115435; Sat, 21 Jun 2025 18:18:35 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7490a69bb99sm4999084b3a.155.2025.06.21.18.18.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:34 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 7/9] GDB: aarch64-linux: Implement GCS support in displaced stepping Date: Sat, 21 Jun 2025 22:18:09 -0300 Message-ID: <20250622011811.371949-8-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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. Approved-By: Luis Machado --- No change since v2. 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. 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 diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index a5a579a90c28..0538412ce554 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. */ @@ -3110,6 +3136,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 Sun Jun 22 01:18:10 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: 899064 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp370902wrm; Sat, 21 Jun 2025 21:09:07 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUAAPe7CqXe75BGZVsP03kBPw0LBp0A7bB2oamV+LESuDih0U2d4ezp8ya7byQiGIERk/V8Bg==@linaro.org X-Google-Smtp-Source: AGHT+IFnFMCKa5fn7nDLKynBNC6uHJEnvWwSIJI+2eHWNG6FAxkRzHwaMRUG/J3dhuuCYqroq4rd X-Received: by 2002:a05:6214:2427:b0:6fb:107:f618 with SMTP id 6a1803df08f44-6fd0a5adf82mr120494086d6.40.1750565347059; Sat, 21 Jun 2025 21:09:07 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750565347; cv=pass; d=google.com; s=arc-20240605; b=Rh1QXDjUDKM8PafrHsrMe47bUEnHdMer5T3xeZU/7uWPCgmlqluq3XTntGcx8iEGwV PV0FWuTxsaLO+PTJtFLzlt7KYjBXjv37qpDeMxPCQSz1r5QwNmSZJxHnLf8B/sle44Ol Hvi9hgEOtpCwhsn7Ov3orKvgMII+eWKiPURIkAvvB0Hr5UyGU7FzXL55yObKH7jnQXpv z2EzlydOy8ZCakaevOQAXOtre+y2MuRGf1W1Zw938jRaqBhvirn3znaQE6AtoTMMiYnq rKc+ePdCnL4GN4pEB1HDDQLiKKNNDUPy/Yp1R3ulA00Ya9RJhDpUA6AbUC26Gx1Y0xET pV5g== 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=XdP+NYfiqCrU7Cj7xmAeAGA4TFktOo9EQLv16wXoccY=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=KHUJ1wGUtmF7Bi68RNhy/iDw7bUScEt2toaByLGwUferBvFXm8ywNWZoijuJcqJIeD VzMztHDD2hMqULdESdo1iejxjsjGCTDnJMKa98qOl+SfeJ/CXq0U5NVD1n/SY6HXbohO kJL559RyvLv3f6CTdo+rlujM4j6Nc009F6uxE9yFVGWHMdH3HpMWFyaWXhqLxsM5cCdn RMNYG9M7/UTsIZNxpY5EgFcRV9D96paLFz367Em8lC5weEavYPeiB5E4FtRfisilW+tK 7h98wGFgdfnpCdZM3Tryj4QNfvbzqeHKJ1upGiVE4tujaWDRyh7LdfbCpiOiQlCDDLWz 4K0w==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="p+JACMp/"; 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-6fd093e15f1si55560576d6.33.2025.06.21.21.09.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 21:09:07 -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="p+JACMp/"; 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 010D839948B7 for ; Sun, 22 Jun 2025 03:05:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 010D839948B7 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=p+JACMp/ X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) by sourceware.org (Postfix) with ESMTPS id DD15B38101B9 for ; Sun, 22 Jun 2025 01:18:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DD15B38101B9 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 DD15B38101B9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::430 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555120; cv=none; b=wxXrahjJg6t2yEixWtOdQSeh5M/ZYMXEDgzZJQrHdWHNSRWGsdao1hzGZlTc1kCwpqqgvSL7gon/r40Z+mnHkfQcH2Qd8KifebXKO0i91V60Du+Ps+Hau/gAQlPtt7QduLQKvntItuzbjrVyZGbs1lbYIe6AsLh8oxHdLTHyf70= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555120; c=relaxed/simple; bh=Jl5HHGrBnhvKAoWNgaxviCSr+GwYp0rIZx7kDzoTL/A=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=cXGLB6qtdQG230X3kOnb2s3XAv67LfXMAkF2LqXk6i34eig1DGH6Q3CicZd+rILsXbfpDq9Vc0f+2MogTmQ5Br/mgRPuQSIdDDXYggQ1UzTsSydaifwAJ+WKlIJoKTwjS6pbzd1pSknWDvxqPk+h71CB1vNoNkfX6lXJ4kWsS8g= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DD15B38101B9 Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-747e41d5469so3162839b3a.3 for ; Sat, 21 Jun 2025 18:18:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555119; x=1751159919; 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=XdP+NYfiqCrU7Cj7xmAeAGA4TFktOo9EQLv16wXoccY=; b=p+JACMp/qTROyrk6Tzxc5xPEgDoUbt0f1OEYm24f5wVduNznFI6j2om2uEZMtn3ee0 ZlhPGhK4Rn2GgwnAurO5mbHjarJgR1V7/OoRmC/K3uXIwU6uRoAiFTPwrRudV7O5I8Vd mq8LfibQQkAQC/43/8a5Paba3YLsOoNJ022jMrkxdYMWIJJSXjW36Zbji84A+WZlsfUl O6wI58Dj4EwgXzT/C0+LX3kLNcjyYzsuziwtOhzOqgP+6cn/+1+Em0v22OWRhd3su0AF WPvq6I7uQJmZKz3TfY73x4ch311qgnGOM4oKXm/lk+azKd5bG/m4LRsa4tWy2JaUEkDB 7+Hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555119; x=1751159919; 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=XdP+NYfiqCrU7Cj7xmAeAGA4TFktOo9EQLv16wXoccY=; b=UIM0pMgBUMl/sLEAiXErpWZ1qerLi3bFekVKIfcxZR2sOLXuab+VRCrVK0Q3QXXTrq nSpNHXawcnWhtdk3nCVOKfYRu55nlWMUQnxNW6z5Kea/r37KU2h0t9LYa4kT+ZIqpR/t Yv4ahCYrW6rTS3wRpm0AWlWjzcC9bjFhwMh3DGqWXlc4kswtxM8Bb1sDEjuMkhlK7IEw Ds5YJK7A27tHvy5MGdojsWlT1hpNbq6Qh0f0zyK5rfvvwNmm6wEFKYEI17H3YkypHY8f maJYfI7uHBATcpPxebmSnTTlealIQK7oR4aEfBG/wPQCeHWwDGYWklGWKBTQa4X3PPJi u0Lg== X-Gm-Message-State: AOJu0YwaHebyjgogYTsFmKg64ugphMRjLPtOdPgpk58Co3gCku6eLf1s so9dRIFQSDGpj9L6Ko4FlY/nfXe+vJbgyAkIq5lU/13JykVHy57vq896aPV3W0lqsX9vkLG+ZQy yHNTl X-Gm-Gg: ASbGncvQFq4ty/6T/dsplbCFH42KSAvvq5AY5iwMSwqv9c0K7bqvG+lWNT/TWg8u2mI E00nXfw+b48WyTAlDD7/U7FRViRLcZ1GbZ0g8oc/AUq9Sg43weBV2TWAT37E/pCJMuUG6iN0K0+ 6kDidwvfbo+FLK82hZk1xalN3M4aPAduGB7VrxeHgrRb2tahurYr5v9WZ9L2QRzc3R3IMMlnIjS 4s9YG0jV+yFm1/cNSS8l6ulkHM+RgIiRd+wmHTdzEjwryhB8PtUYNvPVyNLPqCPtnTZ1KiZbZZk sUb7si9J9iTq20TOWZnf0TkPsaBm9wQfGc0cMHu9SETi3ruU3G6dBEyrplo6GhP1aKf2BR/td1A s7yEV/jc= X-Received: by 2002:a05:6a00:2e99:b0:742:b3a6:db16 with SMTP id d2e1a72fcca58-7490d67f737mr10673445b3a.20.1750555118835; Sat, 21 Jun 2025 18:18:38 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7490a48a1b6sm5265155b3a.50.2025.06.21.18.18.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:38 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 8/9] GDB: aarch64-linux: Support unwinding the GCSPR Date: Sat, 21 Jun 2025 22:18:10 -0300 Message-ID: <20250622011811.371949-9-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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. Approved-By: Luis Machado --- 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/ Changes since v2: - Fix off-by-one error in new_gcspr comparison with GCS memory range, and clarify comment (suggested by Luis). 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 diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 0538412ce554..1335d0424f26 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 still points within the current GCS memory range + we consider it to be 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. */ @@ -3138,8 +3187,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 Sun Jun 22 01:18:11 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: 899057 Delivered-To: patch@linaro.org Received: by 2002:adf:e506:0:b0:3a6:d909:26ce with SMTP id j6csp362983wrm; Sat, 21 Jun 2025 20:29:08 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWfPp6uG7yVtsZK+5Nb4M51uhIvZE8OGKA0OO56WRprnYp1pOkYiFKTY1TLMu/4V8YWeGVVhg==@linaro.org X-Google-Smtp-Source: AGHT+IGwykwg9SrycCtwZhEQ4xQWszfxq3WANCgELy5jyKc6z1dwlAC+dkK8TAkgzYE1EXgkKWQK X-Received: by 2002:a05:6214:4885:b0:6fa:9f9b:8df0 with SMTP id 6a1803df08f44-6fd0a534772mr141484336d6.20.1750562947896; Sat, 21 Jun 2025 20:29:07 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1750562947; cv=pass; d=google.com; s=arc-20240605; b=VroWy4tnbSh3nLHk5Z5wCpOohJIXe22VTaDGEBMbxvLNqBhmQJ9uEA/UNSYllypg12 VCzLaISRC7ZXZdsSbkmwwO94/On3cTsFslS3MhvAeG/+yhKT4OGOfvsuV6+mGIL2ki0n xhmavJwlo6OjRLJtlXLPWejA5EfTCAhoXAySjGiitG6NaNJmvErj3ExKCAPDmiDJHDO4 Z2ucH2f9iSnuvf6DSTmlzeiEcW7Wsy+CXvhXnmwcNl9xDnmDv1ivWmJH6sCay3GgVJNM pivTOCSo4FkTa65fln86widEsu8wFZFowO7NwijRb9fVwczX/blHLTGg+8/vlG0yXTx6 kTUA== 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=8UCsPheKAJ/miZ0v+BEcLPL0Ag4YuAbL6rwTxmNRspw=; fh=v0Swrqm/HGzmFfs2Lyn4KGEK39u4NVWMm4qGXeDZh/s=; b=eWZtMRqfLt1ZwHmGgzRUqHP5Cv5sQ19xuSH7kzzKxQJRmzTipA9y/0/r5Z/SoD7LXr 5MTlYiBsixsblukX4PdofCmjWuYBojJO8Uxw3DY1KLii5jji/ldKtUpQvCfbGF+Aizpq iLfNPnoXjHmsLzRl5tX4MWQMhPrM8LOSG0ETYnZmQBVxCBEetnoRSz07Zq/kK0IBlTm0 0kRkkJbKQAcTb+opk2/W1qUONpRftojjRL8p+TjRQXmyemOCJAgzAFXVLIgoNJ5fJC7/ e00MWnbKB5qeZNtbaXV8SwtHt+srf00tCaksdaUiltNgfN9f1VrPmORUaBeW9p/B7lOu bc3w==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VhgXfqsG; 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-6fd093e15d0si55918246d6.92.2025.06.21.20.29.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 20:29:07 -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=VhgXfqsG; 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 9E0B039DD8A2 for ; Sun, 22 Jun 2025 02:48:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9E0B039DD8A2 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=VhgXfqsG X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 8B0D138EA03E for ; Sun, 22 Jun 2025 01:18:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8B0D138EA03E 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 8B0D138EA03E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555122; cv=none; b=Fp6p4N+d8ik+B95eoKGB9UTvBdXiTYQBj7veR6GIJNoDqSMti/s81Kx1MftMUlMma5f0L2sAORR60zcj6pOJrtmwytI1QvorklMn15xNT6B/QAHVd9jKTB8kT9gEtU54YBDugpHNAPubylPepb3UEN9vtV7o6ZF1bTSGxsx9dPo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750555122; c=relaxed/simple; bh=R64MVqzAkM1oQBeETipOqiwfkFciHmBi6ZNqArujTyA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Migy+QvdOUe2y6pE3/4+hotY8t9BOfQqbrrv8enla7En1dQiEFOl5oYBd59PeXCtJpkkQp+p+dWY/Sodw9kvL4dFlJLdzIKzkWmaj6hKHh+WeO1rp5WdqHqyV9VMTU1rRCsu1NiAr/Jpo0sT6nhFhThMfo6+JIIo7wPAG5XZL8k= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8B0D138EA03E Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-747fc7506d4so2296768b3a.0 for ; Sat, 21 Jun 2025 18:18:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1750555121; x=1751159921; 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=8UCsPheKAJ/miZ0v+BEcLPL0Ag4YuAbL6rwTxmNRspw=; b=VhgXfqsGvYA+pht3ZLm/mFdwTkR1lsQyHKhCHPzcyXTPV/kDKOe+eASziYFgtQBhaZ 7cqvtadcCHpapd7ZDxe8mP18uuCjwFsKML36SfKIDJW096dZ5v+E2DwTyg0J/Hz8zCQi 1/rLs8CV1m1gi2GSFAsjer6GfmI+s0BfX8bv3ymWAqejjSamPsSOsTKURK1FgrhgBKqR wDNuMAhGfJCDU9myNqS/IWrvI7p5RN1cVMZkxz97pz18h/WqeLHuj7OMsxWpGByqTk+z BFllzZaL6Q/93YkNbkf2snnk3yzNBg2LKqNyOu4KCjPT1nA/gJFNKewbCRJijwLLTnRN Y88g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750555121; x=1751159921; 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=8UCsPheKAJ/miZ0v+BEcLPL0Ag4YuAbL6rwTxmNRspw=; b=E48u1dEuEJrRm0oMYwtxL3zHLmIW1Ukw/BFf7BkAMbnJwCl3c98iiKFB70kN4iq5sq qxxbBMCoofLapCjZ+paoVVVJ0D7HqHLTgxSBHQcznbhHSsGYXD9jadQiKWjNOQnKpS48 PBEZQasiweM+I/SAHWc/vy5a+q9yZXu3Q66aLS1P6OiGofouhvtLbfP4Alb/+aSUpRYo LqXw3knpvO9MLDWr/f2SVh5fF5V2vNLB5U0Eb7iyV+pxuvA+vd46IwuFW0qS5SCkHs2v 9HEthF88Hw0eA9U0UYkrihNHzV7kvIXR6O6ZjlOR5x/CoWyX+/qC5vZwycHIoMX2CUYw rKmw== X-Gm-Message-State: AOJu0YxFzd3ScjlSDC3qmp032WvhxwGlzCUtxbm53NZiiPruxb+NV+xc //J5aWaXlxVB68v6ukaMU/zSp+BAJWpohn+W3bBq+1/LPwjm742sY0aU7ZvuDjKwAy9vMqJDLHa MDdxS X-Gm-Gg: ASbGnctS6eML0kBrICeglwan6bqwH+ZMh0F1/i0eXh9jNG8q3lFGGbmUVoDirlnbPu3 +jIEdmd19yIuKZWtZPhBUbvDOaSR8KwVJDAon4hqYe0ngJWJbbP9WIuQ1b7tmUB4mOOmuicUtqf SIBzrT3daQ2Bxn6EEqPUHr9LXC9Qbmwzcpfq7XgM6rJfs3T500eLIcAvh7AXZ30CeATLmoslFFy jCQlq+1NkriSi+VDaOoN08fM1vyHaQG9KUOU1rpPnk1SLf6NyUs1BM9esDwJ3V1+oqnWRkL33/q kkMyHKiaVWc4JonA3EO5FxPgjhuI4gqRxsvt6VdLHIWy2YEmxzCJNcLQ7jh2nq/wfxTKi0QVQJL L0tfGXbU= X-Received: by 2002:a05:6a21:78d:b0:215:e818:9fda with SMTP id adf61e73a8af0-22026f66715mr11145479637.27.1750555121537; Sat, 21 Jun 2025 18:18:41 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:79ae:7a30:10f3:dfed]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7490a64b2aasm5070707b3a.116.2025.06.21.18.18.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Jun 2025 18:18:41 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Cc: Eli Zaretskii , "Schimpe, Christina" , Luis Machado Subject: [PATCH v3 9/9] GDB: doc: Document Linux AArch64 support for Guarded Control Stacks Date: Sat, 21 Jun 2025 22:18:11 -0300 Message-ID: <20250622011811.371949-10-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622011811.371949-1-thiago.bauermann@linaro.org> References: <20250622011811.371949-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 Reviewed-By: Eli Zaretskii --- Changes since v2: - Added missing @code{EL0} and @value{GDBN} tags (suggested by Eli). 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". gdb/NEWS | 3 ++ gdb/doc/gdb.texinfo | 83 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) 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..7afe96035ba8 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 @code{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 @value{GDBN} 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