- Fix for bsc#1146475 [bsc#1146475, swo#24971 ] * gdb-symtab-prefer-var-def-over-decl.patch - Fix for bsc#1146167 [bsc#1146167, swo#24956] * gdb-only-force-interp_console-ui_out-for-breakpoint-commands-in-mi-mode.patch OBS-URL: https://build.opensuse.org/request/show/746178 OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gdb?expand=0&rev=235
233 lines
7.5 KiB
Diff
233 lines
7.5 KiB
Diff
[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.
|
|
|
|
[ The test-case is a bit simpler than the DWARF example listed above, because
|
|
the new variable varval3 that is used is not listed in the minimal symbols, so
|
|
there's no need to work around the fallback mechanism to trigger the problem. ]
|
|
|
|
gdb/ChangeLog:
|
|
|
|
2019-09-10 Tom de Vries <tdevries@suse.de>
|
|
|
|
PR symtab/24971
|
|
* block.c (best_symbol, better_symbol): New function.
|
|
(block_lookup_symbol_primary): Prefer def over decl.
|
|
|
|
gdb/testsuite/ChangeLog:
|
|
|
|
2019-09-10 Tom de Vries <tdevries@suse.de>
|
|
|
|
* gdb.dwarf2/varval.exp: Add decl before def test.
|
|
|
|
Change-Id: Id92326cb8ef9903b121ef9e320658eb565d0f5a9
|
|
|
|
---
|
|
gdb/block.c | 68 +++++++++++++++++++++++++++++++++++--
|
|
gdb/testsuite/gdb.dwarf2/varval.exp | 28 +++++++++++++--
|
|
2 files changed, 92 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/gdb/block.c b/gdb/block.c
|
|
index 3192b33e9e9..37f9d4f8d21 100644
|
|
--- a/gdb/block.c
|
|
+++ b/gdb/block.c
|
|
@@ -726,6 +726,43 @@ block_lookup_symbol (const struct block *block, const char *name,
|
|
}
|
|
}
|
|
|
|
+/* 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. */
|
|
|
|
struct symbol *
|
|
@@ -747,7 +784,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
|
|
@@ -756,7 +820,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;
|
|
diff --git a/gdb/testsuite/gdb.dwarf2/varval.exp b/gdb/testsuite/gdb.dwarf2/varval.exp
|
|
index 4711f4a24ae..fa3d90eb3d9 100644
|
|
--- a/gdb/testsuite/gdb.dwarf2/varval.exp
|
|
+++ b/gdb/testsuite/gdb.dwarf2/varval.exp
|
|
@@ -51,7 +51,7 @@ Dwarf::assemble ${asm_file} {
|
|
var_b_label var_c_label var_p_label var_bad_label \
|
|
varval_label var_s_label var_untyped_label \
|
|
var_a_abstract_label var_a_concrete_label \
|
|
- varval2_label
|
|
+ varval2_label varval3_decl_label varval3_def_label
|
|
|
|
set int_size [get_sizeof "int" -1]
|
|
|
|
@@ -165,6 +165,18 @@ Dwarf::assemble ${asm_file} {
|
|
{DW_AT_location {DW_OP_addr [gdb_target_symbol "var_b"]} SPECIAL_expr}
|
|
}
|
|
|
|
+ varval3_decl_label: DW_TAG_variable {
|
|
+ {DW_AT_name "varval3"}
|
|
+ {DW_AT_type :${int_label}}
|
|
+ {DW_AT_external 1 DW_FORM_flag}
|
|
+ {DW_AT_declaration 1 DW_FORM_flag}
|
|
+ }
|
|
+ varval3_def_label: DW_TAG_variable {
|
|
+ {DW_AT_name "varval3"}
|
|
+ {DW_AT_external 1 DW_FORM_flag}
|
|
+ {DW_AT_type :${int_label}}
|
|
+ {DW_AT_location {DW_OP_addr [gdb_target_symbol "var_a"]} SPECIAL_expr}
|
|
+ }
|
|
DW_TAG_subprogram {
|
|
{MACRO_AT_func { "main" "${srcdir}/${subdir}/${srcfile}" }}
|
|
{DW_AT_type :${int_label}}
|
|
@@ -274,7 +286,19 @@ if ![runto_main] {
|
|
}
|
|
|
|
gdb_test "print varval" "= 8"
|
|
-gdb_test "print varval2" "= 8"
|
|
+#gdb_test "print varval2" "= 8"
|
|
+set test "print varval2"
|
|
+set pass_pattern "= 8"
|
|
+set kfail_pattern "value has been optimized out"
|
|
+gdb_test_multiple $test "" {
|
|
+ -re "\[\r\n\]*(?:$pass_pattern)\[\r\n\]+$gdb_prompt $" {
|
|
+ pass $test
|
|
+ }
|
|
+ -re "\[\r\n\]*(?:$kfail_pattern)\[\r\n\]+$gdb_prompt $" {
|
|
+ kfail gdb/24515 $test
|
|
+ }
|
|
+}
|
|
+gdb_test "print varval3" "= 8"
|
|
gdb_test "print constval" "= 53"
|
|
gdb_test "print mixedval" "= 42"
|
|
gdb_test "print pointerval" "= \\(int \\*\\) $hex <var_b>"
|