aboutsummaryrefslogtreecommitdiff
path: root/gdb/block.c
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2019-12-06 18:51:49 +0100
committerTom de Vries <tdevries@suse.de>2019-12-06 18:51:49 +0100
commit93e55f0a031b0e677d22aaba00857de902ebe685 (patch)
treefca7f2c0c69822cf7a8007e2f1931a0be9fb1eb9 /gdb/block.c
parente8dc9b5bfd234f61c6127d23cb80fbd4b0382115 (diff)
downloadbinutils-93e55f0a031b0e677d22aaba00857de902ebe685.zip
binutils-93e55f0a031b0e677d22aaba00857de902ebe685.tar.gz
binutils-93e55f0a031b0e677d22aaba00857de902ebe685.tar.bz2
[gdb/symtab] Prefer var def over decl
Consider the DWARF as generated by gcc with the tentative patch to fix gcc PR91507 - "wrong debug for completed array with previous incomplete declaration": ... <1><f4>: Abbrev Number: 2 (DW_TAG_array_type) <f5> DW_AT_type : <0xff> <f9> DW_AT_sibling : <0xff> <2><fd>: Abbrev Number: 3 (DW_TAG_subrange_type) <2><fe>: Abbrev Number: 0 <1><ff>: Abbrev Number: 4 (DW_TAG_pointer_type) <100> DW_AT_byte_size : 8 <101> DW_AT_type : <0x105> <1><105>: Abbrev Number: 5 (DW_TAG_base_type) <106> DW_AT_byte_size : 1 <107> DW_AT_encoding : 6 (signed char) <108> DW_AT_name : (indirect string, offset: 0x19f): char <1><10c>: Abbrev Number: 6 (DW_TAG_variable) <10d> DW_AT_name : zzz <111> DW_AT_decl_file : 1 <112> DW_AT_decl_line : 1 <113> DW_AT_decl_column : 14 <114> DW_AT_type : <0xf4> <118> DW_AT_external : 1 <118> DW_AT_declaration : 1 <1><118>: Abbrev Number: 2 (DW_TAG_array_type) <119> DW_AT_type : <0xff> <11d> DW_AT_sibling : <0x128> <1><12f>: Abbrev Number: 8 (DW_TAG_variable) <130> DW_AT_specification: <0x10c> <134> DW_AT_decl_line : 2 <135> DW_AT_decl_column : 7 <136> DW_AT_type : <0x118> <13a> DW_AT_location : 9 byte block: 3 30 10 60 0 0 0 0 0 (DW_OP_addr: 601030) ... The DWARF will result in two entries in the symbol table, a decl with type char *[] and a def with type char*[2]. When trying to print the value of zzz: ... $ gdb a.spec.out -batch -ex "p zzz" ... the decl (rather than the def) will be found in the symbol table, which is missing the location information, and consequently we get: ... $1 = 0x601030 <zzz> ... [ There is a fallback mechanism that finds the address of the variable in the minimal symbol table, but that's not used here, because the type of the decl does not specify a size. We could use the symbol size here to get the size of the type, but that's currently not done: PR exp/24989. Still, fixing that PR would not fix the generic case, where minimal symbol info is not available. ] Fix this by preferring defs over decls when searching in the symbol table. Build and reg-tested on x86_64-linux. gdb/ChangeLog: 2019-12-06 Tom de Vries <tdevries@suse.de> PR symtab/24971 * block.c (best_symbol, better_symbol): New function. (block_lookup_symbol_primary, block_lookup_symbol): Prefer def over decl. gdb/testsuite/ChangeLog: 2019-12-06 Tom de Vries <tdevries@suse.de> * gdb.dwarf2/varval.exp: Add decl before def test. Change-Id: Id92326cb8ef9903b121ef9e320658eb565d0f5a9
Diffstat (limited to 'gdb/block.c')
-rw-r--r--gdb/block.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/gdb/block.c b/gdb/block.c
index a4592e3..b49c548 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -657,6 +657,43 @@ 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. */
+
+static 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. */
+
+static struct symbol *
+better_symbol (struct symbol *a, struct symbol *b, const domain_enum domain)
+{
+ if (a == NULL)
+ return b;
+ if (b == NULL)
+ return a;
+
+ if (SYMBOL_DOMAIN (a) == domain
+ && SYMBOL_DOMAIN (b) != domain)
+ return a;
+ if (SYMBOL_DOMAIN (b) == domain
+ && SYMBOL_DOMAIN (a) != domain)
+ return b;
+
+ if (SYMBOL_CLASS (a) != LOC_UNRESOLVED
+ && SYMBOL_CLASS (b) == LOC_UNRESOLVED)
+ return a;
+ if (SYMBOL_CLASS (b) != LOC_UNRESOLVED
+ && SYMBOL_CLASS (a) == LOC_UNRESOLVED)
+ return b;
+
+ return a;
+}
+
/* See block.h.
Note that if NAME is the demangled form of a C++ symbol, we will fail
@@ -684,7 +721,9 @@ block_lookup_symbol (const struct block *block, const char *name,
ALL_BLOCK_SYMBOLS_WITH_NAME (block, lookup_name, iter, sym)
{
- if (SYMBOL_DOMAIN (sym) == domain)
+ /* See comment related to PR gcc/debug/91507 in
+ block_lookup_symbol_primary. */
+ if (best_symbol (sym, domain))
return sym;
/* This is a bit of a hack, but symbol_matches_domain might ignore
STRUCT vs VAR domain symbols. So if a matching symbol is found,
@@ -692,7 +731,7 @@ block_lookup_symbol (const struct block *block, const char *name,
exactly the same domain. PR 16253. */
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
- other = sym;
+ other = better_symbol (other, sym, domain);
}
return other;
}
@@ -746,7 +785,34 @@ block_lookup_symbol_primary (const struct block *block, const char *name,
sym != NULL;
sym = mdict_iter_match_next (lookup_name, &mdict_iter))
{
- if (SYMBOL_DOMAIN (sym) == domain)
+ /* With the fix for PR gcc/debug/91507, we get for:
+ ...
+ extern char *zzz[];
+ char *zzz[ ] = {
+ "abc",
+ "cde"
+ };
+ ...
+ DWARF which will result in two entries in the symbol table, a decl
+ with type char *[] and a def with type char *[2].
+
+ If we return the decl here, we don't get the value of zzz:
+ ...
+ $ gdb a.spec.out -batch -ex "p zzz"
+ $1 = 0x601030 <zzz>
+ ...
+ because we're returning the symbol without location information, and
+ because the fallback that uses the address from the minimal symbols
+ doesn't work either because the type of the decl does not specify a
+ size.
+
+ To fix this, we prefer def over decl in best_symbol and
+ better_symbol.
+
+ In absence of the gcc fix, both def and decl have type char *[], so
+ the only option to make this work is improve the fallback to use the
+ size of the minimal symbol. Filed as PR exp/24989. */
+ if (best_symbol (sym, domain))
return sym;
/* This is a bit of a hack, but symbol_matches_domain might ignore
@@ -755,7 +821,7 @@ block_lookup_symbol_primary (const struct block *block, const char *name,
exactly the same domain. PR 16253. */
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
- other = sym;
+ other = better_symbol (other, sym, domain);
}
return other;