From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27687 invoked by alias); 16 Nov 2008 01:14:26 -0000 Received: (qmail 27667 invoked by uid 22791); 16 Nov 2008 01:14:25 -0000 X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.45.13) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 16 Nov 2008 01:13:29 +0000 Received: from wpaz5.hot.corp.google.com (wpaz5.hot.corp.google.com [172.24.198.69]) by smtp-out.google.com with ESMTP id mAG1DRk5013370 for ; Sat, 15 Nov 2008 17:13:27 -0800 Received: from localhost (ruffy.corp.google.com [172.18.118.116]) by wpaz5.hot.corp.google.com with ESMTP id mAG1DQo8031511 for ; Sat, 15 Nov 2008 17:13:26 -0800 Received: by localhost (Postfix, from userid 67641) id DE3CB4125E1; Sat, 15 Nov 2008 17:13:25 -0800 (PST) To: gdb-patches@sourceware.org Subject: [RFA] fix popping of dummy frame if inferior gets signal with unwindonsignal Message-Id: <20081116011325.DE3CB4125E1@localhost> Date: Sun, 16 Nov 2008 08:28:00 -0000 From: dje@google.com (Doug Evans) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-11/txt/msg00405.txt.bz2 Hi. This fixes a bug where a signal in an inferior function call with unwindonsignal set doesn't remove the dummy frame from dummy_frame_stack. A testcase is included to exercise the bug. It also adds a comment to clear up something that was a bit confusing at first. The lone frame_pop isn't enough to properly restore program state, but things still work because registers (and thus stack) get restored from inf_status. Tested on i386-linux. Ok to check in? 2008-11-15 Doug Evans * infcall.c (call_function_by_hand): Properly pop the dummy frame if the inferior gets a signal and unwindonsignal is set. * gdb.base/unwindonsignal.c: New file. * gdb.base/unwindonsignal.exp: New file. Index: infcall.c =================================================================== RCS file: /cvs/src/src/gdb/infcall.c,v retrieving revision 1.105 diff -u -p -u -p -r1.105 infcall.c --- infcall.c 12 Nov 2008 00:39:28 -0000 1.105 +++ infcall.c 15 Nov 2008 22:08:54 -0000 @@ -357,7 +358,10 @@ call_function_by_hand (struct value *fun /* Save the caller's registers so that they can be restored once the callee returns. To allow nested calls the registers are (further down) pushed onto a dummy frame stack. Include a cleanup (which - is tossed once the regcache has been pushed). */ + is tossed once the regcache has been pushed). + NOTE: If the inferior gets a signal and unwindonsignal is set, + then this regcache is not used to restore target regs. Instead + the regcache in inf_status is used. */ caller_regcache = frame_save_as_regcache (frame); caller_regcache_cleanup = make_cleanup_regcache_xfree (caller_regcache); @@ -746,8 +749,12 @@ The program being debugged exited while /* The user wants the context restored. */ /* We must get back to the frame we were before the - dummy call. */ - frame_pop (get_current_frame ()); + dummy call. + NOTE: This discards the regcache recorded in the dummy frame + but that's ok, the registers will get restored from the + regcache in inf_status (which gets called by a cleanup). */ + dummy_frame_pop (dummy_id); + reinit_frame_cache (); /* FIXME: Insert a bunch of wrap_here; name can be very long if it's a C++ name with arguments and stuff. */ Index: testsuite/gdb.base/unwindonsignal.c =================================================================== RCS file: testsuite/gdb.base/unwindonsignal.c diff -N testsuite/gdb.base/unwindonsignal.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.base/unwindonsignal.c 16 Nov 2008 01:11:22 -0000 @@ -0,0 +1,49 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008 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 . */ + +/* Support program for testing handling of unwindonsignal. */ + +#include +#include +#include + +/* This function is handcalled from unwindonsignal.exp. */ + +void +gen_signal () +{ + /* According to sigall.exp, SIGABRT is always supported, + so try that first. */ +#ifdef SIGABRT + kill (getpid (), SIGABRT); +#endif +#ifdef SIGSEGV + kill (getpid (), SIGSEGV); +#endif + /* If we get here we couldn't generate a signal, tell dejagnu. */ + printf ("no signal\n"); +} + +int +main () +{ +#ifdef usestubs + set_debug_traps (); + breakpoint (); +#endif + return 0; +} Index: testsuite/gdb.base/unwindonsignal.exp =================================================================== RCS file: testsuite/gdb.base/unwindonsignal.exp diff -N testsuite/gdb.base/unwindonsignal.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.base/unwindonsignal.exp 16 Nov 2008 01:11:22 -0000 @@ -0,0 +1,94 @@ +# Copyright 2008 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 . + +if $tracelevel then { + strace $tracelevel +} + +if [target_info exists gdb,noinferiorio] { + verbose "Skipping unwindonsignal.exp because of no fileio capabilities." + continue +} + +set prms_id 0 +set bug_id 0 + +set testfile "unwindonsignal" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested unwindonsignal.exp + return -1 +} + +# Some targets can't do function calls, so don't even bother with this +# test. +if [target_info exists gdb,cannot_call_functions] { + setup_xfail "*-*-*" 2416 + fail "This target can not call functions" + continue +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if { ![runto_main] } { + fail "Can't run to main" + return 0 +} + +# Turn on unwindonsignal. +gdb_test "set unwindonsignal on" \ + "" \ + "setting unwindonsignal" +gdb_test "show unwindonsignal" \ + "Unwinding of stack .* is on." \ + "showing unwindonsignal" + +# Call function (causing the program to get a signal), and see if gdb handles +# it properly. +gdb_test_multiple "call gen_signal ()" \ + "unwindonsignal, inferior function call signaled" { + -re "\[\r\n\]*no signal\[\r\n\]+$gdb_prompt $" { + unsupported "unwindonsignal, inferior function call signaled" + return 0 + } + -re "\[\r\n\]*The program being debugged was signaled.*\[\r\n\]+$gdb_prompt $" { + pass "unwindonsignal, inferior function call signaled" + } +} + +# Verify the stack got unwound. +gdb_test "bt" \ + "#0 *main \\(.*\\) at .*" \ + "unwindonsignal, stack unwound" + +# Verify the dummy frame got removed from dummy_frame_stack. +gdb_test_multiple "maint print dummy-frames" \ + "unwindonsignal, dummy frame removed" { + -re "\[\r\n\]*.*stack=.*code=.*\[\r\n\]+$gdb_prompt $" { + fail "unwindonsignal, dummy frame removed" + } + -re "\[\r\n\]+$gdb_prompt $" { + pass "unwindonsignal, dummy frame removed" + } +} + +return 0