From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4713 invoked by alias); 29 Jun 2004 23:44:12 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 4665 invoked from network); 29 Jun 2004 23:44:12 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 29 Jun 2004 23:44:12 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.10/8.12.10) with ESMTP id i5TNiBe1022099 for ; Tue, 29 Jun 2004 19:44:11 -0400 Received: from localhost.redhat.com (porkchop.devel.redhat.com [172.16.58.2]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id i5TNiB019141 for ; Tue, 29 Jun 2004 19:44:11 -0400 Received: from redhat.com (localhost [127.0.0.1]) by localhost.redhat.com (Postfix) with ESMTP id 618322B9D for ; Tue, 29 Jun 2004 19:43:58 -0400 (EDT) Message-ID: <40E1FEBE.10007@redhat.com> Date: Tue, 29 Jun 2004 23:44:00 -0000 From: Andrew Cagney User-Agent: Mozilla/5.0 (X11; U; NetBSD macppc; en-GB; rv:1.4.1) Gecko/20040217 MIME-Version: 1.0 To: gdb-patches@sources.redhat.com Subject: [rfa] New test sigbpt.{c,exp} Content-Type: multipart/mixed; boundary="------------080108030807060102090407" X-SW-Source: 2004-06/txt/msg00685.txt.bz2 This is a multi-part message in MIME format. --------------080108030807060102090407 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 335 Hello, This test checks for interaction between signal trampolines, single-step and breakpoints. If nothing else, it highlights broken kernel code - given a system call, both the system call instruction, and the one following are executed. I've a hacked i386 (Linux) and PPC (NetBSD) kernel where all the tests pass. ok? Andrew --------------080108030807060102090407 Content-Type: text/plain; name="diffs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="diffs" Content-length: 10379 2004-06-18 Andrew Cagney * gdb.base/sigbpt.exp, gdb.base/sigbpt.c: New test. Index: ./gdb/testsuite/gdb.base/sigbpt.c =================================================================== RCS file: ./gdb/testsuite/gdb.base/sigbpt.c diff -N ./gdb/testsuite/gdb.base/sigbpt.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./gdb/testsuite/gdb.base/sigbpt.c 23 Jun 2004 13:52:43 -0000 @@ -0,0 +1,53 @@ +/* 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 +#include +#include + +extern void +keeper (int sig) +{ +} + +volatile long v1 = 0; +volatile long v2 = 0; +volatile long v3 = 0; + +extern long +bowler (void) +{ + /* Try to read address zero. Do it in a slightly convoluted way so + that more than one instruction is used. */ + return *(char *) (v1 + v2 + v3); +} + +int +main () +{ + static volatile int i; + + struct sigaction act; + memset (&act, 0, sizeof act); + act.sa_handler = keeper; + sigaction (SIGSEGV, &act, NULL); + + bowler (); + return 0; +} Index: ./gdb/testsuite/gdb.base/sigbpt.exp =================================================================== RCS file: ./gdb/testsuite/gdb.base/sigbpt.exp diff -N ./gdb/testsuite/gdb.base/sigbpt.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./gdb/testsuite/gdb.base/sigbpt.exp 23 Jun 2004 13:52:43 -0000 @@ -0,0 +1,231 @@ +# 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. + +# Check that GDB can and only executes single instructions when +# stepping through a sequence of breakpoints interleaved by signal. + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "sigbpt" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# +# Run to `main' where we begin our tests. +# + +if ![runto_main] then { + gdb_suppress_tests +} + +# If we can examine what's at memory address 0, it is possible that we +# could also execute it. This could probably make us run away, +# executing random code, which could have all sorts of ill effects, +# especially on targets without an MMU. Don't run the tests in that +# case. + +send_gdb "x 0\n" +gdb_expect { + -re "0x0:.*Cannot access memory at address 0x0.*$gdb_prompt $" { } + -re "0x0:.*Error accessing memory address 0x0.*$gdb_prompt $" { } + -re ".*$gdb_prompt $" { + untested "Memory at address 0 is possibly executable" + return + } +} + +gdb_test "break keeper" + +# Run to bowler, and then single step until there's a SIGSEGV. Gather +# the address of every stepped instruction in bowler (step_insn), and +# the address of the SIGSEGV (segv_insn). + +set step_insn bowler +gdb_test {display/i $pc} +gdb_test "advance *bowler" "bowler.*" "advance to the bowler" +set test "stepping to SIGSEGV" +gdb_test_multiple "stepi" "$test" { + -re "Program received signal SIGSEGV.*pc *(0x\[0-9a-f\]*).*$gdb_prompt $" { + set segv_insn $expect_out(1,string) + pass "$test" + } + -re " .*pc *(0x\[0-9a-f\]*).*bowler.*$gdb_prompt $" { + set step_insn [concat $expect_out(1,string) $step_insn] + send_gdb "stepi\n" + exp_continue + } +} + +# Now find the address of the instruction after the faulting +# instruction. + +set test "get insn after fault" +gdb_test_multiple {x/2i $pc} "$test" { + -re "(0x\[0-9a-f\]*).*bowler.*(0x\[0-9a-f\]*).*bowler.*$gdb_prompt $" { + set step_insn [concat $expect_out(2,string) $step_insn] + pass "$test" + } +} + +set test "Verify that SIGSEGV occures at the last STEPI insn" +if {[string compare $segv_insn [lindex $step_insn 1]] == 0} { + pass "$test" +} else { + fail "$test ($segv_insn [lindex $step_insn 1])" +} + +# Check that the inferior is correctly single stepped all the way back +# to a faulting instruction. + +proc stepi_out { name step_insn args } { + global gdb_prompt + + # Set SIGSEGV to pass+nostop and then run the inferior all the way + # through to the signal handler. With the handler is reached, + # disable SIGSEGV, ensuring that further signals stop the + # inferior. Stops a SIGSEGV infinite loop when a broke system + # keeps re-executing the faulting instruction. + rerun_to_main + gdb_test "handle SIGSEGV nostop print pass" "" "pass SIGSEGV for $name" + gdb_test "continue" "keeper.*" "continue to keeper for $name" + gdb_test "handle SIGSEGV stop print nopass" "" "pass SIGSEGV for $name" + + # Insert all the breakpoints. To avoid the need to step over + # these instructions, this is delayed until after the keeper has + # been reached. + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "break [lindex $args $i]" "Breakpoint.*" \ + "set breakpoint $i of [llength $args] for $name" + } + + # Single step our way out of the keeper, through the signal + # trampoline, and back to the instruction that faulted. + set test "stepi out of handler for $name" + gdb_test_multiple "stepi" "$test" { + -re "keeper.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "signal handler.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "Program received signal SIGSEGV.*$gdb_prompt $" { + fail "$test (executed fault insn)" + } + -re "Breakpoint.*pc *[lindex $step_insn 1] .*bowler.*$gdb_prompt $" { + pass "$test (at breakpoint)" + } + -re "Breakpoint.*pc *[lindex $step_insn 0] .*bowler.*$gdb_prompt $" { + fail "$test (executed breakpoint)" + } + -re "pc *[lindex $step_insn 1] .*bowler.*$gdb_prompt $" { + pass "$test" + } + -re "pc *[lindex $step_insn 0] .*bowler.*$gdb_prompt $" { + fail "$test (skipped fault insn)" + } + } + + # Clear any breakpoints + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "clear [lindex $args $i]" "Deleted .*" \ + "clear breakpoint $i of [llength $args] for $name" + } +} + +stepi_out "no breakpoints" $step_insn + +# Try to confuse DECR_PC_AFTER_BREAK architectures by scattering +# breakpoints around the faulting address. + +stepi_out "bp before segv" $step_insn \ + "*[lindex $step_insn 2]" +stepi_out "bp at segv" $step_insn \ + "*[lindex $step_insn 1]" +stepi_out "bp before and at segv" $step_insn \ + "*[lindex $step_insn 1]" "*[lindex $step_insn 2]" + +# Let a signal handler exit, returning to a breakpoint instruction. +# Check that the breakpoint is hit, and then single stepping triggers +# a further SIGSEGV. + +proc cont_to_bp { name step_insn args } { + global gdb_prompt + + # Set SIGSEGV to pass+nostop and then run the inferior all the way + # through to the signal handler. With the handler is reached, + # disable SIGSEGV, ensuring that further signals stop the + # inferior. Stops a SIGSEGV infinite loop when a broke system + # keeps re-executing the faulting instruction. + rerun_to_main + gdb_test "handle SIGSEGV nostop print pass" "" "pass SIGSEGV for $name" + gdb_test "continue" "keeper.*" "continue to keeper for $name" + gdb_test "handle SIGSEGV stop print nopass" "" "pass SIGSEGV for $name" + + # Insert all the breakpoints. To avoid the need to step over + # these instructions, this is delayed until after the keeper has + # been reached. Always set a breakpoint at the signal trampoline + # instruction. + set args [concat $args "*[lindex $step_insn 1]"] + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "break [lindex $args $i]" "Breakpoint.*" \ + "set breakpoint $i of [llength $args] for $name" + } + + # Let the handler return, it should "appear to hit" the breakpoint + # inserted at the faulting instruction. Note that the breakpoint + # instruction wasn't executed, rather the inferior was SIGTRAPed + # with the PC at the breakpoint. + gdb_test "continue" "Breakpoint.*pc *[lindex $step_insn 1] .*" \ + "continue to breakpoint at fault for $name" + + # Now single step the faulted instrction at that breakpoint. + gdb_test "stepi" \ + "Program received signal SIGSEGV.*pc *[lindex $step_insn 1] .*" \ + "stepi fault for $name" + + # Clear any breakpoints + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "clear [lindex $args $i]" "Deleted .*" \ + "clear breakpoint $i of [llength $args] for $name" + } + +} + +cont_to_bp "no breakpoints" $step_insn + +# Try to confuse DECR_PC_AFTER_BREAK architectures by scattering +# breakpoints around the faulting address. +cont_to_bp "no breakpoints" $step_insn \ + "*[lindex $step_insn 2]" +cont_to_bp "no breakpoints" $step_insn \ + "*[lindex $step_insn 2]" "*[lindex $step_insn 0]" --------------080108030807060102090407--