1# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2004, 2005, 2# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 3 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 3 of the License, or 7# (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17# This file is based on corefile.exp which was written by Fred 18# Fish. (fnf@cygnus.com) 19 20if $tracelevel then { 21 strace $tracelevel 22} 23 24 25# Are we on a target board? As of 2004-02-12, GDB didn't have a 26# mechanism that would let it efficiently access a remote corefile. 27 28if ![isnative] then { 29 untested "Remote system" 30 return 31} 32 33# Can the system run this test (in particular support sparse 34# corefiles)? On systems that lack sparse corefile support this test 35# consumes too many resources - gigabytes worth of disk space and and 36# I/O bandwith. 37 38if { [istarget "*-*-*bsd*"] 39 || [istarget "*-*-hpux*"] 40 || [istarget "*-*-solaris*"] 41 || [istarget "*-*-darwin*"] 42 || [istarget "*-*-cygwin*"] } { 43 untested "Kernel lacks sparse corefile support (PR gdb/1551)" 44 return 45} 46 47# This testcase causes too much stress (in terms of memory usage) 48# on certain systems... 49if { [istarget "*-*-*irix*"] } { 50 untested "Testcase too stressful for this system" 51 return 52} 53 54set testfile "bigcore" 55set srcfile ${testfile}.c 56set binfile ${objdir}/${subdir}/${testfile} 57set corefile ${objdir}/${subdir}/${testfile}.corefile 58 59if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { 60 untested bigcore.exp 61 return -1 62} 63 64# Run GDB on the bigcore program up-to where it will dump core. 65 66gdb_exit 67gdb_start 68gdb_reinitialize_dir $srcdir/$subdir 69gdb_load ${binfile} 70gdb_test_no_output "set print sevenbit-strings" 71gdb_test_no_output "set width 0" 72 73if { ![runto_main] } then { 74 gdb_suppress_tests; 75} 76set print_core_line [gdb_get_line_number "Dump core"] 77gdb_test "tbreak $print_core_line" 78gdb_test continue ".*print_string.*" 79gdb_test next ".*0 = 0.*" 80 81# Traverse part of bigcore's linked list of memory chunks (forward or 82# backward), saving each chunk's address. 83 84proc extract_heap { dir } { 85 global gdb_prompt 86 global expect_out 87 set heap "" 88 set test "extract ${dir} heap" 89 set lim 0 90 gdb_test_multiple "print heap.${dir}" "$test" { 91 -re " = \\(struct list \\*\\) 0x0.*$gdb_prompt $" { 92 pass "$test" 93 } 94 -re " = \\(struct list \\*\\) (0x\[0-9a-f\]*).*$gdb_prompt $" { 95 set heap [concat $heap $expect_out(1,string)] 96 if { $lim >= 200 } { 97 pass "$test (stop at $lim)" 98 } else { 99 incr lim 100 send_gdb "print \$.${dir}\n" 101 exp_continue 102 } 103 } 104 -re ".*$gdb_prompt $" { 105 fail "$test (entry $lim)" 106 } 107 timeout { 108 fail "$test (timeout)" 109 } 110 } 111 return $heap; 112} 113set next_heap [extract_heap next] 114set prev_heap [extract_heap prev] 115 116# Save the total allocated size within GDB so that we can check 117# the core size later. 118gdb_test_no_output "set \$bytes_allocated = bytes_allocated" "save heap size" 119 120# Now create a core dump 121 122# Rename the core file to "TESTFILE.corefile" rather than just "core", 123# to avoid problems with sys admin types that like to regularly prune 124# all files named "core" from the system. 125 126# Some systems append "core" to the name of the program; others append 127# the name of the program to "core"; still others (like Linux, as of 128# May 2003) create cores named "core.PID". 129 130# Save the process ID. Some systems dump the core into core.PID. 131set test "grab pid" 132gdb_test_multiple "info program" $test { 133 -re "child process (\[0-9\]+).*$gdb_prompt $" { 134 set inferior_pid $expect_out(1,string) 135 pass $test 136 } 137 -re "$gdb_prompt $" { 138 set inferior_pid unknown 139 pass $test 140 } 141} 142 143# Dump core using SIGABRT 144set oldtimeout $timeout 145set timeout 600 146gdb_test "signal SIGABRT" "Program terminated with signal SIGABRT, .*" 147set timeout $oldtimeout 148 149# Find the corefile 150set file "" 151foreach pat [list core.${inferior_pid} ${testfile}.core core] { 152 set names [glob -nocomplain $pat] 153 if {[llength $names] == 1} { 154 set file [lindex $names 0] 155 remote_exec build "mv $file $corefile" 156 break 157 } 158} 159 160if { $file == "" } { 161 untested "Can't generate a core file" 162 return 0 163} 164 165# Check that the corefile is plausibly large enough. We're trying to 166# detect the case where the operating system has truncated the file 167# just before signed wraparound. TCL, unfortunately, has a similar 168# problem - so use catch. It can handle the "bad" size but not 169# necessarily the "good" one. And we must use GDB for the comparison, 170# similarly. 171 172if {[catch {file size $corefile} core_size] == 0} { 173 set core_ok 0 174 gdb_test_multiple "print \$bytes_allocated < $core_size" "check core size" { 175 -re " = 1\r\n$gdb_prompt $" { 176 pass "check core size" 177 set core_ok 1 178 } 179 -re " = 0\r\n$gdb_prompt $" { 180 pass "check core size" 181 set core_ok 0 182 } 183 } 184} { 185 # Probably failed due to the TCL build having problems with very 186 # large values. Since GDB uses a 64-bit off_t (when possible) it 187 # shouldn't have this problem. Assume that things are going to 188 # work. Without this assumption the test is skiped on systems 189 # (such as i386 GNU/Linux with patched kernel) which do pass. 190 pass "check core size" 191 set core_ok 1 192} 193if {! $core_ok} { 194 untested "check core size (system does not support large corefiles)" 195 return 0 196} 197 198# Now load up that core file 199 200set test "load corefile" 201gdb_test_multiple "core $corefile" "$test" { 202 -re "A program is being debugged already. Kill it. .y or n. " { 203 send_gdb "y\n" 204 exp_continue 205 } 206 -re "Core was generated by.*$gdb_prompt $" { 207 pass "$test" 208 } 209} 210 211# Finally, re-traverse bigcore's linked list, checking each chunk's 212# address against the executable. Don't use gdb_test_multiple as want 213# only one pass/fail. Don't use exp_continue as the regular 214# expression involving $heap needs to be re-evaluated for each new 215# response. 216 217proc check_heap { dir heap } { 218 global gdb_prompt 219 set test "check ${dir} heap" 220 set ok 1 221 set lim 0 222 send_gdb "print heap.${dir}\n" 223 while { $ok } { 224 gdb_expect { 225 -re " = \\(struct list \\*\\) [lindex $heap $lim].*$gdb_prompt $" { 226 if { $lim >= [llength $heap] } { 227 pass "$test" 228 set ok 0 229 } else { 230 incr lim 231 send_gdb "print \$.${dir}\n" 232 } 233 } 234 -re ".*$gdb_prompt $" { 235 fail "$test (address [lindex $heap $lim])" 236 set ok 0 237 } 238 timeout { 239 fail "$test (timeout)" 240 set ok 0 241 } 242 } 243 } 244} 245 246check_heap next $next_heap 247check_heap prev $prev_heap 248