Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.2:Staging:A
gdb
gdb-symtab-prefer-var-def-over-decl.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gdb-symtab-prefer-var-def-over-decl.patch of Package gdb
[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>"
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor