From 80180f796d366d230822c07a15aa68971abf9d77 Mon Sep 17 00:00:00 2001 From: Sanimir Agovic Date: Wed, 9 Oct 2013 15:28:22 +0100 Subject: type: add c99 variable length array support The dwarf standard allow certain attributes to be expressed as dwarf expressions rather than constants. For instance upper-/lowerbound attributes. In case of a c99 variable length array the upperbound is a dynamic attribute. With this change c99 vla behave the same as with static arrays. 1| void foo (size_t n) { 2| int ary[n]; 3| memset(ary, 0, sizeof(ary)); 4| } (gdb) print ary $1 = {0 } gdb/ChangeLog: * dwarf2loc.c (dwarf2_locexpr_baton_eval): New function. (dwarf2_evaluate_property): New function. * dwarf2loc.h (dwarf2_evaluate_property): New function prototype. * dwarf2read.c (attr_to_dynamic_prop): New function. (read_subrange_type): Use attr_to_dynamic_prop to read high bound attribute. * gdbtypes.c: Include dwarf2loc.h. (is_dynamic_type): New function. (resolve_dynamic_type): New function. (resolve_dynamic_bounds): New function. (get_type_length): New function. (check_typedef): Use get_type_length to compute type length. * gdbtypes.h (TYPE_HIGH_BOUND_KIND): New macro. (TYPE_LOW_BOUND_KIND): New macro. (is_dynamic_type): New function prototype. * value.c (value_from_contents_and_address): Call resolve_dynamic_type to resolve dynamic properties of the type. Update comment. * valops.c (get_value_at, value_at, value_at_lazy): Update comment. --- gdb/dwarf2read.c | 106 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 27 deletions(-) (limited to 'gdb/dwarf2read.c') diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 152c8d2..ff66cce 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14405,6 +14405,84 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) return set_die_type (die, type, cu); } +/* Parse dwarf attribute if it's a block, reference or constant and put the + resulting value of the attribute into struct bound_prop. + Returns 1 if ATTR could be resolved into PROP, 0 otherwise. */ + +static int +attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, + struct dwarf2_cu *cu, struct dynamic_prop *prop) +{ + struct dwarf2_property_baton *baton; + struct obstack *obstack = &cu->objfile->objfile_obstack; + + if (attr == NULL || prop == NULL) + return 0; + + if (attr_form_is_block (attr)) + { + baton = obstack_alloc (obstack, sizeof (*baton)); + baton->referenced_type = NULL; + baton->locexpr.per_cu = cu->per_cu; + baton->locexpr.size = DW_BLOCK (attr)->size; + baton->locexpr.data = DW_BLOCK (attr)->data; + prop->data.baton = baton; + prop->kind = PROP_LOCEXPR; + gdb_assert (prop->data.baton != NULL); + } + else if (attr_form_is_ref (attr)) + { + struct dwarf2_cu *target_cu = cu; + struct die_info *target_die; + struct attribute *target_attr; + + target_die = follow_die_ref (die, attr, &target_cu); + target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu); + if (target_attr == NULL) + return 0; + + if (attr_form_is_section_offset (target_attr)) + { + baton = obstack_alloc (obstack, sizeof (*baton)); + baton->referenced_type = die_type (target_die, target_cu); + fill_in_loclist_baton (cu, &baton->loclist, target_attr); + prop->data.baton = baton; + prop->kind = PROP_LOCLIST; + gdb_assert (prop->data.baton != NULL); + } + else if (attr_form_is_block (target_attr)) + { + baton = obstack_alloc (obstack, sizeof (*baton)); + baton->referenced_type = die_type (target_die, target_cu); + baton->locexpr.per_cu = cu->per_cu; + baton->locexpr.size = DW_BLOCK (target_attr)->size; + baton->locexpr.data = DW_BLOCK (target_attr)->data; + prop->data.baton = baton; + prop->kind = PROP_LOCEXPR; + gdb_assert (prop->data.baton != NULL); + } + else + { + dwarf2_invalid_attrib_class_complaint ("DW_AT_location", + "dynamic property"); + return 0; + } + } + else if (attr_form_is_constant (attr)) + { + prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0); + prop->kind = PROP_CONST; + } + else + { + dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form), + dwarf2_name (die, cu)); + return 0; + } + + return 1; +} + /* Read the given DW_AT_subrange DIE. */ static struct type * @@ -14478,27 +14556,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) die->offset.sect_off, objfile_name (cu->objfile)); attr = dwarf2_attr (die, DW_AT_upper_bound, cu); - if (attr) - { - if (attr_form_is_block (attr) || attr_form_is_ref (attr)) - { - /* GCC encodes arrays with unspecified or dynamic length - with a DW_FORM_block1 attribute or a reference attribute. - FIXME: GDB does not yet know how to handle dynamic - arrays properly, treat them as arrays with unspecified - length for now. - - FIXME: jimb/2003-09-22: GDB does not really know - how to handle arrays of unspecified length - either; we just represent them as zero-length - arrays. Choose an appropriate upper bound given - the lower bound we've computed above. */ - high.data.const_val = low.data.const_val - 1; - } - else - high.data.const_val = dwarf2_get_attr_constant_value (attr, 1); - } - else + if (!attr_to_dynamic_prop (attr, die, cu, &high)) { attr = dwarf2_attr (die, DW_AT_count, cu); if (attr) @@ -14569,12 +14627,6 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) range_type = create_range_type (NULL, orig_base_type, &low, &high); - /* Mark arrays with dynamic length at least as an array of unspecified - length. GDB could check the boundary but before it gets implemented at - least allow accessing the array elements. */ - if (attr && attr_form_is_block (attr)) - TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED; - /* Ada expects an empty array on no boundary attributes. */ if (attr == NULL && cu->language != language_ada) TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED; -- cgit v1.1