diff options
author | Tom de Vries <tdevries@suse.de> | 2019-12-06 18:51:49 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2019-12-06 18:51:49 +0100 |
commit | 93e55f0a031b0e677d22aaba00857de902ebe685 (patch) | |
tree | fca7f2c0c69822cf7a8007e2f1931a0be9fb1eb9 /gdb/block.c | |
parent | e8dc9b5bfd234f61c6127d23cb80fbd4b0382115 (diff) | |
download | gdb-93e55f0a031b0e677d22aaba00857de902ebe685.zip gdb-93e55f0a031b0e677d22aaba00857de902ebe685.tar.gz gdb-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.c | 74 |
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; |