From patchwork Sun Jun 8 01:03:18 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: 894808 Delivered-To: patch@linaro.org Received: by 2002:a05:6000:ecd:b0:3a4:ee3f:8f15 with SMTP id ea13csp1177591wrb; Sat, 7 Jun 2025 18:14:39 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXODYLejKpwOBRknyxYFLeDtmtfWv3SefniceUAQD16oFedyJApWm2JB4iMpUmkt3xsxig3aA==@linaro.org X-Google-Smtp-Source: AGHT+IGMa9jEhAA4Z6VhvOTK8a8Nd9LncT1FgZZUcgtXZtRwQ4GTdMYqO5FeUXCxcMLkpABTnELv X-Received: by 2002:a05:6214:d0a:b0:6ed:df6:cdcd with SMTP id 6a1803df08f44-6fb08f6e27fmr140958196d6.21.1749345279721; Sat, 07 Jun 2025 18:14:39 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1749345279; cv=pass; d=google.com; s=arc-20240605; b=AuREg4SnQKgOkzhzXoSzeND79Kujv8xbvL+saHVIq2A5cUNSHCA3/unrPQCxZD4Rpe dQCukveug7+5MckkQIxmNIQyCNHa0JOPcNrlQp1p2VvdcLzpNfrXkjPsmY1HxRGaCCX4 eB+yiWkgruxktDZnfBcQn1FaYMkS3j1YXNMbNnnvzcQ1yRYEs6saj+PYBMM7w6a2g7/w luTVT1KY849ODLGW3Gvs94VuC6zDyLx0iRjKMbxVbhTEgT+dqhl1D9hdnFqjxaXvuqU7 dZDxZcgqxl3IxdpM0rJq723lV+FTVqJD15lUHEpZLe80Ch9TbETPNoqk5iVj2DH2kez8 f7sw== 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:to:from :dkim-signature:dkim-filter:arc-filter:dmarc-filter:delivered-to :dkim-filter; bh=UUDIpZQEuR/3Vkym4M05JsegAxbJWfIO4yDqHYzoInw=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=Q4rfFohDNgMJ+w2nFVxo9Jw5OUsyq8bOxdhGKxKCOzJu7XSuBp2/cCex355mdZYDv3 tzAepKV8/n9vwe17wNYMrvIEcNo/xRmlBDtdDmckCYa5wWTXZ7XFM3yG1rEo2i706a6v dzuTFv9XBItWYqLyQRHcA4ze9+BVtUjDRSR9J53MBeb39qCCcDBPc8QfVMd3WjrfUkgH e/HCtWjqp716fzO7rLzLcY+1OJ44AqsonnGMPm54pb93NimZV5UyYQsd+hDE8/xBE8eH 7WESITmoEvGRYfd+8xsgdwU8UQk+9De5VdANgDDPId8CXx7zr2lffKS+sSoXCbn8cg/R 8++Q==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=aBEAE5H7; 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-6fb09b16e9esi49521546d6.138.2025.06.07.18.14.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Jun 2025 18:14:39 -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=aBEAE5H7; 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 3798A3858290 for ; Sun, 8 Jun 2025 01:14:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3798A3858290 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=aBEAE5H7 X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-vs1-xe2f.google.com (mail-vs1-xe2f.google.com [IPv6:2607:f8b0:4864:20::e2f]) by sourceware.org (Postfix) with ESMTPS id 9B475385781A for ; Sun, 8 Jun 2025 01:04:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9B475385781A 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 9B475385781A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::e2f ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1749344645; cv=none; b=OBvwSkBYxwoFAaWJuly+p3JB4Gbg5epVI7RqDcuUpSoDDoaQF2B2hJxQQFwYtS8S0iFuqjwTdIoSz8pwpKEQJ3QhuLJ9SK/OkrtGElE7E/RNLsXxlasq8/tL7nTYsElARxtu7zLDeQNYwiaUb5OP4VeQjQKuk4bXup0Bhr9dCMg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1749344645; c=relaxed/simple; bh=EfnWAQyDEZlJCR//fw9vw9oC+c1Xud1+771Qzv4Auig=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=qLNj0XyZ6T5ruAblTnix+MQZxXEEAnUiCP6i8j/fl0AILZ0KWoqVduQRpGWhOVfo3kq9WgX5bt162LO4vWFFAqA8uzxEDyG5oH9GI3khMcxC4myCHoowAunHzqoK6WlMpUgjMlMCCz+hLJB+h97kZa5YDNJ6EGMNHZ1y5ufMzEQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9B475385781A Received: by mail-vs1-xe2f.google.com with SMTP id ada2fe7eead31-4e2b5ffb932so1185191137.0 for ; Sat, 07 Jun 2025 18:04:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1749344645; x=1749949445; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=UUDIpZQEuR/3Vkym4M05JsegAxbJWfIO4yDqHYzoInw=; b=aBEAE5H7z9FTX6PQHWKaW18pHZuE/LZqRQ8UqyJ+b9EqxJMjjGFLqqusESlo2XzTHC PYKR+1CBh4YiKhjsxEjke3dlFS8D042kh+3X0YPZMq4a9rb+t24t7CzG7Uk8xUZdOlKs wfbnUtIHTGKFszlRsjj4UCG1ldATF8czsl607ca43wMeFonUIvLYdUKnP21THhdjKDT2 qsyivBtJ7/7/dn1gvt3LxUYVKXgPD3nVk3ztPSyDIFJZ7ViWJyJ7kouJdykDeWEE+k8z Dxd3kKPd496JsA5mp7NStCdT3MlYoz3ooACPC2+2JFr6P10fcgyoVpsmkUfjcO16lRct vcvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749344645; x=1749949445; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UUDIpZQEuR/3Vkym4M05JsegAxbJWfIO4yDqHYzoInw=; b=S8wXFUY5Q5tJ1blx5tIvR4+N1/dZjipha6+e/hAxzlwAYLieg2gzLAo+jV4AIF5mo/ ygV+ixl2NlRCwACIU/3S6Hr/TLQBQYjvtMZbfC4iuVpZaQsRkkluPjJLxcFtyqH91Urs svzRXcnJdUdSWVUB7TZ/5qM2bXk0AUHxhRJG0u0ZpgoN4AdB2x/10bt27qGImOe8yaWp H6bwhWa5SSIntX6aLvW/aMntzupHeW9c1/q0CtKaPg1iohlIZpj9ZU0lqjeTlijHUYb+ C/h8SneKEyVrv9EBCFxR75MgTEy08gSyzLeRsJTV44ka47jOxXqrzWVY9YzIFtzq1vk2 vN6g== X-Gm-Message-State: AOJu0YypPqBcXsvHhy7GNgH0Z3Cdn3SwPgszNnAhkRKRMpqgVSDQF4rl A+FmcuXxNbR35XbSLqnjVE865WHeB0rRFniKSKrB2DPOfhXMMxpJmUiiMlDW62l/t6wHQiJRV29 XXUDI X-Gm-Gg: ASbGnctWIdIEQIKBbcLMt75gooJv1iU2DWXGCA5L8uuwN3e2Vl7srxYgjqd8GsS/LkB V8kONluWoH1Gmnb+ozZkurfa3Dm8pjUB6+GytT7REvPdkwgSKKeykZSE6kZNFHk9Sw/gDplKTI7 Xo/pT9oO6CnspkA3cZ8tJIfEOKPI4h8AefkQK/XKDNILDnkVT6dD7FK5Ph2s/0SnyRIgGn+qXvH uMZ3pnHd+2x+Fj14ZKuTf66w3fj5JFiu3SNDes7w/qPWPHRKiRcHJkn7iuOozAZ4S8uRWW14MWI I+QKwUD5S9AHxdOGrK/gh4D5ujO5agxCBZ02XD10zxufW6s6ous9M0Z8wSWt01193pGxwd4x X-Received: by 2002:a05:6102:159e:b0:4e5:59ce:471b with SMTP id ada2fe7eead31-4e772a84cefmr7514168137.23.1749344644681; Sat, 07 Jun 2025 18:04:04 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:8cb1:1e8e:e951:f687]) by smtp.gmail.com with ESMTPSA id a1e0cc1a2514c-87ece19b65esm921570241.9.2025.06.07.18.04.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Jun 2025 18:04:04 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [PATCH 7/8] GDB: testsuite: Add gdb.arch/aarch64-gcs-core.exp testcase Date: Sat, 7 Jun 2025 22:03:18 -0300 Message-ID: <20250608010338.2234530-8-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250608010338.2234530-1-thiago.bauermann@linaro.org> References: <20250608010338.2234530-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 It tests both gcore and OS-generated core files. --- gdb/testsuite/gdb.arch/aarch64-gcs-core.c | 124 ++++++++++++++++++++ gdb/testsuite/gdb.arch/aarch64-gcs-core.exp | 105 +++++++++++++++++ gdb/testsuite/lib/gdb.exp | 4 +- 3 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-core.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-gcs-core.exp 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..d04bd76e0799 --- /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..17bbb5e4ded9 --- /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" \ + "Guarded Control Stack error\\." \ + "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. +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" \ + "Guarded Control Stack error\\." \ + "#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" { + 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/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 2adfd4b1bcfe..cf0b7cb9562d 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -9408,7 +9408,7 @@ proc remove_core {pid {test ""}} { } } -proc core_find {binfile {deletefiles {}} {arg ""}} { +proc core_find {binfile {deletefiles {}} {arg ""} {output_file "/dev/null"}} { global objdir subdir set destcore "$binfile.core" @@ -9430,7 +9430,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}" foreach i "${coredir}/core ${coredir}/core.coremaker.c ${binfile}.core" { if [remote_file build exists $i] {