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).*"