Re: [PATCH v2] gdb: fix breakpoints on inline functions qualified with source file name
Guinevere Larsen <[email protected]>
| Newsgroups | gmane.comp.gdb.patches |
|---|---|
| Message-ID | <[email protected]> |
On 8/13/26 6:56 AM, Markus Metzger wrote: > On 'break foo.[hc]:foo', GDB only searches the symbols of foo.[hc] on file > scope. If foo has been inlined, GDB would not find it. > > On 'break foo', however, GDB also searches local blocks for inline > function symbols in iterate_over_all_matching_symtabs(), which is called > indirectly from add_matching_symbols_to_info(). > > Add that functionality to add_matching_symbols_to_info() in case it is > called with a list of file symtabs to search. > > Also add iterate_over_local_blocks() as helper function similar to > iterate_over_file_blocks(). > --- Hi Markus! I looked over this and all my questions have been solved. Reviewed-By: Guinevere Larsen <[email protected]> -- Cheers, Guinevere Larsen it/its she/her (deprecated) > gdb/linespec.c | 51 ++++++++++++++++-------- > gdb/testsuite/gdb.base/break-inline2.c | 33 +++++++++++++++ > gdb/testsuite/gdb.base/break-inline2.exp | 30 ++++++++++++++ > gdb/testsuite/gdb.base/break-inline2.h | 28 +++++++++++++ > 4 files changed, 126 insertions(+), 16 deletions(-) > create mode 100644 gdb/testsuite/gdb.base/break-inline2.c > create mode 100644 gdb/testsuite/gdb.base/break-inline2.exp > create mode 100644 gdb/testsuite/gdb.base/break-inline2.h > > diff --git a/gdb/linespec.c b/gdb/linespec.c > index b6505ba283d..9959690b57b 100644 > --- a/gdb/linespec.c > +++ b/gdb/linespec.c > @@ -363,6 +363,11 @@ static void iterate_over_file_blocks > domain_search_flags domain, > for_each_symbol_callback_ftype callback); > > +static void iterate_over_local_blocks > + (const symtab *symtab, const language_defn *language, > + const lookup_name_info &name, domain_search_flags domain, > + for_each_symbol_callback_ftype callback); > + > static void initialize_defaults (struct symtab **default_symtab, > int *default_line); > > @@ -1147,23 +1152,14 @@ iterate_over_all_matching_symtabs > > if (include_inline) > { > - const struct block *block; > - int i; > - const blockvector *bv = symtab->compunit ().blockvector (); > - > - for (i = FIRST_LOCAL_BLOCK; i < bv->num_blocks (); i++) > + auto callback_inlined = [&] (block_symbol *bsym) > { > - block = bv->block (i); > - state->language->for_each_symbol > - (block, lookup_name, domain, > - [&] (block_symbol *bsym) > - { > - /* Restrict calls to CALLBACK to symbols > - representing inline symbols only. */ > - if (bsym->symbol->is_inlined ()) > - callback (bsym); > - }); > - } > + if (bsym->symbol->is_inlined ()) > + callback (bsym); > + }; > + iterate_over_local_blocks (symtab, state->language, > + lookup_name, domain, > + callback_inlined); > } > > return iteration_status::keep_going; > @@ -1203,6 +1199,22 @@ iterate_over_file_blocks > current_language->for_each_symbol (block, name, domain, callback); > } > > +/* Iterate over local blocks. */ > + > +static void > +iterate_over_local_blocks > + (const symtab *symtab, const language_defn *language, > + const lookup_name_info &name, domain_search_flags domain, > + for_each_symbol_callback_ftype callback) > +{ > + const blockvector *bv = symtab->compunit ().blockvector (); > + for (int i = FIRST_LOCAL_BLOCK; i < bv->num_blocks (); i++) > + { > + const struct block *block = bv->block (i); > + language->for_each_symbol (block, name, domain, callback); > + } > +} > + > /* A helper for find_method. This finds all methods in type T of > language T_LANG which match NAME. It adds matching symbol names to > RESULT_NAMES, and adds T's direct superclasses to SUPERCLASSES. */ > @@ -4253,6 +4265,11 @@ add_matching_symbols_to_info (const char *name, > { > info->add_symbol (bsym); > }; > + auto add_inlined_symbol = [&] (block_symbol *bsym) > + { > + if (bsym->symbol->is_inlined ()) > + info->add_symbol (bsym); > + }; > > for (const auto &elt : info->file_symtabs) > { > @@ -4275,6 +4292,8 @@ add_matching_symbols_to_info (const char *name, > gdb_assert (!elt_pspace->executing_startup); > set_current_program_space (elt_pspace); > iterate_over_file_blocks (elt, lookup_name, SEARCH_VFT, add_symbol); > + iterate_over_local_blocks (elt, info->state->language, lookup_name, > + SEARCH_VFT, add_inlined_symbol); > > /* If no new symbols were found in this iteration and this symtab > is in assembler, we might actually be looking for a label for > diff --git a/gdb/testsuite/gdb.base/break-inline2.c b/gdb/testsuite/gdb.base/break-inline2.c > new file mode 100644 > index 00000000000..797ab07da31 > --- /dev/null > +++ b/gdb/testsuite/gdb.base/break-inline2.c > @@ -0,0 +1,33 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2026 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 <http://www.gnu.org/licenses/>. */ > + > +#include "break-inline2.h" > + > +static int > +test (void) > +{ > + int f = foo (); > + int b = bar (); > + return f + b; > +} > + > +int > +main (void) > +{ > + /* Don't make breakpoints on foo and main bind to the same address. */ > + return test (); > +} > diff --git a/gdb/testsuite/gdb.base/break-inline2.exp b/gdb/testsuite/gdb.base/break-inline2.exp > new file mode 100644 > index 00000000000..b10cdece118 > --- /dev/null > +++ b/gdb/testsuite/gdb.base/break-inline2.exp > @@ -0,0 +1,30 @@ > +# Copyright (C) 2026 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 <http://www.gnu.org/licenses/>. > + > +standard_testfile > + > +if {[prepare_for_testing "failed to prepare" "$testfile" "$srcfile"]} { > + return > +} > + > +if {![runto_main]} { > + return > +} > + > +gdb_breakpoint "$testfile.h:foo" -message -allow-pending > +gdb_breakpoint bar -message -allow-pending > + > +gdb_continue_to_breakpoint "foo" ".*foo.entry.*" > +gdb_continue_to_breakpoint "bar" ".*bar.entry.*" > diff --git a/gdb/testsuite/gdb.base/break-inline2.h b/gdb/testsuite/gdb.base/break-inline2.h > new file mode 100644 > index 00000000000..e60d054e85b > --- /dev/null > +++ b/gdb/testsuite/gdb.base/break-inline2.h > @@ -0,0 +1,28 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2026 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 <http://www.gnu.org/licenses/>. */ > + > +static inline int __attribute__((always_inline)) > +foo (void) /* foo.entry */ > +{ /* foo.entry */ > + return 42; /* foo.entry */ > +} > + > +static inline int __attribute__((always_inline)) > +bar (void) /* bar.entry */ > +{ /* bar.entry */ > + return 42; /* bar.entry */ > +}