summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base/coredump-filter.exp
blob: 739ff09353b170ea42de08e0f52bcb56df0697a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# 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] } {
    untested "could not run to 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
}