From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7042 invoked by alias); 30 Jun 2004 15:25:21 -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 7033 invoked from network); 30 Jun 2004 15:25:20 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 30 Jun 2004 15:25:20 -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 i5UFPJe3017456 for ; Wed, 30 Jun 2004 11:25:19 -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 i5UFPJ012151; Wed, 30 Jun 2004 11:25:19 -0400 Received: from redhat.com (localhost [127.0.0.1]) by localhost.redhat.com (Postfix) with ESMTP id AEF372B9D; Wed, 30 Jun 2004 11:25:06 -0400 (EDT) Message-ID: <40E2DB52.5060702@redhat.com> Date: Wed, 30 Jun 2004 15:25: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: Michael Elizabeth Chastain Cc: gdb-patches@sources.redhat.com Subject: Re: [rfa] New test sigbpt.{c,exp} References: <20040630035317.5BEF84B104@berman.michael-chastain.com> In-Reply-To: <20040630035317.5BEF84B104@berman.michael-chastain.com> Content-Type: multipart/mixed; boundary="------------050203000506070607060506" X-SW-Source: 2004-06/txt/msg00692.txt.bz2 This is a multi-part message in MIME format. --------------050203000506070607060506 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2130 > Mostly okay, but there's too many duplicated test names. > > % cat gdb.sum | sort | uniq -c | sort -rn > 8 PASS: gdb.base/sigbpt.exp: pass SIGSEGV for no breakpoints > 7 PASS: gdb.base/sigbpt.exp: rerun to main > 4 PASS: gdb.base/sigbpt.exp: continue to keeper for no breakpoints > 3 PASS: gdb.base/sigbpt.exp: stepi fault for no breakpoints > 3 PASS: gdb.base/sigbpt.exp: continue to breakpoint at fault for no breakpoints > 2 PASS: gdb.base/sigbpt.exp: pass SIGSEGV for bp before segv > 2 PASS: gdb.base/sigbpt.exp: pass SIGSEGV for bp before and at segv > 2 PASS: gdb.base/sigbpt.exp: pass SIGSEGV for bp at segv > > Can you make more of the test names more unique? Oops, I thought I'd covered that. Try the attached. > Last, a typo: > > set test "Verify that SIGSEGV occures at the last STEPI insn" Fixed. > Also I'm getting four FAIL results (native i686-pc-linux-gnu, > red hat 8.0, gcc 3.3.3, binutils 2.15, glibc 2.2.93-5-rh, > kernel 2.4.8-14-rh). > > FAIL: gdb.base/sigbpt.exp: stepi out of handler for no breakpoints (executed fault insn) > FAIL: gdb.base/sigbpt.exp: stepi out of handler for bp before segv (executed fault insn) > FAIL: gdb.base/sigbpt.exp: stepi out of handler for bp at segv > FAIL: gdb.base/sigbpt.exp: stepi out of handler for bp before and at segv > > Is that a fault of the system under test, or a fault of the test script? > Your message implies the former (because it passes with a hacked kernel), > but I just want to check. "yes", so far I've identified the following: - h/w single-step #1 - kernel The kernel is issuing two-for-one instructions when single stepping a system call. - h/w single-step #2 - kernel The kernel is continuing, instead of single-stepping, the sigreturn system call. - s/w single-step #1 - gdb GDB's OSABI software single-step code doesn't know how to single-step sigreturn. We, GDB, can work around the kernel bugs by using software single step. But that means fixing software single-step. Are there [get_kernel_info] and [get_software_singlestep] testsuite calls? Andrew --------------050203000506070607060506 Content-Type: text/plain; name="diffs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="diffs" Content-length: 10835 2004-06-18 Andrew Cagney * gdb.base/sigbpt.exp, gdb.base/sigbpt.c: New test. Index: gdb.base/sigbpt.c =================================================================== RCS file: gdb.base/sigbpt.c diff -N gdb.base/sigbpt.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gdb.base/sigbpt.c 30 Jun 2004 14:58:02 -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.base/sigbpt.exp =================================================================== RCS file: gdb.base/sigbpt.exp diff -N gdb.base/sigbpt.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gdb.base/sigbpt.exp 30 Jun 2004 14:58:02 -0000 @@ -0,0 +1,253 @@ +# 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. Record +# the address of each single-step instruction (up to and including the +# instruction that causes the SIGSEGV) in bowler_addrs, and the address +# of the actual SIGSEGV in segv_addr. + +set bowler_addrs 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_addr $expect_out(1,string) + pass "$test" + } + -re " .*pc *(0x\[0-9a-f\]*).*bowler.*$gdb_prompt $" { + set bowler_addrs [concat $expect_out(1,string) $bowler_addrs] + send_gdb "stepi\n" + exp_continue + } +} + +# Now record the address of the instruction following the faulting +# instruction in bowler_addrs. + +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 bowler_addrs [concat $expect_out(2,string) $bowler_addrs] + pass "$test" + } +} + +# Procedures for returning the address of the instruction before, at +# and after, the faulting instruction. + +proc before_segv { } { + global bowler_addrs + return [lindex $bowler_addrs 2] +} + +proc at_segv { } { + global bowler_addrs + return [lindex $bowler_addrs 1] +} + +proc after_segv { } { + global bowler_addrs + return [lindex $bowler_addrs 0] +} + +# Check that the address table and SIGSEGV correspond. + +set test "Verify that SIGSEGV occurs at the last STEPI insn" +if {[string compare $segv_addr [at_segv]] == 0} { + pass "$test" +} else { + fail "$test ($segv_addr [at_segv])" +} + +# Check that the inferior is correctly single stepped all the way back +# to a faulting instruction. + +proc stepi_out { name 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; $name" + gdb_test "continue" "keeper.*" "continue to keeper; $name" + gdb_test "handle SIGSEGV stop print nopass" "" "nopass SIGSEGV; $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]; $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; $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 *[at_segv] .*bowler.*$gdb_prompt $" { + pass "$test (at breakpoint)" + } + -re "Breakpoint.*pc *[after_segv] .*bowler.*$gdb_prompt $" { + fail "$test (executed breakpoint)" + } + -re "pc *[at_segv] .*bowler.*$gdb_prompt $" { + pass "$test" + } + -re "pc *[after_segv] .*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]; $name" + } +} + +# Let a signal handler exit, returning to a breakpoint instruction +# inserted at the original fault instruction. Check that the +# breakpoint is hit, and that single stepping off that breakpoint +# executes the underlying fault instruction causing a SIGSEGV. + +proc cont_out { name 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; $name" + gdb_test "continue" "keeper.*" "continue to keeper; $name" + gdb_test "handle SIGSEGV stop print nopass" "" "nopass SIGSEGV; $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 "*[at_segv]"] + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "break [lindex $args $i]" "Breakpoint.*" \ + "set breakpoint $i of [llength $args]; $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 *[at_segv] .*" \ + "continue to breakpoint at fault; $name" + + # Now single step the faulted instrction at that breakpoint. + gdb_test "stepi" \ + "Program received signal SIGSEGV.*pc *[at_segv] .*" \ + "stepi fault; $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]; $name" + } + +} + + + +# Try to confuse DECR_PC_AFTER_BREAK architectures by scattering +# breakpoints around the faulting address. In all cases the inferior +# should single-step out of the signal trampoline halting (but not +# executing) the fault instruction. + +stepi_out "stepi" +stepi_out "stepi bp before segv" "*[before_segv]" +stepi_out "stepi bp at segv" "*[at_segv]" +stepi_out "stepi bp before and at segv" "*[at_segv]" "*[before_segv]" + + +# Try to confuse DECR_PC_AFTER_BREAK architectures by scattering +# breakpoints around the faulting address. In all cases the inferior +# should exit the signal trampoline halting at the breakpoint that +# replaced the fault instruction. +cont_out "cont" +cont_out "cont bp after segv" "*[before_segv]" +cont_out "cont bp before and after segv" "*[before_segv]" "*[after_segv]" --------------050203000506070607060506--