diff options
author | Andrew Cagney <cagney@redhat.com> | 2004-11-03 14:46:18 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2004-11-03 14:46:18 +0000 |
commit | a1e167bbea08cc5f2f846de9f556c73e2c688e73 (patch) | |
tree | 869049b3c7630ba602ff164607ca538216f90c0b /gdb/testsuite/gdb.base | |
parent | 4577593c76eba3ba0a0b5078e21e6a0b7beb21e2 (diff) | |
download | gdb-a1e167bbea08cc5f2f846de9f556c73e2c688e73.zip gdb-a1e167bbea08cc5f2f846de9f556c73e2c688e73.tar.gz gdb-a1e167bbea08cc5f2f846de9f556c73e2c688e73.tar.bz2 |
2004-11-03 Andrew Cagney <cagney@gnu.org>
* gdb.base/savedregs.exp, gdb.base/savedregs.c: New files.
Diffstat (limited to 'gdb/testsuite/gdb.base')
-rw-r--r-- | gdb/testsuite/gdb.base/savedregs.c | 56 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/savedregs.exp | 160 |
2 files changed, 216 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.base/savedregs.c b/gdb/testsuite/gdb.base/savedregs.c new file mode 100644 index 0000000..6709eb1 --- /dev/null +++ b/gdb/testsuite/gdb.base/savedregs.c @@ -0,0 +1,56 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <sys/time.h> + +static volatile int done; + +extern int +callee (int param) +{ + return param * done + 1; +} + +extern int +caller (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) +{ + return callee (a1 << a2 * a3 / a4 + a6 & a6 % a7 - a8) + done; +} + +static void +catcher (int sig) +{ + done = 1; +} /* handler */ + +static void +thrower (void) +{ + *(char *)0 = 0; +} + +main () +{ + signal (SIGSEGV, catcher); + thrower (); +} diff --git a/gdb/testsuite/gdb.base/savedregs.exp b/gdb/testsuite/gdb.base/savedregs.exp new file mode 100644 index 0000000..92f14a2 --- /dev/null +++ b/gdb/testsuite/gdb.base/savedregs.exp @@ -0,0 +1,160 @@ +# Copyright 2004 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This test is to check that a frame's "info frame", especially the +# saved registers list, doesn't change while that frame isn't current. + +# It uses the program savedregs.c to construct a somewhat warped +# backtrace (contains both signal and dummy frames) and then, at each +# step checks that non-inner frames have consistent "info frame" +# output. Note that a frame's "info frame" can only be captured after +# it is non-current (made a call, interrupted, ...), this is because +# instructions executed to perform the call may affect "info frame" +# output. + +if [target_info exists gdb,nosignals] { + verbose "Skipping savedregs.exp because of nosignals." + continue +} + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile savedregs +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "Couldn't compile ${module}.c" + return -1 +} + +# get things started +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Advance to main +if { ![runto_main] } { + gdb_suppress_tests; +} + +proc process_saved_regs { current inner outer } { + global gdb_prompt + global expect_out + global saved_regs + + # Skip the CURRENT frame. + + set level 1 + + # Run over the list of INNER frames capturing the "info frame" + # output for each. Both dummy and sigtramp frames need to be + # handled specially: they do not yet have correct function names; + # and for dummy frames won't have saved registers. If there's a + # problem, fail but capture the output anyway, hopefully later + # "info frame" requests for that same frame will at least fail in + # a consistent manner (stops propogated fails). + + foreach func $inner { + set saved_regs($func) "error" + set test "Get $func info frame" + # Both dummy and sigtramp frames have problems. + switch $func { + dummy { + # Dummy frame's do not have saved registers, and do + # not print <dummy>. + set pat "Stack frame at .* in .*" + } + sigtramp { + # Sigtramp frames don't yet print <signal trampoline>. + set pat "Stack frame at .* in .* .* Saved registers:.*" + } + default { + set pat "Stack frame at .* in $func .* Saved registers:.*" + } + } + # If the "info frame" barf, capture the output anyway so that + # it does not cascade further failures. + gdb_test_multiple "info frame $level" "$test" { + -re "($pat)$gdb_prompt " { + set saved_regs($func) "$expect_out(1,string)" + pass "$test" + } + -re "(Stack frame at .*)$gdb_prompt " { + set saved_regs($func) "$expect_out(1,string)" + fail "$test" + } + -re "(Cannot access .*)$gdb_prompt " { + set saved_regs($func) "$expect_out(1,string)" + fail "$test" + } + } + incr level + } + + # Now iterate through the list of OUTER frames checking that the + # "info frame" output from each still matches what was captured + # during an early query. To avoid cascading failures, checking is + # abandoned after the first failure. The assumption is that, + # since frames outer to the botched frame rely on the botched + # frame's info, those more outer frames are also botched. Besides + # we've got the failure we're after. + + set ok 1 + foreach func $outer { + set test [concat "Check $func info frame; stack contains" \ + $current $inner $outer] + if $ok { + set ok 0 + set pat [string_to_regexp "$saved_regs($func)"] + gdb_test_multiple "info frame $level" "$test" { + -re "$pat$gdb_prompt " { + pass "$test" + set ok 1 + } + } + } { + pass "$test (skipped)" + } + incr level + } +} + + +# Continue to the signal thrower, capture main's saved-reg info. +gdb_test "advance thrower" "thrower .* at .*" +process_saved_regs thrower { main } { } + +# Continue to the signal catcher, check main's saved-reg info, capture +# catcher's saved-reg info. +gdb_test "handle SIGSEGV pass print nostop" +gdb_test "advance catcher" "catcher .* at .*" +process_saved_regs catcher { sigtramp thrower } { main } + +# Breakpoint at and call the caller function, saved-regs of main and +# catcher, capture caller's registers. +gdb_test "break caller" +gdb_test "call caller (1,2,3,4,5,6,7,8)" +process_saved_regs caller { dummy catcher } { sigtramp thrower main } + +# Run to callee, again check everything. +gdb_test "advance callee" "callee .* at .*" +process_saved_regs callee { caller } { dummy catcher sigtramp thrower main } |