* [PATCH v2] gdb: fix breakpoints on inline functions qualified with source file name
@ 2026-08-13 9:56 Markus Metzger
2026-08-14 13:57 ` Guinevere Larsen
0 siblings, 1 reply; 2+ messages in thread
From: Markus Metzger @ 2026-08-13 9:56 UTC (permalink / raw)
To: gdb-patches
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().
---
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 */
+}
--
2.53.0
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH v2] gdb: fix breakpoints on inline functions qualified with source file name
2026-08-13 9:56 [PATCH v2] gdb: fix breakpoints on inline functions qualified with source file name Markus Metzger
@ 2026-08-14 13:57 ` Guinevere Larsen
0 siblings, 0 replies; 2+ messages in thread
From: Guinevere Larsen @ 2026-08-14 13:57 UTC (permalink / raw)
To: Markus Metzger, gdb-patches
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 <guinevere@redhat.com>
--
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 */
> +}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-14 13:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-13 9:56 [PATCH v2] gdb: fix breakpoints on inline functions qualified with source file name Markus Metzger
2026-08-14 13:57 ` Guinevere Larsen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox