From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26078 invoked by alias); 29 Nov 2011 15:02:29 -0000 Received: (qmail 26068 invoked by uid 22791); 29 Nov 2011 15:02:25 -0000 X-SWARE-Spam-Status: No, hits=-0.0 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,TO_NO_BRKTS_DIRECT X-Spam-Check-By: sourceware.org Received: from gbenson.demon.co.uk (HELO gbenson.demon.co.uk) (80.177.220.214) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 29 Nov 2011 15:02:03 +0000 Date: Tue, 29 Nov 2011 15:02:00 -0000 From: Gary Benson To: gdb-patches@sourceware.org Subject: [RFA] Allow setting breakpoints on inline functions (PR 10738) Message-ID: <20111129150200.GB3425@redhat.com> Mail-Followup-To: gdb-patches@sourceware.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="H+4ONPRPur6+Ovig" Content-Disposition: inline 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: 2011-11/txt/msg00814.txt.bz2 --H+4ONPRPur6+Ovig Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 463 Hi all, This patch, which applies on top of Tom's ambiguous linespec work, allows you to set breakpoints on inlined functions. Although it can't be committed until Tom's stuff goes in, I'm posting it for feedback now. I'm particularly interested in how this affects users of languages other than C. I'm also interested in feedback about the tests I've written, since this is the first time I've worked on the testsuite. Thanks, Gary -- http://gbenson.net/ --H+4ONPRPur6+Ovig Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=patch Content-length: 8831 2011-11-29 Gary Benson PR breakpoints/10738 * dwarf2read.c (struct partial_die_info): New member may_be_inlined. (read_partial_die): Set may_be_inlined where appropriate. (add_partial_subprogram): Add partial symbols for partial DIEs that may be inlined. (new_symbol_full): Add inlined subroutines to the static symbol table. 2011-11-29 Gary Benson PR breakpoints/10738 * gdb.opt/inline-break.exp: New file. * gdb.opt/inline-break.c: Likewise. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 145c8d0..ee89286 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -578,6 +578,7 @@ struct partial_die_info unsigned int has_type : 1; unsigned int has_specification : 1; unsigned int has_pc_info : 1; + unsigned int may_be_inlined : 1; /* Flag set if the SCOPE field of this structure has been computed. */ @@ -4285,6 +4286,10 @@ add_partial_subprogram (struct partial_die_info *pdi, pdi->highpc - 1 + baseaddr, cu->per_cu->v.psymtab); } + } + + if (pdi->has_pc_info || (!pdi->is_external && pdi->may_be_inlined)) + { if (!pdi->is_declaration) /* Ignore subprogram DIEs that do not have a name, they are illegal. Do not emit a complaint at this point, we will @@ -9925,6 +9930,11 @@ read_partial_die (struct partial_die_info *part_die, language_of_main = language_fortran; } break; + case DW_AT_inline: + if (DW_UNSND (&attr) == DW_INL_inlined + || DW_UNSND (&attr) == DW_INL_declared_inlined) + part_die->may_be_inlined = 1; + break; default: break; } @@ -11800,8 +11810,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, finish_block. */ SYMBOL_CLASS (sym) = LOC_BLOCK; SYMBOL_INLINED (sym) = 1; - /* Do not add the symbol to any lists. It will be found via - BLOCK_FUNCTION from the blockvector. */ + list_to_add = &file_symbols; break; case DW_TAG_template_value_param: suppress_add = 1; diff --git a/gdb/testsuite/gdb.opt/inline-break.c b/gdb/testsuite/gdb.opt/inline-break.c new file mode 100644 index 0000000..7e1807f --- /dev/null +++ b/gdb/testsuite/gdb.opt/inline-break.c @@ -0,0 +1,154 @@ +/* Copyright (C) 2011 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 . */ + +#ifdef __GNUC__ +#define ATTR __attribute__((always_inline)) +#else +#define ATTR +#endif + +/* A static inlined function that is called once. */ + +static inline ATTR int +func1 (int x) +{ + return x * 23; +} + +/* A non-static inlined function that is called once. */ + +inline ATTR int +func2 (int x) +{ + return x * 17; +} + +/* A static inlined function that calls another static inlined + function. */ + +static inline ATTR int +func3b (int x) +{ + return x < 14 ? 1 : 2; +} + +static inline ATTR int +func3a (int x) +{ + return func3b (x * 23); +} + +/* A non-static inlined function that calls a static inlined + function. */ + +static inline ATTR int +func4b (int x) +{ + return x < 13 ? 1 : 2; +} + +inline ATTR int +func4a (int x) +{ + return func4b (x * 17); +} + +/* A static inlined function that calls a non-static inlined + function. */ + +inline ATTR int +func5b (int x) +{ + return x < 12 ? 1 : 2; +} + +static inline ATTR int +func5a (int x) +{ + return func5b (x * 23); +} + +/* A non-static inlined function that calls another non-static inlined + function. */ + +inline ATTR int +func6b (int x) +{ + return x < 14 ? 3 : 2; +} + +inline ATTR int +func6a (int x) +{ + return func6b (x * 17); +} + +/* A static inlined function that is called more than once. */ + +static inline ATTR int +func7b (int x) +{ + return x < 23 ? 1 : 4; +} + +static inline ATTR int +func7a (int x) +{ + return func7b (x * 29); +} + +/* A non-static inlined function that is called more than once. */ + +inline ATTR int +func8b (int x) +{ + return x < 7 ? 11 : 9; +} + +static inline ATTR int +func8a (int x) +{ + return func8b (x * 31); +} + +/* Entry point. */ + +int +main (int argc, char *argv[]) +{ + /* Declaring x as volatile here prevents GCC from combining calls. + If GCC is allowed to combine calls then some of them end up with + no instructions at all, so there is no specific address for GDB + to set a breakpoint at. */ + volatile int x = argc; + + x = func1 (x); + + x = func2 (x); + + x = func3a (x); + + x = func4a (x); + + x = func5a (x); + + x = func6a (x); + + x = func7a (x) + func7b (x); + + x = func8a (x) + func8b (x); + + return x; +} diff --git a/gdb/testsuite/gdb.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp new file mode 100644 index 0000000..63d1fad --- /dev/null +++ b/gdb/testsuite/gdb.opt/inline-break.exp @@ -0,0 +1,91 @@ +# Copyright 2011 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 . + +set testfile "inline-break" + +if { [prepare_for_testing $testfile.exp $testfile $testfile.c \ + {debug optimize=-O2 additional_flags=-Winline}] } { + return -1 +} + +# +# func1 is a static inlined function that is called once. +# The result should be a single-location breakpoint. +# +gdb_test "break func1" \ + "Breakpoint.*at.* file .*$testfile\.c, line.*" + +# +# func2 is a non-static inlined function that is called once. +# The result should be a breakpoint with two locations: the +# out-of-line function and the single inlined instance. +# +gdb_test "break func2" \ + "Breakpoint.*at.*func2.*(2 locations).*" + +# +# func3b is a static inlined function that is called once from +# within another static inlined function. The result should be +# a single-location breakpoint. +# +gdb_test "break func3b" \ + "Breakpoint.*at.* file .*$testfile\.c, line.*" + +# +# func4b is a static inlined function that is called once from +# within a non-static inlined function. The result should be +# a breakpoint with two locations: the inlined instance within +# the inlined call to func4a in main, and the inlined instance +# within the out-of-line func4a. +# +gdb_test "break func4b" \ + "Breakpoint.*at.*func4b.*(2 locations).*" + +# +# func5b is a non-static inlined function that is called once +# from within a static inlined function. The result should be a +# breakpoint with two locations: the out-of-line function and the +# inlined instance within the inlined call to func5a in main. +# +gdb_test "break func5b" \ + "Breakpoint.*at.*func5b.*(2 locations).*" +# +# func6b is a non-static inlined function that is called once from +# within another non-static inlined function. The result should be +# a breakpoint with three locations: the out-of-line function, the +# inlined instance within the out-of-line func6a, and the inlined +# instance within the inlined call to func6a in main, +# +gdb_test "break func6b" \ + "Breakpoint.*at.*func6b.*(3 locations).*" + +# +# func7b is a static inlined function that is called twice: once from +# func7a, and once from main. The result should be a breakpoint with +# two locations: the inlined instance within the inlined instance of +# func7a, and the inlined instance within main. +# +gdb_test "break func7b" \ + "Breakpoint.*at.*func7b.*(2 locations).*" + +# +# func8b is a non-static inlined function that is called twice: once +# func8a, and once from main. The result should be a breakpoint with +# three locations: the out-of-line function, the inlined instance +# within the inlined instance of func7a, and the inlined instance +# within main. +# +gdb_test "break func8b" \ + "Breakpoint.*at.*func8b.*(3 locations).*" --H+4ONPRPur6+Ovig--