+2015-01-29 Joel Brobecker <brobecker@adacore.com>
+
+ * gdbtypes.h (struct dynamic_prop): New PROP_ADDR_OFFSET enum
+ kind.
+ * gdbtypes.c (resolve_dynamic_type_internal): Replace "addr"
+ parameter by "addr_stack" parameter.
+ (resolve_dynamic_range): Replace "addr" parameter by
+ "stack_addr" parameter. Update function documentation.
+ Update code accordingly.
+ (resolve_dynamic_array, resolve_dynamic_union)
+ (resolve_dynamic_struct, resolve_dynamic_type_internal): Likewise.
+ (resolve_dynamic_type): Update code, following the changes made
+ to resolve_dynamic_type_internal's interface.
+ * dwarf2loc.h (struct property_addr_info): New.
+ (dwarf2_evaluate_property): Replace "address" parameter
+ by "addr_stack" parameter. Adjust function documentation.
+ (struct dwarf2_offset_baton): New.
+ (struct dwarf2_property_baton): Update documentation of
+ field "referenced_type" to be more general. New field
+ "offset_info" in union data field.
+ * dwarf2loc.c (dwarf2_evaluate_property): Replace "address"
+ parameter by "addr_stack" parameter. Adjust code accordingly.
+ Add support for PROP_ADDR_OFFSET properties.
+ * dwarf2read.c (attr_to_dynamic_prop): Add support for
+ DW_AT_data_member_location attributes as well. Use case
+ statements instead of if/else condition.
+
2015-01-29 Joel Brobecker <brobecker@adacore.com>
* ada-varobj.c (ada_varobj_get_array_number_of_children):
int
dwarf2_evaluate_property (const struct dynamic_prop *prop,
- CORE_ADDR address, CORE_ADDR *value)
+ struct property_addr_info *addr_stack,
+ CORE_ADDR *value)
{
if (prop == NULL)
return 0;
{
const struct dwarf2_property_baton *baton = prop->data.baton;
- if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
+ if (dwarf2_locexpr_baton_eval (&baton->locexpr, addr_stack->addr,
+ value))
{
if (baton->referenced_type)
{
case PROP_CONST:
*value = prop->data.const_val;
return 1;
+
+ case PROP_ADDR_OFFSET:
+ {
+ struct dwarf2_property_baton *baton = prop->data.baton;
+ struct property_addr_info *pinfo;
+ struct value *val;
+
+ for (pinfo = addr_stack; pinfo != NULL; pinfo = pinfo->next)
+ if (pinfo->type == baton->referenced_type)
+ break;
+ if (pinfo == NULL)
+ error ("cannot find reference address for offset property");
+ val = value_at (baton->offset_info.type,
+ pinfo->addr + baton->offset_info.offset);
+ *value = value_as_address (val);
+ return 1;
+ }
}
return 0;
size_t size,
struct dwarf2_per_cu_data *per_cu);
-/* Converts a dynamic property into a static one. ADDRESS is the address
- of the object currently being evaluated and might be nedded.
+/* A chain of addresses that might be needed to resolve a dynamic
+ property. */
+
+struct property_addr_info
+{
+ /* The type of the object whose dynamic properties, if any, are
+ being resolved. */
+ struct type *type;
+
+ /* The address of that object. */
+ CORE_ADDR addr;
+
+ /* If not NULL, a pointer to the info for the object containing
+ the object described by this node. */
+ struct property_addr_info *next;
+};
+
+/* Converts a dynamic property into a static one. ADDR_STACK is the stack
+ of addresses that might be needed to evaluate the property.
Returns 1 if PROP could be converted and the static value is passed back
into VALUE, otherwise returns 0. */
int dwarf2_evaluate_property (const struct dynamic_prop *prop,
- CORE_ADDR address,
+ struct property_addr_info *addr_stack,
CORE_ADDR *value);
/* A helper for the compiler interface that compiles a single dynamic
unsigned char from_dwo;
};
+/* The baton used when a dynamic property is an offset to a parent
+ type. This can be used, for instance, then the bound of an array
+ inside a record is determined by the value of another field inside
+ that record. */
+
+struct dwarf2_offset_baton
+{
+ /* The offset from the parent type where the value of the property
+ is stored. In the example provided above, this would be the offset
+ of the field being used as the array bound. */
+ LONGEST offset;
+
+ /* The type of the object whose property is dynamic. In the example
+ provided above, this would the the array's index type. */
+ struct type *type;
+};
+
/* A dynamic property is either expressed as a single location expression
or a location list. If the property is an indirection, pointing to
another die, keep track of the targeted type in REFERENCED_TYPE. */
struct dwarf2_property_baton
{
/* If the property is an indirection, we need to evaluate the location
- LOCEXPR or LOCLIST in the context of the type REFERENCED_TYPE.
+ in the context of the type REFERENCED_TYPE.
If NULL, the location is the actual value of the property. */
struct type *referenced_type;
union
/* Location list to be evaluated in the context of REFERENCED_TYPE. */
struct dwarf2_loclist_baton loclist;
+
+ /* The location is an offset to REFERENCED_TYPE. */
+ struct dwarf2_offset_baton offset_info;
};
};
target_die = follow_die_ref (die, attr, &target_cu);
target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+ if (target_attr == NULL)
+ target_attr = dwarf2_attr (target_die, DW_AT_data_member_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
+ switch (target_attr->name)
{
- dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
- "dynamic property");
- return 0;
+ case DW_AT_location:
+ 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;
+ }
+ break;
+ case DW_AT_data_member_location:
+ {
+ LONGEST offset;
+
+ if (!handle_data_member_location (target_die, target_cu,
+ &offset))
+ return 0;
+
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = get_die_type (target_die->parent,
+ target_cu);
+ baton->offset_info.offset = offset;
+ baton->offset_info.type = die_type (target_die, target_cu);
+ prop->data.baton = baton;
+ prop->kind = PROP_ADDR_OFFSET;
+ break;
+ }
}
}
else if (attr_form_is_constant (attr))
return is_dynamic_type_internal (type, 1);
}
-static struct type *resolve_dynamic_type_internal (struct type *type,
- CORE_ADDR addr,
- int top_level);
+static struct type *resolve_dynamic_type_internal
+ (struct type *type, struct property_addr_info *addr_stack, int top_level);
-/* Given a dynamic range type (dyn_range_type) and address,
- return a static version of that type. */
+/* Given a dynamic range type (dyn_range_type) and a stack of
+ struct property_addr_info elements, return a static version
+ of that type. */
static struct type *
-resolve_dynamic_range (struct type *dyn_range_type, CORE_ADDR addr)
+resolve_dynamic_range (struct type *dyn_range_type,
+ struct property_addr_info *addr_stack)
{
CORE_ADDR value;
struct type *static_range_type, *static_target_type;
gdb_assert (TYPE_CODE (dyn_range_type) == TYPE_CODE_RANGE);
prop = &TYPE_RANGE_DATA (dyn_range_type)->low;
- if (dwarf2_evaluate_property (prop, addr, &value))
+ if (dwarf2_evaluate_property (prop, addr_stack, &value))
{
low_bound.kind = PROP_CONST;
low_bound.data.const_val = value;
}
prop = &TYPE_RANGE_DATA (dyn_range_type)->high;
- if (dwarf2_evaluate_property (prop, addr, &value))
+ if (dwarf2_evaluate_property (prop, addr_stack, &value))
{
high_bound.kind = PROP_CONST;
high_bound.data.const_val = value;
static_target_type
= resolve_dynamic_type_internal (TYPE_TARGET_TYPE (dyn_range_type),
- addr, 0);
+ addr_stack, 0);
static_range_type = create_range_type (copy_type (dyn_range_type),
static_target_type,
&low_bound, &high_bound);
}
/* Resolves dynamic bound values of an array type TYPE to static ones.
- ADDRESS might be needed to resolve the subrange bounds, it is the location
- of the associated array. */
+ ADDR_STACK is a stack of struct property_addr_info to be used
+ if needed during the dynamic resolution. */
static struct type *
-resolve_dynamic_array (struct type *type, CORE_ADDR addr)
+resolve_dynamic_array (struct type *type,
+ struct property_addr_info *addr_stack)
{
CORE_ADDR value;
struct type *elt_type;
elt_type = type;
range_type = check_typedef (TYPE_INDEX_TYPE (elt_type));
- range_type = resolve_dynamic_range (range_type, addr);
+ range_type = resolve_dynamic_range (range_type, addr_stack);
ary_dim = check_typedef (TYPE_TARGET_TYPE (elt_type));
if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
- elt_type = resolve_dynamic_array (TYPE_TARGET_TYPE (type), addr);
+ elt_type = resolve_dynamic_array (TYPE_TARGET_TYPE (type), addr_stack);
else
elt_type = TYPE_TARGET_TYPE (type);
}
/* Resolve dynamic bounds of members of the union TYPE to static
- bounds. */
+ bounds. ADDR_STACK is a stack of struct property_addr_info
+ to be used if needed during the dynamic resolution. */
static struct type *
-resolve_dynamic_union (struct type *type, CORE_ADDR addr)
+resolve_dynamic_union (struct type *type,
+ struct property_addr_info *addr_stack)
{
struct type *resolved_type;
int i;
continue;
t = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
- addr, 0);
+ addr_stack, 0);
TYPE_FIELD_TYPE (resolved_type, i) = t;
if (TYPE_LENGTH (t) > max_len)
max_len = TYPE_LENGTH (t);
}
/* Resolve dynamic bounds of members of the struct TYPE to static
- bounds. */
+ bounds. ADDR_STACK is a stack of struct property_addr_info to
+ be used if needed during the dynamic resolution. */
static struct type *
-resolve_dynamic_struct (struct type *type, CORE_ADDR addr)
+resolve_dynamic_struct (struct type *type,
+ struct property_addr_info *addr_stack)
{
struct type *resolved_type;
int i;
for (i = 0; i < TYPE_NFIELDS (resolved_type); ++i)
{
unsigned new_bit_length;
+ struct property_addr_info pinfo;
if (field_is_static (&TYPE_FIELD (type, i)))
continue;
- TYPE_FIELD_TYPE (resolved_type, i)
- = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
- addr, 0);
-
/* As we know this field is not a static field, the field's
field_loc_kind should be FIELD_LOC_KIND_BITPOS. Verify
this is the case, but only trigger a simple error rather
that verification indicates a bug in our code, the error
is not severe enough to suggest to the user he stops
his debugging session because of it. */
- if (TYPE_FIELD_LOC_KIND (resolved_type, i) != FIELD_LOC_KIND_BITPOS)
+ if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_BITPOS)
error (_("Cannot determine struct field location"
" (invalid location kind)"));
+
+ pinfo.type = check_typedef (TYPE_FIELD_TYPE (type, i));
+ pinfo.addr = addr_stack->addr;
+ pinfo.next = addr_stack;
+
+ TYPE_FIELD_TYPE (resolved_type, i)
+ = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
+ &pinfo, 0);
+ gdb_assert (TYPE_FIELD_LOC_KIND (resolved_type, i)
+ == FIELD_LOC_KIND_BITPOS);
+
new_bit_length = TYPE_FIELD_BITPOS (resolved_type, i);
if (TYPE_FIELD_BITSIZE (resolved_type, i) != 0)
new_bit_length += TYPE_FIELD_BITSIZE (resolved_type, i);
/* Worker for resolved_dynamic_type. */
static struct type *
-resolve_dynamic_type_internal (struct type *type, CORE_ADDR addr,
+resolve_dynamic_type_internal (struct type *type,
+ struct property_addr_info *addr_stack,
int top_level)
{
struct type *real_type = check_typedef (type);
{
resolved_type = copy_type (type);
TYPE_TARGET_TYPE (resolved_type)
- = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type), addr,
+ = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type), addr_stack,
top_level);
}
else
{
case TYPE_CODE_REF:
{
- CORE_ADDR target_addr = read_memory_typed_address (addr, type);
+ struct property_addr_info pinfo;
+
+ pinfo.type = check_typedef (TYPE_TARGET_TYPE (type));
+ pinfo.addr = read_memory_typed_address (addr_stack->addr, type);
+ pinfo.next = addr_stack;
resolved_type = copy_type (type);
TYPE_TARGET_TYPE (resolved_type)
= resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type),
- target_addr, top_level);
+ &pinfo, top_level);
break;
}
case TYPE_CODE_ARRAY:
- resolved_type = resolve_dynamic_array (type, addr);
+ resolved_type = resolve_dynamic_array (type, addr_stack);
break;
case TYPE_CODE_RANGE:
- resolved_type = resolve_dynamic_range (type, addr);
+ resolved_type = resolve_dynamic_range (type, addr_stack);
break;
case TYPE_CODE_UNION:
- resolved_type = resolve_dynamic_union (type, addr);
+ resolved_type = resolve_dynamic_union (type, addr_stack);
break;
case TYPE_CODE_STRUCT:
- resolved_type = resolve_dynamic_struct (type, addr);
+ resolved_type = resolve_dynamic_struct (type, addr_stack);
break;
}
}
/* Resolve data_location attribute. */
prop = TYPE_DATA_LOCATION (resolved_type);
- if (dwarf2_evaluate_property (prop, addr, &value))
+ if (dwarf2_evaluate_property (prop, addr_stack, &value))
{
TYPE_DATA_LOCATION_ADDR (resolved_type) = value;
TYPE_DATA_LOCATION_KIND (resolved_type) = PROP_CONST;
struct type *
resolve_dynamic_type (struct type *type, CORE_ADDR addr)
{
- return resolve_dynamic_type_internal (type, addr, 1);
+ struct property_addr_info pinfo = {check_typedef (type), addr, NULL};
+
+ return resolve_dynamic_type_internal (type, &pinfo, 1);
}
/* Find the real type of TYPE. This function returns the real type,
{
PROP_UNDEFINED, /* Not defined. */
PROP_CONST, /* Constant. */
+ PROP_ADDR_OFFSET, /* Address offset. */
PROP_LOCEXPR, /* Location expression. */
PROP_LOCLIST /* Location list. */
} kind;
+2015-01-29 Joel Brobecker <brobecker@adacore.com>
+
+ * gdb.ada/disc_arr_bound: New testcase.
+
2015-01-29 Joel Brobecker <brobecker@adacore.com>
* gdb.ada/mi_var_array: New testcase.
--- /dev/null
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+standard_ada_testfile foo_n612_026
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/foo_n612_026.adb]
+if ![runto "foo_n612_026.adb:$bp_location" ] then {
+ perror "Couldn't run ${testfile}"
+ return
+}
+
+gdb_test "print r" \
+ " = \\(n => 10, a => \\(10, 20, 30, 40, 50, 60, 70, 80, 90, 100\\)\\)"
+
+gdb_test "print r.a" \
+ " = \\(10, 20, 30, 40, 50, 60, 70, 80, 90, 100\\)"
--- /dev/null
+-- Copyright 2015 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+with Pck; use Pck;
+
+procedure Foo_N612_026 is
+ R : Record_Type := Get (10);
+begin
+ Do_Nothing (R'Address); -- STOP
+end Foo_N612_026;
--- /dev/null
+-- Copyright 2015 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package body Pck is
+
+ function Get (N : Integer) return Record_Type is
+ Result : Record_Type (N);
+ begin
+ for I in 1 .. N loop
+ Result.A (I) := 10 * I;
+ end loop;
+ return Result;
+ end Get;
+
+ procedure Do_Nothing (A : System.Address) is
+ begin
+ null;
+ end Do_Nothing;
+
+end Pck;
--- /dev/null
+-- Copyright 2015 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+with System;
+
+package Pck is
+
+ type Array_Type is array (Integer range <>) of Integer;
+ type Record_Type (N : Integer) is record
+ A : Array_Type (1 .. N);
+ end record;
+
+ function Get (N : Integer) return Record_Type;
+
+ procedure Do_Nothing (A : System.Address);
+
+end Pck;