+2018-09-05 Tom de Vries <tdevries@suse.de>
+
+ * 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 <brobecker@adacore.com>
GDB 8.2 released.
(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
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
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);
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,
}
}
- 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
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;
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.".
#ifndef DWARF2READ_H
#define DWARF2READ_H
+#include <unordered_map>
#include "dwarf-index-cache.h"
#include "filename-seen-cache.h"
#include "gdb_obstack.h"
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. */
/* 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_resource> index_cache_res;
+
+ /* Mapping from abstract origin DIE to concrete DIEs that reference it as
+ DW_AT_abstract_origin. */
+ std::unordered_map<die_info_ptr, std::vector<die_info_ptr>>
+ abstract_to_concrete;
};
/* Get the dwarf2_per_objfile associated to OBJFILE. */
+2018-09-05 Tom de Vries <tdevries@suse.de>
+
+ * gdb.dwarf2/varval.exp: Add test.
+
2018-09-04 Gary Benson <gbenson@redhat.com>
* gdb.base/batch-exit-status.exp: Use gdb_test_multiple and expect
} {
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]
{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}}
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}}
}
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 <var_b>"