diff mbox

[v6,03/15] type: add c99 variable length array support

Message ID 1397133617-26681-4-git-send-email-sanimir.agovic@intel.com
State Committed
Headers show

Commit Message

Agovic, Sanimir April 10, 2014, 12:40 p.m. UTC
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 <repeats 42 times>}

2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

	* 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.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/dwarf2loc.c  | 119 +++++++++++++++++++++++++++++++++
 gdb/dwarf2loc.h  |  28 ++++++++
 gdb/dwarf2read.c | 106 +++++++++++++++++++++--------
 gdb/gdbtypes.c   | 199 +++++++++++++++++++++++++++++++++++++++++--------------
 gdb/gdbtypes.h   |  10 +++
 gdb/valops.c     |  15 ++++-
 gdb/value.c      |  19 ++++--
 7 files changed, 409 insertions(+), 87 deletions(-)

Comments

Joel Brobecker April 10, 2014, 2:21 p.m. UTC | #1
On Thu, Apr 10, 2014 at 02:40:05PM +0200, Sanimir Agovic wrote:
> 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 <repeats 42 times>}
> 
> 2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell  <keven.boell@intel.com>
> 
> 	* 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.

LGTM. Pre-approved with the following minor corrections outlined below.
It's nice to see that there were even more simplifications that could
be made after abandonning types deep copies!

> 
> 
> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/dwarf2loc.c  | 119 +++++++++++++++++++++++++++++++++
>  gdb/dwarf2loc.h  |  28 ++++++++
>  gdb/dwarf2read.c | 106 +++++++++++++++++++++--------
>  gdb/gdbtypes.c   | 199 +++++++++++++++++++++++++++++++++++++++++--------------
>  gdb/gdbtypes.h   |  10 +++
>  gdb/valops.c     |  15 ++++-
>  gdb/value.c      |  19 ++++--
>  7 files changed, 409 insertions(+), 87 deletions(-)
> 
> diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
> index 2b1f323..d903322 100644
> --- a/gdb/dwarf2loc.c
> +++ b/gdb/dwarf2loc.c
> @@ -2431,6 +2431,125 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
>    return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0);
>  }
>  
> +/* Evaluates a dwarf expression and stores the result in VAL, expecting
> +   that the dwarf expression only produces a single CORE_ADDR.  ADDR is a
> +   context (location of a variable) and might be needed to evaluate the
> +   location expression.
> +   Returns 1 on success, 0 otherwise.   */
> +
> +static int
> +dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
> +			   CORE_ADDR addr, CORE_ADDR *valp)
> +{
> +  struct dwarf_expr_context *ctx;
> +  struct dwarf_expr_baton baton;
> +  struct objfile *objfile;
> +  struct cleanup *cleanup;
> +
> +  if (dlbaton == NULL || dlbaton->size == 0)
> +    return 0;
> +
> +  ctx = new_dwarf_expr_context ();
> +  cleanup = make_cleanup_free_dwarf_expr_context (ctx);
> +
> +  baton.frame = get_selected_frame (NULL);
> +  baton.per_cu = dlbaton->per_cu;
> +
> +  objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
> +
> +  ctx->gdbarch = get_objfile_arch (objfile);
> +  ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
> +  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
> +  ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
> +  ctx->funcs = &dwarf_expr_ctx_funcs;
> +  ctx->baton = &baton;
> +
> +  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
> +
> +  switch (ctx->location)
> +    {
> +    case DWARF_VALUE_REGISTER:
> +    case DWARF_VALUE_MEMORY:
> +    case DWARF_VALUE_STACK:
> +      *valp = dwarf_expr_fetch_address (ctx, 0);
> +      if (ctx->location == DWARF_VALUE_REGISTER)
> +	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
> +      do_cleanups (cleanup);
> +      return 1;
> +    case DWARF_VALUE_LITERAL:
> +      *valp = extract_signed_integer (ctx->data, ctx->len,
> +				      gdbarch_byte_order (ctx->gdbarch));
> +      do_cleanups (cleanup);
> +      return 1;
> +      /* Unsupported dwarf values.  */
> +    case DWARF_VALUE_OPTIMIZED_OUT:
> +    case DWARF_VALUE_IMPLICIT_POINTER:
> +      break;
> +    }
> +
> +  do_cleanups (cleanup);
> +  return 0;
> +}
> +
> +/* See dwarf2loc.h.  */
> +
> +int
> +dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR address,
> +			  CORE_ADDR *value)
> +{
> +  if (prop == NULL)
> +    return 0;
> +
> +  switch (prop->kind)
> +    {
> +    case PROP_LOCEXPR:
> +      {
> +	const struct dwarf2_property_baton *baton = prop->data.baton;
> +
> +	if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
> +	  {
> +	    if (baton->referenced_type)
> +	      {
> +		struct value *val = value_at (baton->referenced_type, *value);
> +
> +		*value = value_as_address (val);
> +	      }
> +	    return 1;
> +	  }
> +      }
> +      break;
> +
> +    case PROP_LOCLIST:
> +      {
> +	struct dwarf2_property_baton *baton = prop->data.baton;
> +	struct frame_info *frame = get_selected_frame (NULL);
> +	CORE_ADDR pc = get_frame_address_in_block (frame);
> +	const gdb_byte *data;
> +	struct value *val;
> +	size_t size;
> +
> +	data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
> +	if (data != NULL)
> +	  {
> +	    val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data,
> +					    size, baton->loclist.per_cu);
> +	    if (!value_optimized_out (val))
> +	      {
> +		*value = value_as_address (val);
> +		return 1;
> +	      }
> +	  }
> +      }
> +      break;
> +
> +    case PROP_CONST:
> +      *value = prop->data.const_val;
> +      return 1;
> +    }
> +
> +  return 0;
> +}
> +
>  
>  /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
>  
> diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
> index 9bc8ca5..94d9c5f 100644
> --- a/gdb/dwarf2loc.h
> +++ b/gdb/dwarf2loc.h
> @@ -90,6 +90,14 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type,
>  					size_t size,
>  					struct dwarf2_per_cu_data *per_cu);
>  
> +/* Converts a dynamic property into a static one.  ADDR is the address of
> +   the object currently being evaluated and might be nedded.
> +   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 addr, CORE_ADDR *value);
> +
>  CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
>  				  unsigned int addr_index);
>  
> @@ -135,6 +143,26 @@ struct dwarf2_loclist_baton
>    unsigned char from_dwo;
>  };
>  
> +/* 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.
> +     If NULL, the location is the actual value of the property.  */
> +  struct type *referenced_type;
> +  union
> +  {
> +    /* Location expression.  */
> +    struct dwarf2_locexpr_baton locexpr;
> +
> +    /* Location list to be evaluated in the context of TYPE.  */
> +    struct dwarf2_loclist_baton loclist;

I missed that one in my first review, but I think you meant
REFERENCED_TYPE, rather than TYPE?

> +  };
> +};
> +
>  extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
>  extern const struct symbol_computed_ops dwarf2_loclist_funcs;
>  
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 101065b..436d0db 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -14252,6 +14252,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 *
> @@ -14325,27 +14403,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)
> @@ -14409,12 +14467,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;
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 7f0269c..ce582f8 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -853,6 +853,17 @@ create_static_range_type (struct type *result_type, struct type *index_type,
>    return result_type;
>  }
>  
> +/* Predicate tests whether BOUNDS are static.  Returns 1 if all bounds values
> +   are static, otherwise returns 0.  */
> +
> +static int
> +has_static_range (const struct range_bounds *bounds)
> +{
> +  return (bounds->low.kind == PROP_CONST
> +	  && bounds->high.kind == PROP_CONST);
> +}
> +
> +
>  /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
>     TYPE.  Return 1 if type is a range type, 0 if it is discrete (and
>     bounds will fit in LONGEST), or -1 otherwise.  */
> @@ -982,24 +993,31 @@ create_array_type (struct type *result_type,
>  		   struct type *element_type,
>  		   struct type *range_type)
>  {
> -  LONGEST low_bound, high_bound;
> -
>    if (result_type == NULL)
>      result_type = alloc_type_copy (range_type);
>  
>    TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
>    TYPE_TARGET_TYPE (result_type) = element_type;
> -  if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
> -    low_bound = high_bound = 0;
> -  CHECK_TYPEDEF (element_type);
> -  /* Be careful when setting the array length.  Ada arrays can be
> -     empty arrays with the high_bound being smaller than the low_bound.
> -     In such cases, the array length should be zero.  */
> -  if (high_bound < low_bound)
> -    TYPE_LENGTH (result_type) = 0;
> +
> +  if (has_static_range (TYPE_RANGE_DATA (range_type)))
> +    {
> +      LONGEST low_bound, high_bound;
> +
> +      if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
> +	low_bound = high_bound = 0;
> +      CHECK_TYPEDEF (element_type);
> +      /* Be careful when setting the array length.  Ada arrays can be
> +	 empty arrays with the high_bound being smaller than the low_bound.
> +	 In such cases, the array length should be zero.  */
> +      if (high_bound < low_bound)
> +	TYPE_LENGTH (result_type) = 0;
> +      else
> +	TYPE_LENGTH (result_type) =
> +	  TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
> +    }
>    else
> -    TYPE_LENGTH (result_type) =
> -      TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
> +    TYPE_LENGTH (result_type) = 0;

Thanks for making that change. I think it'd be worth while explaining
why we set the length to zero. How about the following:

  else
    {
      /* This type is dynamic and its length needs to be computed
         on demand.  In the meantime, avoid leaving the TYPE_LENGTH
         undefined by setting it to zero.  Although we are not expected
         to trust TYPE_LENGTH in this case, setting the size to zero
         allows us to avoid allocating objects of random sizes in case
         we accidently do.  */
      TYPE_LENGTH (result_type) = 0;
    }

> +
>    TYPE_NFIELDS (result_type) = 1;
>    TYPE_FIELDS (result_type) =
>      (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));
> @@ -1530,6 +1548,124 @@ stub_noname_complaint (void)
>    complaint (&symfile_complaints, _("stub type has NULL name"));
>  }
>  
> +/* See gdbtypes.h.  */
> +
> +int
> +is_dynamic_type (struct type *type)
> +{
> +  type = check_typedef (type);
> +
> +  if (TYPE_CODE (type) == TYPE_CODE_REF)
> +    type = check_typedef (TYPE_TARGET_TYPE (type));
> +
> +  switch (TYPE_CODE (type))
> +    {
> +    case TYPE_CODE_ARRAY:
> +      {
> +	const struct type *range_type;
> +
> +	gdb_assert (TYPE_NFIELDS (type) == 1);
> +	range_type = TYPE_INDEX_TYPE (type);
> +	if (!has_static_range (TYPE_RANGE_DATA (range_type)))
> +	  return 1;
> +	else
> +	  return is_dynamic_type (TYPE_TARGET_TYPE (type));
> +	break;
> +      }
> +    default:
> +      return 0;
> +      break;
> +    }
> +}
> +
> +/* 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.  */
> +
> +static struct type *
> +resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
> +{
> +  CORE_ADDR value;
> +  struct type *elt_type;
> +  struct type *range_type;
> +  struct type *ary_dim;
> +  const struct dynamic_prop *prop;
> +  const struct dwarf2_locexpr_baton *baton;
> +  struct dynamic_prop low_bound, high_bound;
> +
> +  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
> +    {
> +      struct type *copy = copy_type (type);
> +
> +      TYPE_TARGET_TYPE (copy)
> +	= resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
> +
> +      return copy;
> +    }
> +
> +  gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
> +
> +  elt_type = type;
> +  range_type = check_typedef (TYPE_INDEX_TYPE (elt_type));
> +
> +  prop = &TYPE_RANGE_DATA (range_type)->low;
> +  if (dwarf2_evaluate_property (prop, addr, &value))
> +    {
> +      low_bound.kind = PROP_CONST;
> +      low_bound.data.const_val = value;
> +    }
> +  else
> +    {
> +      low_bound.kind = PROP_UNDEFINED;
> +      low_bound.data.const_val = 0;
> +    }
> +
> +  prop = &TYPE_RANGE_DATA (range_type)->high;
> +  if (dwarf2_evaluate_property (prop, addr, &value))
> +    {
> +      high_bound.kind = PROP_CONST;
> +      high_bound.data.const_val = value;
> +    }
> +  else
> +    {
> +      high_bound.kind = PROP_UNDEFINED;
> +      high_bound.data.const_val = 0;
> +    }
> +
> +  ary_dim = check_typedef (TYPE_TARGET_TYPE (elt_type));
> +
> +  if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
> +    elt_type = resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
> +  else
> +    elt_type = TYPE_TARGET_TYPE (type);
> +
> +  range_type
> +    = create_range_type (NULL,
> +			 TYPE_TARGET_TYPE (range_type),
> +			 &low_bound, &high_bound);

There was a small nit-pick request here, and since you're going to be
touching this code again (see below), would you mind...

Joel> Small formatting nit-pick (while we're touching this code):
Joel>
Joel>   range_type = create_range_type (NULL,
Joel>                                   TYPE_TARGET_TYPE (range_type),
Joel>                                   &low_bound, &high_bound);

> +  elt_type = create_array_type (copy_type (type),
> +				elt_type,
> +				range_type);
> +
> +  return elt_type;

Can you avoid assigning the array types being created to elt_type
(possibly confusing), and just do...

    return create_array_type (copy_type (type), elt_type, range_type);

... instead?


> +}
> +
> +/* See gdbtypes.h  */
> +
> +struct type *
> +resolve_dynamic_type (struct type *type, CORE_ADDR addr)
> +{
> +  struct type *real_type = check_typedef (type);
> +  struct type *resolved_type;
> +
> +  if (!is_dynamic_type (real_type))
> +    return type;
> +
> +  resolved_type = resolve_dynamic_bounds (type, addr);
> +
> +  return resolved_type;
> +}
> +
>  /* Find the real type of TYPE.  This function returns the real type,
>     after removing all layers of typedefs, and completing opaque or stub
>     types.  Completion changes the TYPE argument, but stripping of
> @@ -1705,45 +1841,6 @@ check_typedef (struct type *type)
>  	{
>  	  /* Nothing we can do.  */
>  	}
> -      else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> -	       && TYPE_NFIELDS (type) == 1
> -	       && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type))
> -		   == TYPE_CODE_RANGE))
> -	{
> -	  /* Now recompute the length of the array type, based on its
> -	     number of elements and the target type's length.
> -	     Watch out for Ada null Ada arrays where the high bound
> -	     is smaller than the low bound.  */
> -	  const LONGEST low_bound = TYPE_LOW_BOUND (range_type);
> -	  const LONGEST high_bound = TYPE_HIGH_BOUND (range_type);
> -	  ULONGEST len;
> -
> -	  if (high_bound < low_bound)
> -	    len = 0;
> -	  else
> -	    {
> -	      /* For now, we conservatively take the array length to be 0
> -		 if its length exceeds UINT_MAX.  The code below assumes
> -		 that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
> -		 which is technically not guaranteed by C, but is usually true
> -		 (because it would be true if x were unsigned with its
> -		 high-order bit on).  It uses the fact that
> -		 high_bound-low_bound is always representable in
> -		 ULONGEST and that if high_bound-low_bound+1 overflows,
> -		 it overflows to 0.  We must change these tests if we 
> -		 decide to increase the representation of TYPE_LENGTH
> -		 from unsigned int to ULONGEST.  */
> -	      ULONGEST ulow = low_bound, uhigh = high_bound;
> -	      ULONGEST tlen = TYPE_LENGTH (target_type);
> -
> -	      len = tlen * (uhigh - ulow + 1);
> -	      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh 
> -		  || len > UINT_MAX)
> -		len = 0;
> -	    }
> -	  TYPE_LENGTH (type) = len;
> -	  TYPE_TARGET_STUB (type) = 0;
> -	}
>        else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
>  	{
>  	  TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index f6e68c5..36e4a5f 100644
> --- a/gdb/gdbtypes.h
> +++ b/gdb/gdbtypes.h
> @@ -1,3 +1,4 @@
> +
>  /* Internal type definitions for GDB.
>  
>     Copyright (C) 1992-2013 Free Software Foundation, Inc.
> @@ -1574,6 +1575,15 @@ extern struct type *lookup_unsigned_typename (const struct language_defn *,
>  extern struct type *lookup_signed_typename (const struct language_defn *,
>  					    struct gdbarch *, const char *);
>  
> +/* Resolve all dynamic values of a type e.g. array bounds to static values.
> +   ADDR specifies the location of the variable the type is bound to.
> +   If TYPE has no dynamic properties return TYPE; otherwise a new type with
> +   static properties is returned.  */
> +extern struct type *resolve_dynamic_type (struct type *type, CORE_ADDR addr);
> +
> +/* Predicate if the type has dynamic values, which are not resolved yet.  */
> +extern int is_dynamic_type (struct type *type);
> +
>  extern struct type *check_typedef (struct type *);
>  
>  #define CHECK_TYPEDEF(TYPE)			\
> diff --git a/gdb/valops.c b/gdb/valops.c
> index 5c7bb89..eefa8c6 100644
> --- a/gdb/valops.c
> +++ b/gdb/valops.c
> @@ -902,7 +902,10 @@ value_one (struct type *type)
>    return val;
>  }
>  
> -/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.  */
> +/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.
> +   The type of the created value may differ from the passed type TYPE.
> +   Make sure to retrieve the returned values's new type after this call
> +   e.g. in case the type is a variable length array.  */
>  
>  static struct value *
>  get_value_at (struct type *type, CORE_ADDR addr, int lazy)
> @@ -927,7 +930,10 @@ get_value_at (struct type *type, CORE_ADDR addr, int lazy)
>     value_at_lazy instead.  value_at_lazy simply records the address of
>     the data and sets the lazy-evaluation-required flag.  The lazy flag
>     is tested in the value_contents macro, which is used if and when
> -   the contents are actually required.
> +   the contents are actually required.  The type of the created value
> +   may differ from the passed type TYPE.  Make sure to retrieve the
> +   returned values's new type after this call e.g. in case the type
> +   is a variable length array.
>  
>     Note: value_at does *NOT* handle embedded offsets; perform such
>     adjustments before or after calling it.  */
> @@ -938,7 +944,10 @@ value_at (struct type *type, CORE_ADDR addr)
>    return get_value_at (type, addr, 0);
>  }
>  
> -/* Return a lazy value with type TYPE located at ADDR (cf. value_at).  */
> +/* Return a lazy value with type TYPE located at ADDR (cf. value_at).
> +   The type of the created value may differ from the passed type TYPE.
> +   Make sure to retrieve the returned values's new type after this call
> +   e.g. in case the type is a variable length array.  */
>  
>  struct value *
>  value_at_lazy (struct type *type, CORE_ADDR addr)
> diff --git a/gdb/value.c b/gdb/value.c
> index a64e7e1..993157f 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -3178,32 +3178,39 @@ value_from_ulongest (struct type *type, ULONGEST num)
>  
>  
>  /* Create a value representing a pointer of type TYPE to the address
> -   ADDR.  */
> +   ADDR.  The type of the created value may differ from the passed
> +   type TYPE. Make sure to retrieve the returned values's new type
> +   after this call e.g. in case of an variable length array.  */
> +
>  struct value *
>  value_from_pointer (struct type *type, CORE_ADDR addr)
>  {
> -  struct value *val = allocate_value (type);
> +  struct type *resolved_type = resolve_dynamic_type (type, addr);
> +  struct value *val = allocate_value (resolved_type);
>  
> -  store_typed_address (value_contents_raw (val), check_typedef (type), addr);
> +  store_typed_address (value_contents_raw (val),
> +		       check_typedef (resolved_type), addr);
>    return val;
>  }
>  
>  
>  /* Create a value of type TYPE whose contents come from VALADDR, if it
>     is non-null, and whose memory address (in the inferior) is
> -   ADDRESS.  */
> +   ADDRESS.  The type of the created value may differ from the passed
> +   type TYPE.  Make sure to retrieve values new type after this call.  */
>  
>  struct value *
>  value_from_contents_and_address (struct type *type,
>  				 const gdb_byte *valaddr,
>  				 CORE_ADDR address)
>  {
> +  struct type *resolved_type = resolve_dynamic_type (type, address);
>    struct value *v;
>  
>    if (valaddr == NULL)
> -    v = allocate_value_lazy (type);
> +    v = allocate_value_lazy (resolved_type);
>    else
> -    v = value_from_contents (type, valaddr);
> +    v = value_from_contents (resolved_type, valaddr);
>    set_value_address (v, address);
>    VALUE_LVAL (v) = lval_memory;
>    return v;
> -- 
> 1.8.4.2
diff mbox

Patch

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 2b1f323..d903322 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2431,6 +2431,125 @@  dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
   return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0);
 }
 
+/* Evaluates a dwarf expression and stores the result in VAL, expecting
+   that the dwarf expression only produces a single CORE_ADDR.  ADDR is a
+   context (location of a variable) and might be needed to evaluate the
+   location expression.
+   Returns 1 on success, 0 otherwise.   */
+
+static int
+dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
+			   CORE_ADDR addr, CORE_ADDR *valp)
+{
+  struct dwarf_expr_context *ctx;
+  struct dwarf_expr_baton baton;
+  struct objfile *objfile;
+  struct cleanup *cleanup;
+
+  if (dlbaton == NULL || dlbaton->size == 0)
+    return 0;
+
+  ctx = new_dwarf_expr_context ();
+  cleanup = make_cleanup_free_dwarf_expr_context (ctx);
+
+  baton.frame = get_selected_frame (NULL);
+  baton.per_cu = dlbaton->per_cu;
+
+  objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
+
+  ctx->gdbarch = get_objfile_arch (objfile);
+  ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
+  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
+  ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
+  ctx->funcs = &dwarf_expr_ctx_funcs;
+  ctx->baton = &baton;
+
+  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
+
+  switch (ctx->location)
+    {
+    case DWARF_VALUE_REGISTER:
+    case DWARF_VALUE_MEMORY:
+    case DWARF_VALUE_STACK:
+      *valp = dwarf_expr_fetch_address (ctx, 0);
+      if (ctx->location == DWARF_VALUE_REGISTER)
+	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
+      do_cleanups (cleanup);
+      return 1;
+    case DWARF_VALUE_LITERAL:
+      *valp = extract_signed_integer (ctx->data, ctx->len,
+				      gdbarch_byte_order (ctx->gdbarch));
+      do_cleanups (cleanup);
+      return 1;
+      /* Unsupported dwarf values.  */
+    case DWARF_VALUE_OPTIMIZED_OUT:
+    case DWARF_VALUE_IMPLICIT_POINTER:
+      break;
+    }
+
+  do_cleanups (cleanup);
+  return 0;
+}
+
+/* See dwarf2loc.h.  */
+
+int
+dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR address,
+			  CORE_ADDR *value)
+{
+  if (prop == NULL)
+    return 0;
+
+  switch (prop->kind)
+    {
+    case PROP_LOCEXPR:
+      {
+	const struct dwarf2_property_baton *baton = prop->data.baton;
+
+	if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
+	  {
+	    if (baton->referenced_type)
+	      {
+		struct value *val = value_at (baton->referenced_type, *value);
+
+		*value = value_as_address (val);
+	      }
+	    return 1;
+	  }
+      }
+      break;
+
+    case PROP_LOCLIST:
+      {
+	struct dwarf2_property_baton *baton = prop->data.baton;
+	struct frame_info *frame = get_selected_frame (NULL);
+	CORE_ADDR pc = get_frame_address_in_block (frame);
+	const gdb_byte *data;
+	struct value *val;
+	size_t size;
+
+	data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
+	if (data != NULL)
+	  {
+	    val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data,
+					    size, baton->loclist.per_cu);
+	    if (!value_optimized_out (val))
+	      {
+		*value = value_as_address (val);
+		return 1;
+	      }
+	  }
+      }
+      break;
+
+    case PROP_CONST:
+      *value = prop->data.const_val;
+      return 1;
+    }
+
+  return 0;
+}
+
 
 /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
 
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index 9bc8ca5..94d9c5f 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -90,6 +90,14 @@  struct value *dwarf2_evaluate_loc_desc (struct type *type,
 					size_t size,
 					struct dwarf2_per_cu_data *per_cu);
 
+/* Converts a dynamic property into a static one.  ADDR is the address of
+   the object currently being evaluated and might be nedded.
+   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 addr, CORE_ADDR *value);
+
 CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
 				  unsigned int addr_index);
 
@@ -135,6 +143,26 @@  struct dwarf2_loclist_baton
   unsigned char from_dwo;
 };
 
+/* 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.
+     If NULL, the location is the actual value of the property.  */
+  struct type *referenced_type;
+  union
+  {
+    /* Location expression.  */
+    struct dwarf2_locexpr_baton locexpr;
+
+    /* Location list to be evaluated in the context of TYPE.  */
+    struct dwarf2_loclist_baton loclist;
+  };
+};
+
 extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
 extern const struct symbol_computed_ops dwarf2_loclist_funcs;
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 101065b..436d0db 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14252,6 +14252,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 *
@@ -14325,27 +14403,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)
@@ -14409,12 +14467,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;
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 7f0269c..ce582f8 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -853,6 +853,17 @@  create_static_range_type (struct type *result_type, struct type *index_type,
   return result_type;
 }
 
+/* Predicate tests whether BOUNDS are static.  Returns 1 if all bounds values
+   are static, otherwise returns 0.  */
+
+static int
+has_static_range (const struct range_bounds *bounds)
+{
+  return (bounds->low.kind == PROP_CONST
+	  && bounds->high.kind == PROP_CONST);
+}
+
+
 /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
    TYPE.  Return 1 if type is a range type, 0 if it is discrete (and
    bounds will fit in LONGEST), or -1 otherwise.  */
@@ -982,24 +993,31 @@  create_array_type (struct type *result_type,
 		   struct type *element_type,
 		   struct type *range_type)
 {
-  LONGEST low_bound, high_bound;
-
   if (result_type == NULL)
     result_type = alloc_type_copy (range_type);
 
   TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
   TYPE_TARGET_TYPE (result_type) = element_type;
-  if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
-    low_bound = high_bound = 0;
-  CHECK_TYPEDEF (element_type);
-  /* Be careful when setting the array length.  Ada arrays can be
-     empty arrays with the high_bound being smaller than the low_bound.
-     In such cases, the array length should be zero.  */
-  if (high_bound < low_bound)
-    TYPE_LENGTH (result_type) = 0;
+
+  if (has_static_range (TYPE_RANGE_DATA (range_type)))
+    {
+      LONGEST low_bound, high_bound;
+
+      if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+	low_bound = high_bound = 0;
+      CHECK_TYPEDEF (element_type);
+      /* Be careful when setting the array length.  Ada arrays can be
+	 empty arrays with the high_bound being smaller than the low_bound.
+	 In such cases, the array length should be zero.  */
+      if (high_bound < low_bound)
+	TYPE_LENGTH (result_type) = 0;
+      else
+	TYPE_LENGTH (result_type) =
+	  TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+    }
   else
-    TYPE_LENGTH (result_type) =
-      TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+    TYPE_LENGTH (result_type) = 0;
+
   TYPE_NFIELDS (result_type) = 1;
   TYPE_FIELDS (result_type) =
     (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));
@@ -1530,6 +1548,124 @@  stub_noname_complaint (void)
   complaint (&symfile_complaints, _("stub type has NULL name"));
 }
 
+/* See gdbtypes.h.  */
+
+int
+is_dynamic_type (struct type *type)
+{
+  type = check_typedef (type);
+
+  if (TYPE_CODE (type) == TYPE_CODE_REF)
+    type = check_typedef (TYPE_TARGET_TYPE (type));
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_ARRAY:
+      {
+	const struct type *range_type;
+
+	gdb_assert (TYPE_NFIELDS (type) == 1);
+	range_type = TYPE_INDEX_TYPE (type);
+	if (!has_static_range (TYPE_RANGE_DATA (range_type)))
+	  return 1;
+	else
+	  return is_dynamic_type (TYPE_TARGET_TYPE (type));
+	break;
+      }
+    default:
+      return 0;
+      break;
+    }
+}
+
+/* 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.  */
+
+static struct type *
+resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
+{
+  CORE_ADDR value;
+  struct type *elt_type;
+  struct type *range_type;
+  struct type *ary_dim;
+  const struct dynamic_prop *prop;
+  const struct dwarf2_locexpr_baton *baton;
+  struct dynamic_prop low_bound, high_bound;
+
+  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+    {
+      struct type *copy = copy_type (type);
+
+      TYPE_TARGET_TYPE (copy)
+	= resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
+
+      return copy;
+    }
+
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
+
+  elt_type = type;
+  range_type = check_typedef (TYPE_INDEX_TYPE (elt_type));
+
+  prop = &TYPE_RANGE_DATA (range_type)->low;
+  if (dwarf2_evaluate_property (prop, addr, &value))
+    {
+      low_bound.kind = PROP_CONST;
+      low_bound.data.const_val = value;
+    }
+  else
+    {
+      low_bound.kind = PROP_UNDEFINED;
+      low_bound.data.const_val = 0;
+    }
+
+  prop = &TYPE_RANGE_DATA (range_type)->high;
+  if (dwarf2_evaluate_property (prop, addr, &value))
+    {
+      high_bound.kind = PROP_CONST;
+      high_bound.data.const_val = value;
+    }
+  else
+    {
+      high_bound.kind = PROP_UNDEFINED;
+      high_bound.data.const_val = 0;
+    }
+
+  ary_dim = check_typedef (TYPE_TARGET_TYPE (elt_type));
+
+  if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
+    elt_type = resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
+  else
+    elt_type = TYPE_TARGET_TYPE (type);
+
+  range_type
+    = create_range_type (NULL,
+			 TYPE_TARGET_TYPE (range_type),
+			 &low_bound, &high_bound);
+  elt_type = create_array_type (copy_type (type),
+				elt_type,
+				range_type);
+
+  return elt_type;
+}
+
+/* See gdbtypes.h  */
+
+struct type *
+resolve_dynamic_type (struct type *type, CORE_ADDR addr)
+{
+  struct type *real_type = check_typedef (type);
+  struct type *resolved_type;
+
+  if (!is_dynamic_type (real_type))
+    return type;
+
+  resolved_type = resolve_dynamic_bounds (type, addr);
+
+  return resolved_type;
+}
+
 /* Find the real type of TYPE.  This function returns the real type,
    after removing all layers of typedefs, and completing opaque or stub
    types.  Completion changes the TYPE argument, but stripping of
@@ -1705,45 +1841,6 @@  check_typedef (struct type *type)
 	{
 	  /* Nothing we can do.  */
 	}
-      else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
-	       && TYPE_NFIELDS (type) == 1
-	       && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type))
-		   == TYPE_CODE_RANGE))
-	{
-	  /* Now recompute the length of the array type, based on its
-	     number of elements and the target type's length.
-	     Watch out for Ada null Ada arrays where the high bound
-	     is smaller than the low bound.  */
-	  const LONGEST low_bound = TYPE_LOW_BOUND (range_type);
-	  const LONGEST high_bound = TYPE_HIGH_BOUND (range_type);
-	  ULONGEST len;
-
-	  if (high_bound < low_bound)
-	    len = 0;
-	  else
-	    {
-	      /* For now, we conservatively take the array length to be 0
-		 if its length exceeds UINT_MAX.  The code below assumes
-		 that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
-		 which is technically not guaranteed by C, but is usually true
-		 (because it would be true if x were unsigned with its
-		 high-order bit on).  It uses the fact that
-		 high_bound-low_bound is always representable in
-		 ULONGEST and that if high_bound-low_bound+1 overflows,
-		 it overflows to 0.  We must change these tests if we 
-		 decide to increase the representation of TYPE_LENGTH
-		 from unsigned int to ULONGEST.  */
-	      ULONGEST ulow = low_bound, uhigh = high_bound;
-	      ULONGEST tlen = TYPE_LENGTH (target_type);
-
-	      len = tlen * (uhigh - ulow + 1);
-	      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh 
-		  || len > UINT_MAX)
-		len = 0;
-	    }
-	  TYPE_LENGTH (type) = len;
-	  TYPE_TARGET_STUB (type) = 0;
-	}
       else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
 	{
 	  TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index f6e68c5..36e4a5f 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1,3 +1,4 @@ 
+
 /* Internal type definitions for GDB.
 
    Copyright (C) 1992-2013 Free Software Foundation, Inc.
@@ -1574,6 +1575,15 @@  extern struct type *lookup_unsigned_typename (const struct language_defn *,
 extern struct type *lookup_signed_typename (const struct language_defn *,
 					    struct gdbarch *, const char *);
 
+/* Resolve all dynamic values of a type e.g. array bounds to static values.
+   ADDR specifies the location of the variable the type is bound to.
+   If TYPE has no dynamic properties return TYPE; otherwise a new type with
+   static properties is returned.  */
+extern struct type *resolve_dynamic_type (struct type *type, CORE_ADDR addr);
+
+/* Predicate if the type has dynamic values, which are not resolved yet.  */
+extern int is_dynamic_type (struct type *type);
+
 extern struct type *check_typedef (struct type *);
 
 #define CHECK_TYPEDEF(TYPE)			\
diff --git a/gdb/valops.c b/gdb/valops.c
index 5c7bb89..eefa8c6 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -902,7 +902,10 @@  value_one (struct type *type)
   return val;
 }
 
-/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.  */
+/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.
+   The type of the created value may differ from the passed type TYPE.
+   Make sure to retrieve the returned values's new type after this call
+   e.g. in case the type is a variable length array.  */
 
 static struct value *
 get_value_at (struct type *type, CORE_ADDR addr, int lazy)
@@ -927,7 +930,10 @@  get_value_at (struct type *type, CORE_ADDR addr, int lazy)
    value_at_lazy instead.  value_at_lazy simply records the address of
    the data and sets the lazy-evaluation-required flag.  The lazy flag
    is tested in the value_contents macro, which is used if and when
-   the contents are actually required.
+   the contents are actually required.  The type of the created value
+   may differ from the passed type TYPE.  Make sure to retrieve the
+   returned values's new type after this call e.g. in case the type
+   is a variable length array.
 
    Note: value_at does *NOT* handle embedded offsets; perform such
    adjustments before or after calling it.  */
@@ -938,7 +944,10 @@  value_at (struct type *type, CORE_ADDR addr)
   return get_value_at (type, addr, 0);
 }
 
-/* Return a lazy value with type TYPE located at ADDR (cf. value_at).  */
+/* Return a lazy value with type TYPE located at ADDR (cf. value_at).
+   The type of the created value may differ from the passed type TYPE.
+   Make sure to retrieve the returned values's new type after this call
+   e.g. in case the type is a variable length array.  */
 
 struct value *
 value_at_lazy (struct type *type, CORE_ADDR addr)
diff --git a/gdb/value.c b/gdb/value.c
index a64e7e1..993157f 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3178,32 +3178,39 @@  value_from_ulongest (struct type *type, ULONGEST num)
 
 
 /* Create a value representing a pointer of type TYPE to the address
-   ADDR.  */
+   ADDR.  The type of the created value may differ from the passed
+   type TYPE. Make sure to retrieve the returned values's new type
+   after this call e.g. in case of an variable length array.  */
+
 struct value *
 value_from_pointer (struct type *type, CORE_ADDR addr)
 {
-  struct value *val = allocate_value (type);
+  struct type *resolved_type = resolve_dynamic_type (type, addr);
+  struct value *val = allocate_value (resolved_type);
 
-  store_typed_address (value_contents_raw (val), check_typedef (type), addr);
+  store_typed_address (value_contents_raw (val),
+		       check_typedef (resolved_type), addr);
   return val;
 }
 
 
 /* Create a value of type TYPE whose contents come from VALADDR, if it
    is non-null, and whose memory address (in the inferior) is
-   ADDRESS.  */
+   ADDRESS.  The type of the created value may differ from the passed
+   type TYPE.  Make sure to retrieve values new type after this call.  */
 
 struct value *
 value_from_contents_and_address (struct type *type,
 				 const gdb_byte *valaddr,
 				 CORE_ADDR address)
 {
+  struct type *resolved_type = resolve_dynamic_type (type, address);
   struct value *v;
 
   if (valaddr == NULL)
-    v = allocate_value_lazy (type);
+    v = allocate_value_lazy (resolved_type);
   else
-    v = value_from_contents (type, valaddr);
+    v = value_from_contents (resolved_type, valaddr);
   set_value_address (v, address);
   VALUE_LVAL (v) = lval_memory;
   return v;