From de82891ce5b6d2c8109f512cd0732325f4cd0557 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Thu, 23 Apr 2020 15:42:47 +0200 Subject: [PATCH] [gdb/symtab] Prefer def over decl (inter-CU case) When running test-case gdb.threads/tls.exp with target board -readnow, we have: ... (gdb) print a_thread_local^M Cannot find thread-local storage for process 0, executable file tls/tls:^M Cannot find thread-local variables on this target^M (gdb) FAIL: gdb.threads/tls.exp: print a_thread_local ... while with native we have: ... (gdb) print a_thread_local^M Cannot read `a_thread_local' without registers^M (gdb) PASS: gdb.threads/tls.exp: print a_thread_local ... The difference in behaviour can be explained as follows. Without -readnow, we have two a_thread_locals, the def and the decl, each in a different CU: ... $ gdb -batch outputs/gdb.threads/tls/tls \ -ex "maint expand-symtabs" \ -ex "print a_thread_local" \ -ex "maint print symbols" \ | grep "a_thread_local;" Cannot read `a_thread_local' without registers int a_thread_local; computed at runtime int a_thread_local; unresolved ... and with -readnow, we have the opposite order: ... $ gdb -readnow -batch outputs/gdb.threads/tls/tls \ -ex "maint expand-symtabs" \ -ex "print a_thread_local" \ -ex "maint print symbols" \ | grep "a_thread_local;" Cannot find thread-local storage for process 0, executable file tls/tls: Cannot find thread-local variables on this target int a_thread_local; unresolved int a_thread_local; computed at runtime ... Fix the FAIL by preferring the def over the decl (something we already do intra-CU since the fix for PR24971, commit 93e55f0a03 "[gdb/symtab] Prefer var def over decl"). Build and reg-tested on x86_64-linux. gdb/ChangeLog: 2020-04-23 Tom de Vries PR symtab/25807 * block.c (best_symbol, better_symbol): Promote to external. * block.h (best_symbol, better_symbol): Declare. * symtab.c (lookup_symbol_in_objfile_symtabs): Prefer def over decl. gdb/testsuite/ChangeLog: 2020-04-23 Tom de Vries * gdb.base/decl-before-def-decl.c: New test. * gdb.base/decl-before-def-def.c: New test. * gdb.base/decl-before-def.exp: New file. --- gdb/ChangeLog | 8 +++++ gdb/block.c | 9 +++-- gdb/block.h | 10 ++++++ gdb/symtab.c | 34 +++++++++++++++---- gdb/testsuite/ChangeLog | 6 ++++ gdb/testsuite/gdb.base/decl-before-def-decl.c | 25 ++++++++++++++ gdb/testsuite/gdb.base/decl-before-def-def.c | 18 ++++++++++ gdb/testsuite/gdb.base/decl-before-def.exp | 26 ++++++++++++++ 8 files changed, 124 insertions(+), 12 deletions(-) create mode 100644 gdb/testsuite/gdb.base/decl-before-def-decl.c create mode 100644 gdb/testsuite/gdb.base/decl-before-def-def.c create mode 100644 gdb/testsuite/gdb.base/decl-before-def.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cbe26937198..f1ebf09ff46 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2020-04-23 Tom de Vries + + PR symtab/25807 + * block.c (best_symbol, better_symbol): Promote to external. + * block.h (best_symbol, better_symbol): Declare. + * symtab.c (lookup_symbol_in_objfile_symtabs): Prefer def over + decl. + 2020-04-23 Tom Tromey PR ada/25837: diff --git a/gdb/block.c b/gdb/block.c index 9b582433e48..597d6d5d875 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -657,19 +657,18 @@ block_iter_match_next (const lookup_name_info &name, return block_iter_match_step (iterator, name, 0); } -/* Return true if symbol A is the best match possible for DOMAIN. */ +/* See block.h. */ -static bool +bool best_symbol (struct symbol *a, const domain_enum domain) { return (SYMBOL_DOMAIN (a) == domain && SYMBOL_CLASS (a) != LOC_UNRESOLVED); } -/* Return symbol B if it is a better match than symbol A for DOMAIN. - Otherwise return A. */ +/* See block.h. */ -static struct symbol * +struct symbol * better_symbol (struct symbol *a, struct symbol *b, const domain_enum domain) { if (a == NULL) diff --git a/gdb/block.h b/gdb/block.h index 7c0b2d36966..50ab049f8e6 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -342,6 +342,16 @@ extern struct symbol *block_iter_match_first (const struct block *block, extern struct symbol *block_iter_match_next (const lookup_name_info &name, struct block_iterator *iterator); +/* Return true if symbol A is the best match possible for DOMAIN. */ + +extern bool best_symbol (struct symbol *a, const domain_enum domain); + +/* Return symbol B if it is a better match than symbol A for DOMAIN. + Otherwise return A. */ + +extern struct symbol *better_symbol (struct symbol *a, struct symbol *b, + const domain_enum domain); + /* Search BLOCK for symbol NAME in DOMAIN. */ extern struct symbol *block_lookup_symbol (const struct block *block, diff --git a/gdb/symtab.c b/gdb/symtab.c index dc079efbc27..1eef97837e8 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -2285,6 +2285,8 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile, name, domain_name (domain)); } + struct block_symbol other; + other.symbol = NULL; for (compunit_symtab *cust : objfile->compunits ()) { const struct blockvector *bv; @@ -2295,18 +2297,36 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile, block = BLOCKVECTOR_BLOCK (bv, block_index); result.symbol = block_lookup_symbol_primary (block, name, domain); result.block = block; - if (result.symbol != NULL) + if (result.symbol == NULL) + continue; + if (best_symbol (result.symbol, domain)) { - if (symbol_lookup_debug > 1) + other = result; + break; + } + if (symbol_matches_domain (result.symbol->language (), + SYMBOL_DOMAIN (result.symbol), domain)) + { + struct symbol *better + = better_symbol (other.symbol, result.symbol, domain); + if (better != other.symbol) { - fprintf_unfiltered (gdb_stdlog, " = %s (block %s)\n", - host_address_to_string (result.symbol), - host_address_to_string (block)); + other.symbol = better; + other.block = block; } - result.symbol = fixup_symbol_section (result.symbol, objfile); - return result; + } + } + if (other.symbol != NULL) + { + if (symbol_lookup_debug > 1) + { + fprintf_unfiltered (gdb_stdlog, " = %s (block %s)\n", + host_address_to_string (other.symbol), + host_address_to_string (other.block)); } + other.symbol = fixup_symbol_section (other.symbol, objfile); + return other; } if (symbol_lookup_debug > 1) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 7e6bf73fa41..e37aca2b5af 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-23 Tom de Vries + + * gdb.base/decl-before-def-decl.c: New test. + * gdb.base/decl-before-def-def.c: New test. + * gdb.base/decl-before-def.exp: New file. + 2020-04-23 Tom de Vries * gdb.base/readnever.exp: Skip if GDBFLAGS contain -readnow/--readnow. diff --git a/gdb/testsuite/gdb.base/decl-before-def-decl.c b/gdb/testsuite/gdb.base/decl-before-def-decl.c new file mode 100644 index 00000000000..3e4e6d777d9 --- /dev/null +++ b/gdb/testsuite/gdb.base/decl-before-def-decl.c @@ -0,0 +1,25 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2020 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 . */ + +extern int a[]; + +int +main (void) +{ + a[0] = 1; + return 0; +} diff --git a/gdb/testsuite/gdb.base/decl-before-def-def.c b/gdb/testsuite/gdb.base/decl-before-def-def.c new file mode 100644 index 00000000000..4d25248bc27 --- /dev/null +++ b/gdb/testsuite/gdb.base/decl-before-def-def.c @@ -0,0 +1,18 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2020 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 . */ + +int a[2] = { 1, 2 }; diff --git a/gdb/testsuite/gdb.base/decl-before-def.exp b/gdb/testsuite/gdb.base/decl-before-def.exp new file mode 100644 index 00000000000..feb2084a82f --- /dev/null +++ b/gdb/testsuite/gdb.base/decl-before-def.exp @@ -0,0 +1,26 @@ +# Copyright 2020 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 decl-before-def-decl.c decl-before-def-def.c +set sources [list $srcfile $srcfile2] + +if {[prepare_for_testing "failed to prepare" $testfile $sources]} { + return -1 +} + +# This is required due to PR25764. +gdb_test "maint expand-symtabs" + +gdb_test "p a" { = \{1, 2\}} -- 2.30.2