diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c5d5555bcd7..0f8599bb166 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2018-09-05 Tom de Vries + + * dwarf2loc.c (sect_variable_value): Call indirect_synthetic_pointer + with resolve_abstract_p == true. + (indirect_synthetic_pointer): Add resolve_abstract_p parameter, + defaulting to false. Propagate resolve_abstract_p to + dwarf2_fetch_die_loc_sect_off. + * dwarf2loc.h (dwarf2_fetch_die_loc_sect_off): Add resolve_abstract_p + parameter, defaulting to false. + * dwarf2read.c (read_variable): Add variable to abstract_to_concrete. + (dwarf2_fetch_die_loc_sect_off): Add and handle resolve_abstract_p + parameter. + * dwarf2read.h (struct die_info): Forward-declare. + (die_info_ptr): New typedef. + (struct dwarf2_per_objfile): Add abstract_to_concrete field. + 2018-09-05 Joel Brobecker GDB 8.2 released. diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 200fa03f46a..84e3c3ca691 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -65,7 +65,7 @@ static struct value *indirect_synthetic_pointer (sect_offset die, LONGEST byte_offset, struct dwarf2_per_cu_data *per_cu, struct frame_info *frame, - struct type *type); + struct type *type, bool resolve_abstract_p = false); /* Until these have formal names, we define these here. ref: http://gcc.gnu.org/wiki/DebugFission @@ -573,7 +573,7 @@ sect_variable_value (struct dwarf_expr_context *ctx, sect_offset sect_off, struct type *type = lookup_pointer_type (die_type); struct frame_info *frame = get_selected_frame (_("No frame selected.")); - return indirect_synthetic_pointer (sect_off, 0, per_cu, frame, type); + return indirect_synthetic_pointer (sect_off, 0, per_cu, frame, type, true); } class dwarf_evaluate_loc_desc : public dwarf_expr_context @@ -2181,12 +2181,14 @@ fetch_const_value_from_synthetic_pointer (sect_offset die, LONGEST byte_offset, static struct value * indirect_synthetic_pointer (sect_offset die, LONGEST byte_offset, struct dwarf2_per_cu_data *per_cu, - struct frame_info *frame, struct type *type) + struct frame_info *frame, struct type *type, + bool resolve_abstract_p) { /* Fetch the location expression of the DIE we're pointing to. */ struct dwarf2_locexpr_baton baton = dwarf2_fetch_die_loc_sect_off (die, per_cu, - get_frame_address_in_block_wrapper, frame); + get_frame_address_in_block_wrapper, frame, + resolve_abstract_p); /* Get type of pointed-to DIE. */ struct type *orig_type = dwarf2_fetch_die_type_sect_off (die, per_cu); diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index f82e7b2d117..d02e3cd3541 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -67,7 +67,7 @@ const gdb_byte *dwarf2_find_location_expression struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_sect_off (sect_offset offset_in_cu, struct dwarf2_per_cu_data *per_cu, CORE_ADDR (*get_frame_pc) (void *baton), - void *baton); + void *baton, bool resolve_abstract_p = false); struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu, struct dwarf2_per_cu_data *per_cu, diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index d66dfeaf2d2..4a35e389e93 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14283,7 +14283,22 @@ read_variable (struct die_info *die, struct dwarf2_cu *cu) } } - new_symbol (die, NULL, cu, storage); + struct symbol *res = new_symbol (die, NULL, cu, storage); + struct attribute *abstract_origin + = dwarf2_attr (die, DW_AT_abstract_origin, cu); + struct attribute *loc = dwarf2_attr (die, DW_AT_location, cu); + if (res == NULL && loc && abstract_origin) + { + /* We have a variable without a name, but with a location and an abstract + origin. This may be a concrete instance of an abstract variable + referenced from an DW_OP_GNU_variable_value, so save it to find it back + later. */ + struct dwarf2_cu *origin_cu = cu; + struct die_info *origin_die + = follow_die_ref (die, abstract_origin, &origin_cu); + dwarf2_per_objfile *dpo = cu->per_cu->dwarf2_per_objfile; + dpo->abstract_to_concrete[origin_die].push_back (die); + } } /* Call CALLBACK from DW_AT_ranges attribute value OFFSET @@ -23010,7 +23025,7 @@ struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, struct dwarf2_per_cu_data *per_cu, CORE_ADDR (*get_frame_pc) (void *baton), - void *baton) + void *baton, bool resolve_abstract_p) { struct dwarf2_cu *cu; struct die_info *die; @@ -23036,6 +23051,30 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, sect_offset_str (sect_off), objfile_name (objfile)); attr = dwarf2_attr (die, DW_AT_location, cu); + if (!attr && resolve_abstract_p + && (dwarf2_per_objfile->abstract_to_concrete.find (die) + != dwarf2_per_objfile->abstract_to_concrete.end ())) + { + CORE_ADDR pc = (*get_frame_pc) (baton); + + for (const auto &cand : dwarf2_per_objfile->abstract_to_concrete[die]) + { + if (!cand->parent + || cand->parent->tag != DW_TAG_subprogram) + continue; + + CORE_ADDR pc_low, pc_high; + get_scope_pc_bounds (cand->parent, &pc_low, &pc_high, cu); + if (pc_low == ((CORE_ADDR) -1) + || !(pc_low <= pc && pc < pc_high)) + continue; + + die = cand; + attr = dwarf2_attr (die, DW_AT_location, cu); + break; + } + } + if (!attr) { /* DWARF: "If there is no such attribute, then there is no effect.". diff --git a/gdb/dwarf2read.h b/gdb/dwarf2read.h index 13855bcd547..67ebc1902b2 100644 --- a/gdb/dwarf2read.h +++ b/gdb/dwarf2read.h @@ -20,6 +20,7 @@ #ifndef DWARF2READ_H #define DWARF2READ_H +#include #include "dwarf-index-cache.h" #include "filename-seen-cache.h" #include "gdb_obstack.h" @@ -95,6 +96,8 @@ struct dwarf2_debug_sections; struct mapped_index; struct mapped_debug_names; struct signatured_type; +struct die_info; +typedef struct die_info *die_info_ptr; /* Collection of data recorded per objfile. This hangs off of dwarf2_objfile_data_key. */ @@ -250,6 +253,11 @@ public: /* If we loaded the index from an external file, this contains the resources associated to the open file, memory mapping, etc. */ std::unique_ptr index_cache_res; + + /* Mapping from abstract origin DIE to concrete DIEs that reference it as + DW_AT_abstract_origin. */ + std::unordered_map> + abstract_to_concrete; }; /* Get the dwarf2_per_objfile associated to OBJFILE. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 79e57fcd8bb..a7059332496 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-09-05 Tom de Vries + + * gdb.dwarf2/varval.exp: Add test. + 2018-09-04 Gary Benson * gdb.base/batch-exit-status.exp: Use gdb_test_multiple and expect diff --git a/gdb/testsuite/gdb.dwarf2/varval.exp b/gdb/testsuite/gdb.dwarf2/varval.exp index f4319ae7d25..400ad60873b 100644 --- a/gdb/testsuite/gdb.dwarf2/varval.exp +++ b/gdb/testsuite/gdb.dwarf2/varval.exp @@ -49,7 +49,9 @@ Dwarf::assemble ${asm_file} { } { declare_labels int_label ptr_label struct_label var_a_label \ var_b_label var_c_label var_p_label var_bad_label \ - varval_label var_s_label var_untyped_label + varval_label var_s_label var_untyped_label \ + var_a_abstract_label var_a_concrete_label \ + varval2_label set int_size [get_sizeof "int" -1] @@ -73,6 +75,11 @@ Dwarf::assemble ${asm_file} { {DW_AT_location {DW_OP_addr [gdb_target_symbol "var_a"]} SPECIAL_expr} } + var_a_abstract_label: DW_TAG_variable { + {DW_AT_type :${int_label}} + {DW_AT_external 1 DW_FORM_flag} + } + var_b_label: DW_TAG_variable { {DW_AT_name "var_b"} {DW_AT_type :${int_label}} @@ -171,6 +178,18 @@ Dwarf::assemble ${asm_file} { DW_OP_stack_value } SPECIAL_expr} } + varval2_label: DW_TAG_variable { + {DW_AT_name "varval2"} + {DW_AT_type :${int_label}} + {DW_AT_location { + DW_OP_GNU_variable_value ${var_a_abstract_label} + DW_OP_stack_value + } SPECIAL_expr} + } + var_a_concrete_label: DW_TAG_variable { + {DW_AT_abstract_origin :${var_a_abstract_label}} + {DW_AT_location {DW_OP_addr [gdb_target_symbol "var_a"]} SPECIAL_expr} + } DW_TAG_variable { {DW_AT_name "constval"} {DW_AT_type :${int_label}} @@ -255,6 +274,7 @@ if ![runto_main] { } gdb_test "print varval" "= 8" +gdb_test "print varval2" "= 8" gdb_test "print constval" "= 53" gdb_test "print mixedval" "= 42" gdb_test "print pointerval" "= \\(int \\*\\) $hex "