blob: 0a8f3959049310ccd72fd4f27d791868d0fd2b0b [file] [log] [blame]
# Copyright 2024-2026 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 <http://www.gnu.org/licenses/>.
# Test the shadow stack pointer note in core dumps.
# Based on the corefile tests in gdb.arch/aarch64-gcs-core.exp.
require allow_ssp_tests
standard_testfile
# Make sure GDB can read the given core file correctly.
proc check_core_file {core_filename saved_pl3_ssp} {
global decimal
# 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 \\(\\) at .*amd64-shadow-stack-corefile.c:$decimal" \
"$decimal.*__asm__ volatile \\(\"ret\\\\n\"\\);"] \
"load core file"]} {
return
}
# Check the value of ssp in the core file.
gdb_test "print/x \$pl3_ssp" "\\$\[0-9\]+ = $saved_pl3_ssp" \
"pl3_ssp contents from core file"
}
save_vars { ::env(GLIBC_TUNABLES) } {
append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK"
if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
{debug additional_flags="-fcf-protection=return"}] } {
return
}
set linespec ${srcfile}:[gdb_get_line_number "Break here"]
if {![runto $linespec]} {
return
}
# 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 != ""}]
if {!$core_generated} {
untested "unable to create or find corefile"
}
# Load the core file and check the value of the shadow stack pointer.
if {$core_generated} {
clean_restart $::testfile
with_test_prefix "OS corefile" {
# Read ssp value from saved output of the test program.
set out_id [open ${binfile}.out "r"]
set ssp_in_gcore [gets $out_id]
close $out_id
check_core_file $core_filename $ssp_in_gcore
}
}
if {![gcore_cmd_available]} {
unsupported "target does not support gcore command."
return
}
clean_restart $::testfile
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 \\(\\) at .*amd64-shadow-stack-corefile.c:$decimal" \
{.*__asm__ volatile \("ret\\n"\);}] \
"continue to SIGSEGV"
set ssp_in_gcore [get_valueof "/x" "\$pl3_ssp" "*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"]
gdb_assert { $gcore_generated } "gcore corefile created"
if { $gcore_generated } {
clean_restart $::testfile
with_test_prefix "gcore corefile" {
check_core_file $gcore_filename $ssp_in_gcore
}
}
}