blob: fc1ee86a3b7b363dd8c32f6e29d29c52a38a04ba [file] [log] [blame]
# Copyright 2015-2021 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/>.
standard_testfile
# This test is Linux-only.
if ![istarget *-*-linux*] then {
untested "coredump-filter.exp"
return -1
}
if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
return -1
}
if { ![runto_main] } {
return -1
}
gdb_breakpoint [gdb_get_line_number "break-here"]
gdb_continue_to_breakpoint "break-here" ".* break-here .*"
proc do_save_core { filter_flag core dump_excluded } {
verbose -log "writing $filter_flag to /proc/<inferior pid>/coredump_filter"
gdb_test "p set_coredump_filter ($filter_flag)" " = 0"
# Enable dumping of excluded mappings (i.e. VM_DONTDUMP).
if { $dump_excluded == 1 } {
gdb_test_no_output "set dump-excluded-mappings on"
}
# Generate a corefile.
gdb_gcore_cmd "$core" "save corefile"
# Restore original status.
if { $dump_excluded == 1 } {
gdb_test_no_output "set dump-excluded-mappings off"
}
}
proc do_load_and_test_core { core var working_var working_value dump_excluded } {
global hex decimal coredump_var_addr
set core_loaded [gdb_core_cmd "$core" "load core"]
if { $core_loaded == -1 } {
fail "loading $core"
return
}
# Access the memory the addresses point to.
if { $dump_excluded == 0 } {
gdb_test "print/x *(char *) $coredump_var_addr($var)" "\(\\\$$decimal = <error: \)?Cannot access memory at address $hex\(>\)?" \
"printing $var when core is loaded (should not work)"
gdb_test "print/x *(char *) $coredump_var_addr($working_var)" " = $working_value.*" \
"print/x *$working_var ( = $working_value)"
} else {
# Check if VM_DONTDUMP mappings are present in the core file.
gdb_test "print/x *(char *) $coredump_var_addr($var)" " = $working_value.*" \
"print/x *$var ( = $working_value)"
}
}
# We do not do file-backed mappings in the test program, but it is
# important to test this anyway. One way of performing the test is to
# load GDB with a corefile but without a binary, and then ask for the
# disassemble of a function (i.e., the binary's .text section). GDB
# should fail in this case. However, it must succeed if the binary is
# provided along with the corefile. This is what we test here.
#
# A further complication is that Linux NT_FILE notes are now read from
# the corefile. This note allows GDB to find the binary for file
# backed mappings even though the binary wasn't loaded by GDB in the
# conventional manner. In order to see the expected failure for this
# case, we rename the binary in order to perform this test.
proc test_disasm { core address should_fail } {
global testfile hex binfile
# Restart GDB without loading the binary.
with_test_prefix "no binary" {
gdb_exit
gdb_start
set hide_binfile [standard_output_file "${testfile}.hide"]
if { $should_fail == 1 } {
remote_exec host "mv -f $binfile $hide_binfile"
}
set core_loaded [gdb_core_cmd "$core" "load core"]
if { $core_loaded == -1 } {
fail "loading $core"
return
}
if { $should_fail == 1 } {
remote_exec host "mv -f $hide_binfile $binfile"
gdb_test "x/i \$pc" "=> $hex:\tCannot access memory at address $hex" \
"disassemble function with corefile and without a binary"
} else {
gdb_test "x/i \$pc" "=> $hex:\t\[^C\].*" \
"disassemble function with corefile and without a binary"
}
}
with_test_prefix "with binary" {
clean_restart $testfile
set core_loaded [gdb_core_cmd "$core" "load core"]
if { $core_loaded == -1 } {
fail "loading $core"
return
}
gdb_test "disassemble $address" "Dump of assembler code for function.*" \
"disassemble function with corefile and with a binary"
}
}
set non_private_anon_core [standard_output_file non-private-anon.gcore]
set non_shared_anon_core [standard_output_file non-shared-anon.gcore]
# A corefile without {private,shared} {anonymous,file-backed} pages
set non_private_shared_anon_file_core [standard_output_file non-private-shared-anon-file.gcore]
set dont_dump_core [standard_output_file dont-dump.gcore]
set dump_excluded_core [standard_output_file dump-excluded.gcore]
# We will generate a few corefiles.
#
# This list is composed by sub-lists, and their elements are (in
# order):
#
# - name of the test
# - hexadecimal value to be put in the /proc/PID/coredump_filter file
# - name of the variable that contains the name of the corefile to be
# generated (including the initial $).
# - name of the variable in the C source code that points to the
# memory mapping that will NOT be present in the corefile.
# - name of a variable in the C source code that points to a memory
# mapping that WILL be present in the corefile
# - corresponding value expected for the above variable
# - whether to include mappings marked as VM_DONTDUMP in the
# corefile (1) or not (0).
#
# This list refers to the corefiles generated by MAP_ANONYMOUS in the
# test program.
set all_anon_corefiles { { "non-Private-Anonymous" "0x7e" \
$non_private_anon_core \
"private_anon" \
"shared_anon" "0x22" "0" }
{ "non-Shared-Anonymous" "0x7d" \
$non_shared_anon_core "shared_anon" \
"private_anon" "0x11" "0" }
{ "DoNotDump" "0x33" \
$dont_dump_core "dont_dump" \
"shared_anon" "0x22" "0" }
{ "DoNotDump-DumpExcluded" "0x33" \
$dump_excluded_core "dont_dump" \
"shared_anon" "0x55" "1" } }
# If corefile loading is not supported, we do not even try to run the
# tests.
set core_supported [gdb_gcore_cmd "$non_private_anon_core" "save a corefile"]
if { !$core_supported } {
untested "corefile generation is not supported"
return -1
}
gdb_test_multiple "info inferiors" "getting inferior pid" {
-re "process $decimal.*\r\n$gdb_prompt $" {
}
-re "Remote target.*$gdb_prompt $" {
# If the target does not provide PID information (like usermode QEMU),
# just bail out as the rest of the test may rely on it, giving spurious
# failures.
return -1
}
}
# Get the main function's address.
set main_addr ""
gdb_test_multiple "print/x &main" "getting main's address" {
-re "$decimal = \($hex\)\r\n$gdb_prompt $" {
set main_addr $expect_out(1,string)
}
}
# Obtain the address of each variable that will be checked on each
# case.
unset -nocomplain coredump_var_addr
foreach item $all_anon_corefiles {
foreach name [list [lindex $item 3] [lindex $item 4]] {
set test "print/x $name"
gdb_test_multiple $test $test {
-re " = \($hex\)\r\n$gdb_prompt $" {
set coredump_var_addr($name) $expect_out(1,string)
}
}
}
}
# Generate corefiles for the "anon" case.
foreach item $all_anon_corefiles {
with_test_prefix "saving corefile for [lindex $item 0]" {
do_save_core [lindex $item 1] [subst [lindex $item 2]] [lindex $item 6]
}
}
with_test_prefix "saving corefile for non-Private-Shared-Anon-File" {
do_save_core "0x60" $non_private_shared_anon_file_core "0"
}
clean_restart $testfile
foreach item $all_anon_corefiles {
with_test_prefix "loading and testing corefile for [lindex $item 0]" {
do_load_and_test_core [subst [lindex $item 2]] [lindex $item 3] \
[lindex $item 4] [lindex $item 5] [lindex $item 6]
}
with_test_prefix "disassembling function main for [lindex $item 0]" {
test_disasm [subst [lindex $item 2]] $main_addr 0
}
}
with_test_prefix "loading and testing corefile for non-Private-Shared-Anon-File" {
test_disasm $non_private_shared_anon_file_core $main_addr 0
}
with_test_prefix "loading and testing corefile for non-Private-Shared-Anon-File with renamed binary" {
test_disasm $non_private_shared_anon_file_core $main_addr 1
}