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
|
# Copyright 2015-2017 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 } {
verbose -log "writing $filter_flag to /proc/<inferior pid>/coredump_filter"
gdb_test "p set_coredump_filter ($filter_flag)" " = 0"
# Generate a corefile.
gdb_gcore_cmd "$core" "save corefile"
}
proc do_load_and_test_core { core var working_var working_value } {
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.
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)"
}
# 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.
proc test_disasm { core address should_fail } {
global testfile hex
# Restart GDB without loading the binary.
with_test_prefix "no binary" {
gdb_exit
gdb_start
set core_loaded [gdb_core_cmd "$core" "load core"]
if { $core_loaded == -1 } {
fail "loading $core"
return
}
if { $should_fail == 1 } {
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]
# 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
#
# 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" }
{ "non-Shared-Anonymous" "0x7d" \
$non_shared_anon_core "shared_anon" \
"private_anon" "0x11" }
{ "DoNotDump" "0x33" \
$dont_dump_core "dont_dump" \
"shared_anon" "0x22" } }
# 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]]
}
}
with_test_prefix "saving corefile for non-Private-Shared-Anon-File" {
do_save_core "0x60" $non_private_shared_anon_file_core
}
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]
}
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 1
}
|