From patchwork Thu Jan 15 23:56:12 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Wielaard X-Patchwork-Id: 4710 Received: (qmail 25968 invoked by alias); 15 Jan 2015 23:56:22 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 25953 invoked by uid 89); 15 Jan 2015 23:56:20 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.7 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 15 Jan 2015 23:56:18 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t0FNuEjT022510 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 15 Jan 2015 18:56:14 -0500 Received: from bordewijk.wildebeest.org (ovpn-116-139.ams2.redhat.com [10.36.116.139]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t0FNuD1W013157 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 15 Jan 2015 18:56:14 -0500 Received: by bordewijk.wildebeest.org (Postfix, from userid 1000) id B2DEA813D800; Fri, 16 Jan 2015 00:56:12 +0100 (CET) Message-ID: <1421366172.26117.29.camel@bordewijk.wildebeest.org> Subject: Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally. From: Mark Wielaard To: Pedro Alves Cc: Stan Shebs , gdb-patches@sourceware.org Date: Fri, 16 Jan 2015 00:56:12 +0100 In-Reply-To: <548AC7C3.9020000@redhat.com> References: <1417099980-31834-1-git-send-email-mjw@redhat.com> <5480696F.1060308@redhat.com> <1418122161.18974.42.camel@bordewijk.wildebeest.org> <548745FD.40000@earthlink.net> <1418210696.5011.10.camel@bordewijk.wildebeest.org> <548AC7C3.9020000@redhat.com> Mime-Version: 1.0 On Fri, 2014-12-12 at 10:47 +0000, Pedro Alves wrote: > There are some tests for "return" in the testsuite -- return.exp or > return2.exp -- and at least one for "finish" -- finish.exp. I'd suggest > using these as inspiration. I added a test for answering no to the return query and and finish queries if they and the warning are there. They PASS with (GCC5) and without (older compilers) the new attribute. Also rebased the code to current master as attached. OK to commit? Thanks, Mark From ea5d7662c2bfa83d0de737f56956a88820643b61 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 9 Dec 2014 11:45:41 +0100 Subject: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally. Add a flag field is_noreturn to struct func_type. Make calling_convention a small bit field to not increase the size of the struct. Set is_noreturn if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram. Use this information to warn the user before doing a finish or return from a function that does not return normally to its caller. (gdb) finish warning: Function endless does not return normally. Try to finish anyway? (y or n) (gdb) return warning: Function does not return normally to caller. Make endless return now? (y or n) gdb/ChangeLog * dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from DW_AT_noreturn. * gdbtypes.h (struct func_type): Add is_noreturn field flag. Make calling_convention an 8 bit bit field. (TYPE_NO_RETURN): New macro. * infcmd.c (finish_command): Query if function does not return normally. * stack.c (return_command): Likewise. gdb/testsuite/ChangeLog * gdb.base/noreturn.c: New file. * gdb.base/noreturn.exp: New file. * gdb.base/noreturn_finish.c: New file. * gdb.base/noreturn_finish.exp: New file. include/ChangeLog * dwarf2.def (DW_AT_noreturn): New DWARF5 attribute. The dwarf2.h addition and the code to emit the new attribute is already in the gcc tree. --- gdb/ChangeLog | 11 ++++++ gdb/dwarf2read.c | 6 ++++ gdb/gdbtypes.h | 12 +++++-- gdb/infcmd.c | 9 ++++- gdb/stack.c | 8 +++-- gdb/testsuite/ChangeLog | 7 ++++ gdb/testsuite/gdb.base/noreturn.c | 13 +++++++ gdb/testsuite/gdb.base/noreturn.exp | 54 ++++++++++++++++++++++++++++++ gdb/testsuite/gdb.base/noreturn_finish.c | 14 ++++++++ gdb/testsuite/gdb.base/noreturn_finish.exp | 54 ++++++++++++++++++++++++++++++ include/ChangeLog | 4 +++ include/dwarf2.def | 2 ++ 12 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 gdb/testsuite/gdb.base/noreturn.c create mode 100644 gdb/testsuite/gdb.base/noreturn.exp create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.c create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5c45780..611008c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2015-01-15 Mark Wielaard + + * dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from + DW_AT_noreturn. + * gdbtypes.h (struct func_type): Add is_noreturn field flag. Make + calling_convention an 8 bit bit field. + (TYPE_NO_RETURN): New macro. + * infcmd.c (finish_command): Query if function does not return + normally. + * stack.c (return_command): Likewise. + 2015-01-15 Joel Brobecker GDB 7.8.2 released. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 96b2537..9d765c5 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14343,6 +14343,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) else TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal; + /* Record whether the function returns normally to its caller or not + if the DWARF producer set that information. */ + attr = dwarf2_attr (die, DW_AT_noreturn, cu); + if (attr && (DW_UNSND (attr) != 0)) + TYPE_NO_RETURN (ftype) = 1; + /* We need to add the subroutine type to the die immediately so we don't infinitely recurse when dealing with parameters declared as the same subroutine type. */ diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 7c06a4f..ba5c857 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -1019,9 +1019,16 @@ struct func_type { /* * The calling convention for targets supporting multiple ABIs. Right now this is only fetched from the Dwarf-2 - DW_AT_calling_convention attribute. */ + DW_AT_calling_convention attribute. The value is one of the + DW_CC enum dwarf_calling_convention constants. */ - unsigned calling_convention; + unsigned calling_convention : 8; + + /* * Whether this function normally returns to its caller. It is + set from the DW_AT_noreturn attribute if set on the + DW_TAG_subprogram. */ + + unsigned int is_noreturn : 1; /* * Only those DW_TAG_GNU_call_site's in this function that have DW_AT_GNU_tail_call set are linked in this list. Function @@ -1245,6 +1252,7 @@ extern void allocate_gnat_aux_type (struct type *); #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention +#define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_noreturn #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index) #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 7b26663..9a1fb8d 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1872,7 +1872,14 @@ finish_command (char *arg, int from_tty) if (execution_direction == EXEC_REVERSE) printf_filtered (_("Run back to call of ")); else - printf_filtered (_("Run till exit from ")); + { + if (function != NULL && TYPE_NO_RETURN (function->type) + && !query (_("warning: Function %s does not return normally.\n" + "Try to finish anyway? "), + SYMBOL_PRINT_NAME (function))) + error (_("Not confirmed.")); + printf_filtered (_("Run till exit from ")); + } print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0); } diff --git a/gdb/stack.c b/gdb/stack.c index 0201d0a..5f2a3dc 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty) confirmed = query (_("%sMake selected stack frame return now? "), query_prefix); else - confirmed = query (_("%sMake %s return now? "), query_prefix, - SYMBOL_PRINT_NAME (thisfun)); + { + if (TYPE_NO_RETURN (thisfun->type)) + warning ("Function does not return normally to caller."); + confirmed = query (_("%sMake %s return now? "), query_prefix, + SYMBOL_PRINT_NAME (thisfun)); + } if (!confirmed) error (_("Not confirmed")); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index a71ee98..ab027a7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-01-15 Mark Wielaard + + * gdb.base/noreturn.c: New file. + * gdb.base/noreturn.exp: New file. + * gdb.base/noreturn_finish.c: New file. + * gdb.base/noreturn_finish.exp: New file. + 2015-01-15 Joel Brobecker * gdb.ada/var_arr_attrs: New testcase. diff --git a/gdb/testsuite/gdb.base/noreturn.c b/gdb/testsuite/gdb.base/noreturn.c new file mode 100644 index 0000000..e39cf15 --- /dev/null +++ b/gdb/testsuite/gdb.base/noreturn.c @@ -0,0 +1,13 @@ +void __attribute__((noreturn)) +noreturn_func () +{ + while (1) + ; +} + +int +main () +{ + noreturn_func (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/noreturn.exp b/gdb/testsuite/gdb.base/noreturn.exp new file mode 100644 index 0000000..885642f --- /dev/null +++ b/gdb/testsuite/gdb.base/noreturn.exp @@ -0,0 +1,54 @@ +# Copyright 2015 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 . + +standard_testfile .c + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested noreturn.exp + return -1 +} + +proc noreturn_test { } { + global gdb_prompt + + if { ! [ runto_main ] } then { + untested noreturn.exp + return -1 + } + + gdb_test "break noreturn_func" "Breakpoint \[0123456789\].*" \ + "set break on noreturn_func" + gdb_test "continue" "Breakpoint.* noreturn_func.*" \ + "continue to noreturn_func" + + gdb_test_multiple "return" "return from noreturn_func" { + -re "warning: Function does not return normally to caller" { + verbose -log "saw warning" + exp_continue + } + -re "Make noreturn_func return now.*y or n. $" { + send_gdb "n\n" + exp_continue + } + -re "Not confirmed.*$gdb_prompt $" { + pass "noreturn_func return cancelled" + } + } +} + +clean_restart ${binfile} + +set timeout 30 +noreturn_test diff --git a/gdb/testsuite/gdb.base/noreturn_finish.c b/gdb/testsuite/gdb.base/noreturn_finish.c new file mode 100644 index 0000000..cd52769 --- /dev/null +++ b/gdb/testsuite/gdb.base/noreturn_finish.c @@ -0,0 +1,14 @@ +#include + +void __attribute__((noreturn)) +noreturn_func () +{ + abort (); +} + +int +main () +{ + noreturn_func (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/noreturn_finish.exp b/gdb/testsuite/gdb.base/noreturn_finish.exp new file mode 100644 index 0000000..d518826 --- /dev/null +++ b/gdb/testsuite/gdb.base/noreturn_finish.exp @@ -0,0 +1,54 @@ +# Copyright 2015 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 . + +standard_testfile .c + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested noreturn_finish.exp + return -1 +} + +proc noreturn_finish_test { } { + global gdb_prompt + + if { ! [ runto_main ] } then { + untested noreturn_finish.exp + return -1 + } + + gdb_test "break noreturn_func" "Breakpoint \[0123456789\].*" \ + "set break on noreturn_func" + gdb_test "continue" "Breakpoint.* noreturn_func.*" \ + "continue to noreturn_func" + + gdb_test_multiple "finish" "return from noreturn_func" { + -re "warning: Function noreturn_func does not return normally" { + verbose -log "saw warning" + exp_continue + } + -re "Try to finish anyway.*y or n.* $" { + send_gdb "n\n" + exp_continue + } + -re ".*$gdb_prompt $" { + pass "noreturn_func finish done" + } + } +} + +clean_restart ${binfile} + +set timeout 30 +noreturn_finish_test diff --git a/include/ChangeLog b/include/ChangeLog index 31f1e18..21b6ae6 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2015-01-15 Mark Wielaard + + * dwarf2.def (DW_AT_noreturn): New DWARF5 attribute. + 2015-01-14 Jan-Benedict Glaw * libiberty.h: Merge from GCC. diff --git a/include/dwarf2.def b/include/dwarf2.def index 5da3ae0..3aecdfc 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -306,6 +306,8 @@ DW_AT (DW_AT_data_bit_offset, 0x6b) DW_AT (DW_AT_const_expr, 0x6c) DW_AT (DW_AT_enum_class, 0x6d) DW_AT (DW_AT_linkage_name, 0x6e) +/* DWARF 5. */ +DW_AT (DW_AT_noreturn, 0x87) DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start. */ DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end. */ -- 1.8.3.1