This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[4/6] Fortran dynamic arrays #2: Dynamic array bounds
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Sat, 24 Nov 2007 00:44:00 +0100
- Subject: [4/6] Fortran dynamic arrays #2: Dynamic array bounds
aHi,
DW_AT_lower_bound / DW_AT_upper_bound can now have the DW_FORM_block* value.
We recalculate TYPE_LENGTH each time from CHECK_TYPEDEF.
It also sets TYPE_ARRAY_UPPER_BOUND_TYPE to BOUND_CANNOT_BE_DETERMINED where
appropriate (the variable `vart' in the testcase code).
READ_VAR_VALUE has an chicken-and-egg problem. It first allocates VALUE V and
then detects the variable data for it. We need to know the variable size in
the first place to be able to allocate VALUE V with the appropriate size.
Patch provides TYPE_COUNT_BOUND for DW_AT_count. Bidirectional interface
provided for TYPE_HIGH_BOUND/DW_AT_upper_bound <-> DW_COUNT_BOUND/DW_AT_count.
Regards,
Jan
2007-11-23 Jan Kratochvil <jan.kratochvil@redhat.com>
* Makefile.in: Update dependencies.
* findvar.c: Include "dwarf2block.h".
(read_var_value): Refactored to rely on TYPE_LENGTH_GET_WITH_ADDRESS
and ALLOCATE_VALUE_WITH_LENGTH and allocated the returned VALUE only
after its ADDRESS has been found.
* gdbtypes.c: Include "dwarf2block.h".
(create_range_type): Rename to ...
(create_range_type_nfields): ... here and add the parameter NFIELDS.
Move setting TYPE_LOW_BOUND_RAW, TYPE_HIGH_BOUND_RAW and
TYPE_FLAG_UNSIGNED into ...
(create_range_type): ... a new function.
(create_array_type): Remove variable LOW_BOUND and HIGH_BOUND.
No longer call GET_DISCRETE_BOUNDS, set TYPE_LENGTH only for
non-dynamic array types.
(range_type_any_field_internal, range_type_high_bound_internal)
(range_type_count_bound_internal, range_type_byte_stride_internal)
(type_length_get): New functions.
(check_typedef): Call TYPE_LENGTH_GET to get the array memory size.
* dwarf2read.c (enum dwarf2_get_attr_constant_value): New.
(dwarf2_get_attr_constant_value): Update the prototype.
(read_array_type): Propagate TYPE_ARRAY_UPPER_BOUND_TYPE and
TYPE_ARRAY_LOWER_BOUND_TYPE from the range type into the array type.
(read_subrange_type): New variables BYTE_STRIDE_ATTR, BYTE_STRIDE_INT,
HIGH_TYPE and BYTE_STRIDE_TYPE. Replace the call to CREATE_RANGE_TYPE
with a call to CREATE_RANGE_TYPE_NFIELDS. New support for
`DW_AT_count'. Support DWARF2_ATTR_BLOCK for `DW_AT_lower_bound',
`DW_AT_upper_bound', `DW_AT_count' and `DW_AT_byte_stride'. Fill in
TYPE_ARRAY_UPPER_BOUND_TYPE appropriately.
(dwarf2_get_attr_constant_value): Change the calling convention.
Support the `DW_FORM_block', `DW_FORM_block1', `DW_FORM_block2' and
`DW_FORM_block4' detection. Support the NULL ATTR entry value.
* gdbtypes.h (struct main_type): New field LOC.DWARF_BLOCK. Include
the range bounds meaning for the field STATIC_KIND.
Update the TYPE_LENGTH comment also for ARRAYs.
(TYPE_LOW_BOUND): Renamed to ...
(TYPE_LOW_BOUND_RAW): ... here.
(TYPE_HIGH_BOUND): Renamed to ...
(TYPE_HIGH_BOUND_RAW): ... here.
(TYPE_BYTE_STRIDE_RAW, TYPE_LOW_BOUND, TYPE_HIGH_BOUND)
(TYPE_COUNT_BOUND, TYPE_BYTE_STRIDE, TYPE_BOUND_IS_DWARF_BLOCK_MASK)
(TYPE_BOUND_IS_DWARF_BLOCK_VAR, TYPE_HIGH_BOUND_IS_COUNT_MASK)
(TYPE_HIGH_BOUND_IS_COUNT_VAR, FIELD_DWARF_BLOCK)
(TYPE_FIELD_DWARF_BLOCK): New macros.
(TYPE_ARRAY_UPPER_BOUND_VALUE, TYPE_ARRAY_BYTE_STRIDE_VALUE): Redefine
using underneath TYPE_INDEX_TYPE.
(create_range_type_nfields, range_type_any_field_internal)
(range_type_high_bound_internal, range_type_count_bound_internal)
(range_type_byte_stride_internal): New prototypes.
Index: sources/gdb/Makefile.in
===================================================================
--- sources.orig/gdb/Makefile.in 2007-11-23 22:07:58.000000000 +0100
+++ sources/gdb/Makefile.in 2007-11-23 22:08:01.000000000 +0100
@@ -2091,7 +2091,7 @@ f-exp.o: f-exp.c $(defs_h) $(gdb_string_
findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \
$(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \
$(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \
- $(user_regs_h) $(block_h)
+ $(user_regs_h) $(block_h) $(dwarf2block_h)
f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(parser_defs_h) $(language_h) $(f_lang_h) \
$(valprint_h) $(value_h)
@@ -2134,7 +2134,8 @@ gdb-events.o: gdb-events.c $(defs_h) $(g
gdbtypes.o: gdbtypes.c $(defs_h) $(gdb_string_h) $(bfd_h) $(symtab_h) \
$(symfile_h) $(objfiles_h) $(gdbtypes_h) $(expression_h) \
$(language_h) $(target_h) $(value_h) $(demangle_h) $(complaints_h) \
- $(gdbcmd_h) $(wrapper_h) $(cp_abi_h) $(gdb_assert_h) $(hashtab_h)
+ $(gdbcmd_h) $(wrapper_h) $(cp_abi_h) $(gdb_assert_h) $(hashtab_h) \
+ $(dwarf2block_h)
glibc-tdep.o: glibc-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(symfile_h) \
$(objfiles_h) $(glibc_tdep_h)
gnu-nat.o: gnu-nat.c $(gdb_string_h) $(defs_h) $(inferior_h) $(symtab_h) \
Index: sources/gdb/findvar.c
===================================================================
--- sources.orig/gdb/findvar.c 2007-11-23 22:07:47.000000000 +0100
+++ sources/gdb/findvar.c 2007-11-23 22:08:01.000000000 +0100
@@ -34,6 +34,7 @@
#include "regcache.h"
#include "user-regs.h"
#include "block.h"
+#include "dwarf2block.h"
/* Basic byte-swapping routines. GDB has needed these for a long time...
All extract a target-format integer at ADDR which is LEN bytes long. */
@@ -370,24 +371,8 @@ symbol_read_needs_frame (struct symbol *
struct value *
read_var_value (struct symbol *var, struct frame_info *frame)
{
- struct value *v;
struct type *type = SYMBOL_TYPE (var);
CORE_ADDR addr;
- int len;
-
- if (SYMBOL_CLASS (var) == LOC_COMPUTED
- || SYMBOL_CLASS (var) == LOC_COMPUTED_ARG
- || SYMBOL_CLASS (var) == LOC_REGISTER
- || SYMBOL_CLASS (var) == LOC_REGPARM)
- /* These cases do not use V. */
- v = NULL;
- else
- {
- v = allocate_value (type);
- VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
- }
-
- len = TYPE_LENGTH (type);
/* FIXME drow/2003-09-06: this call to the selected frame should be
pushed upwards to the callers. */
@@ -397,31 +382,39 @@ read_var_value (struct symbol *var, stru
switch (SYMBOL_CLASS (var))
{
case LOC_CONST:
- /* Put the constant back in target format. */
- store_signed_integer (value_contents_raw (v), len,
- (LONGEST) SYMBOL_VALUE (var));
- VALUE_LVAL (v) = not_lval;
- return v;
+ {
+ /* Put the constant back in target format. */
+ struct value *v = allocate_value (type);
+ VALUE_LVAL (v) = not_lval;
+ store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type),
+ (LONGEST) SYMBOL_VALUE (var));
+ return v;
+ }
case LOC_LABEL:
- /* Put the constant back in target format. */
- if (overlay_debugging)
- {
- CORE_ADDR addr
- = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
- SYMBOL_BFD_SECTION (var));
- store_typed_address (value_contents_raw (v), type, addr);
- }
- else
- store_typed_address (value_contents_raw (v), type,
- SYMBOL_VALUE_ADDRESS (var));
- VALUE_LVAL (v) = not_lval;
- return v;
+ {
+ /* Put the constant back in target format. */
+ struct value *v = allocate_value (type);
+ VALUE_LVAL (v) = not_lval;
+ if (overlay_debugging)
+ {
+ CORE_ADDR addr
+ = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+ SYMBOL_BFD_SECTION (var));
+ store_typed_address (value_contents_raw (v), type, addr);
+ }
+ else
+ store_typed_address (value_contents_raw (v), type,
+ SYMBOL_VALUE_ADDRESS (var));
+ return v;
+ }
case LOC_CONST_BYTES:
{
- memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), len);
+ struct value *v = allocate_value (type);
VALUE_LVAL (v) = not_lval;
+ memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
+ TYPE_LENGTH (type));
return v;
}
@@ -503,12 +496,23 @@ addresses have not been bound by the dyn
break;
case LOC_BLOCK:
- if (overlay_debugging)
- VALUE_ADDRESS (v) = symbol_overlayed_address
- (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_BFD_SECTION (var));
- else
- VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
- return v;
+ {
+ CORE_ADDR addr;
+ struct value *v;
+
+ if (overlay_debugging)
+ addr = symbol_overlayed_address
+ (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_BFD_SECTION (var));
+ else
+ addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for
+ DW_OP_push_object_address. */
+ object_address_set (addr);
+ v = allocate_value (type);
+ VALUE_ADDRESS (v) = addr;
+ VALUE_LVAL (v) = lval_memory;
+ return v;
+ }
case LOC_REGISTER:
case LOC_REGPARM:
@@ -532,7 +536,6 @@ addresses have not been bound by the dyn
error (_("Value of register variable not available."));
addr = value_as_address (regval);
- VALUE_LVAL (v) = lval_memory;
}
else
{
@@ -572,18 +575,33 @@ addresses have not been bound by the dyn
break;
case LOC_OPTIMIZED_OUT:
- VALUE_LVAL (v) = not_lval;
- set_value_optimized_out (v, 1);
- return v;
+ {
+ struct value *v = allocate_value (type);
+
+ VALUE_LVAL (v) = not_lval;
+ set_value_optimized_out (v, 1);
+ return v;
+ }
default:
error (_("Cannot look up value of a botched symbol."));
break;
}
- VALUE_ADDRESS (v) = addr;
- set_value_lazy (v, 1);
- return v;
+ {
+ struct value *v;
+
+ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for
+ DW_OP_push_object_address. */
+ object_address_set (addr);
+ v = allocate_value (type);
+ VALUE_ADDRESS (v) = addr;
+ VALUE_LVAL (v) = lval_memory;
+
+ set_value_lazy (v, 1);
+
+ return v;
+ }
}
/* Install default attributes for register values. */
Index: sources/gdb/gdbtypes.c
===================================================================
--- sources.orig/gdb/gdbtypes.c 2007-11-23 22:07:47.000000000 +0100
+++ sources/gdb/gdbtypes.c 2007-11-23 22:08:01.000000000 +0100
@@ -38,6 +38,7 @@
#include "cp-abi.h"
#include "gdb_assert.h"
#include "hashtab.h"
+#include "dwarf2block.h"
/* These variables point to the objects
representing the predefined C data types. */
@@ -682,16 +683,21 @@ allocate_stub_method (struct type *type)
RESULT_TYPE, or creating a new type, inheriting the objfile from
INDEX_TYPE.
- Indices will be of type INDEX_TYPE, and will range from LOW_BOUND
- to HIGH_BOUND, inclusive.
+ Indices will be of type INDEX_TYPE. NFIELDS should be 2 for standard
+ arrays, 3 for a custom TYPE_BYTE_STRIDE. Use CREATE_RANGE_TYPE for common
+ constant LOW_BOUND/HIGH_BOUND ranges.
+
+ You must set TYPE_FLAG_UNSIGNED yourself as being done in CREATE_RANGE_TYPE.
FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
sure it is TYPE_CODE_UNDEF before we bash it into a range type? */
struct type *
-create_range_type (struct type *result_type, struct type *index_type,
- int low_bound, int high_bound)
+create_range_type_nfields (struct type *result_type, struct type *index_type,
+ int nfields)
{
+ int fieldno;
+
if (result_type == NULL)
{
result_type = alloc_type (TYPE_OBJFILE (index_type));
@@ -702,17 +708,33 @@ create_range_type (struct type *result_t
TYPE_FLAGS (result_type) |= TYPE_FLAG_TARGET_STUB;
else
TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type));
- TYPE_NFIELDS (result_type) = 2;
+ TYPE_NFIELDS (result_type) = nfields;
TYPE_FIELDS (result_type) = (struct field *)
- TYPE_ALLOC (result_type, 2 * sizeof (struct field));
- memset (TYPE_FIELDS (result_type), 0, 2 * sizeof (struct field));
- TYPE_FIELD_BITPOS (result_type, 0) = low_bound;
- TYPE_FIELD_BITPOS (result_type, 1) = high_bound;
+ TYPE_ALLOC (result_type,
+ TYPE_NFIELDS (result_type) * sizeof (struct field));
+ memset (TYPE_FIELDS (result_type), 0,
+ TYPE_NFIELDS (result_type) * sizeof (struct field));
+
+ return (result_type);
+}
+
+/* Simplified CREATE_RANGE_TYPE_NFIELDS for constant ranges from LOW_BOUND to
+ HIGH_BOUND, inclusive. TYPE_BYTE_STRIDE is always set to zero (default
+ native target type length). */
+
+struct type *
+create_range_type (struct type *result_type, struct type *index_type,
+ int low_bound, int high_bound)
+{
+ result_type = create_range_type_nfields (result_type, index_type, 2);
+
+ TYPE_LOW_BOUND_RAW (result_type) = low_bound;
+ TYPE_HIGH_BOUND_RAW (result_type) = high_bound;
if (low_bound >= 0)
TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
- return (result_type);
+ return result_type;
}
/* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
@@ -800,19 +822,23 @@ create_array_type (struct type *result_t
struct type *element_type,
struct type *range_type)
{
- LONGEST low_bound, high_bound;
-
if (result_type == NULL)
{
result_type = alloc_type (TYPE_OBJFILE (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);
- TYPE_LENGTH (result_type) =
- TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+ /* Dynamically sized arrays cannot be computed now as we may have forward
+ DWARF references here. */
+ if ((TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 0)
+ & TYPE_BOUND_IS_DWARF_BLOCK_MASK) != 0
+ && (TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 1)
+ & TYPE_BOUND_IS_DWARF_BLOCK_MASK) != 0)
+ TYPE_LENGTH (result_type) = 0;
+ else
+ TYPE_LENGTH (result_type) = TYPE_LENGTH (element_type)
+ * TYPE_COUNT_BOUND (range_type);
TYPE_NFIELDS (result_type) = 1;
TYPE_FIELDS (result_type) =
(struct field *) TYPE_ALLOC (result_type, sizeof (struct field));
@@ -1349,6 +1375,111 @@ stub_noname_complaint (void)
complaint (&symfile_complaints, _("stub type has NULL name"));
}
+CORE_ADDR range_type_any_field_internal (struct type *range_type, int fieldno)
+{
+ if ((TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, fieldno)
+ & TYPE_BOUND_IS_DWARF_BLOCK_MASK) != 0)
+ return dwarf_block_exec (TYPE_FIELD_DWARF_BLOCK (range_type, fieldno));
+ else
+ return TYPE_FIELD_BITPOS (range_type, (fieldno));
+}
+
+int
+range_type_high_bound_internal (struct type *range_type)
+{
+ int raw_value = range_type_any_field_internal (range_type, 1);
+
+ if ((TYPE_HIGH_BOUND_IS_COUNT_VAR (range_type)
+ & TYPE_HIGH_BOUND_IS_COUNT_MASK) == 0)
+ {
+ /* DW_AT_upper_bound value. */
+ return raw_value;
+ }
+ else
+ {
+ /* DW_AT_count value. */
+ return TYPE_LOW_BOUND (range_type) + raw_value - 1;
+ }
+}
+
+int
+range_type_count_bound_internal (struct type *range_type)
+{
+ int raw_value = range_type_any_field_internal (range_type, 1);
+ if ((TYPE_HIGH_BOUND_IS_COUNT_VAR (range_type)
+ & TYPE_HIGH_BOUND_IS_COUNT_MASK) != 0)
+ {
+ /* DW_AT_count value. */
+ return raw_value;
+ }
+ else
+ {
+ /* DW_AT_upper_bound value. */
+ return 1 + raw_value - TYPE_LOW_BOUND (range_type);
+ }
+}
+
+CORE_ADDR range_type_byte_stride_internal (struct type *range_type)
+{
+ if (TYPE_NFIELDS (range_type) >= 3)
+ return range_type_any_field_internal (range_type, 2);
+ else
+ {
+ /* The caller will need to call something like
+ `TYPE_LENGTH (check_typedef (element_type))
+ * TYPE_COUNT_BOUND (range_type) '. */
+ return 0;
+ }
+}
+
+/* Calculate the memory length of array TYPE.
+
+ TARGET_TYPE should be set to `check_typedef (TYPE_TARGET_TYPE (type))' as
+ a performance hint. Feel free to pass NULL. Set FULL_SPAN to return the
+ size incl. the possibly incomplete last element - it may differ from the
+ cleared FULL_SPAN return value for larger TYPE_BYTE_STRIDE values. */
+
+static CORE_ADDR
+type_length_get (struct type *type, struct type *target_type, int full_span)
+{
+ struct type *range_type;
+ int count;
+ CORE_ADDR byte_stride = 0; /* `= 0' for a false GCC warning. */
+ CORE_ADDR element_size;
+
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+ return TYPE_LENGTH (type);
+
+ /* Avoid executing TYPE_COUNT_BOUND for invalid (unallocated/unassociated)
+ Fortran arrays. The allocated data will never be used so they can be
+ zero-length. */
+ if (!LA_VALUE_ADDRESS_GET (type, NULL))
+ return 0;
+
+ range_type = TYPE_INDEX_TYPE (type);
+ count = TYPE_COUNT_BOUND (range_type);
+ if (count < 0)
+ warning (_("Object count %d < 0"), count);
+ if (count <= 0)
+ return 0;
+ if (full_span || count > 1)
+ {
+ byte_stride = TYPE_BYTE_STRIDE (range_type);
+ if (byte_stride == 0)
+ {
+ if (target_type == NULL)
+ target_type = check_typedef (TYPE_TARGET_TYPE (type));
+ byte_stride = type_length_get (target_type, NULL, 1);
+ }
+ }
+ if (full_span)
+ return count * byte_stride;
+ if (target_type == NULL)
+ target_type = check_typedef (TYPE_TARGET_TYPE (type));
+ element_size = type_length_get (target_type, NULL, 1);
+ return (count - 1) * byte_stride + element_size;
+}
+
/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
If this is a stubbed struct (i.e. declared as struct foo *), see if
@@ -1493,10 +1624,7 @@ check_typedef (struct type *type)
{
/* Now recompute the length of the array type, based on its
number of elements and the target type's length. */
- TYPE_LENGTH (type) =
- ((TYPE_FIELD_BITPOS (range_type, 1)
- - TYPE_FIELD_BITPOS (range_type, 0) + 1)
- * TYPE_LENGTH (target_type));
+ TYPE_LENGTH (type) = type_length_get (type, target_type, 0);
TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
}
else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
Index: sources/gdb/dwarf2read.c
===================================================================
--- sources.orig/gdb/dwarf2read.c 2007-11-23 22:07:59.000000000 +0100
+++ sources/gdb/dwarf2read.c 2007-11-23 22:08:01.000000000 +0100
@@ -1006,7 +1006,14 @@ static void store_in_ref_table (unsigned
static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
struct dwarf2_cu *);
-static int dwarf2_get_attr_constant_value (struct attribute *, int);
+enum dwarf2_get_attr_constant_value
+ {
+ dwarf2_attr_unknown,
+ dwarf2_attr_const,
+ dwarf2_attr_block
+ };
+static enum dwarf2_get_attr_constant_value dwarf2_get_attr_constant_value
+ (struct attribute *attr, int *val_return);
static struct die_info *follow_die_ref (struct die_info *,
struct attribute *,
@@ -4299,14 +4306,27 @@ read_array_type (struct die_info *die, s
if (read_array_order (die, cu) == DW_ORD_col_major)
{
- int i = 0;
- while (i < ndim)
- type = create_array_type (NULL, type, range_types[i++]);
+ int i;
+ for (i = 0; i < ndim; i++)
+ {
+ type = create_array_type (NULL, type, range_types[i]);
+ TYPE_ARRAY_UPPER_BOUND_TYPE (type) =
+ TYPE_ARRAY_UPPER_BOUND_TYPE (range_types[i]);
+ TYPE_ARRAY_LOWER_BOUND_TYPE (type) =
+ TYPE_ARRAY_LOWER_BOUND_TYPE (range_types[i]);
+ }
}
else
{
- while (ndim-- > 0)
- type = create_array_type (NULL, type, range_types[ndim]);
+ int i;
+ for (i = ndim - 1; i >= 0; i--)
+ {
+ type = create_array_type (NULL, type, range_types[i]);
+ TYPE_ARRAY_UPPER_BOUND_TYPE (type) =
+ TYPE_ARRAY_UPPER_BOUND_TYPE (range_types[i]);
+ TYPE_ARRAY_LOWER_BOUND_TYPE (type) =
+ TYPE_ARRAY_LOWER_BOUND_TYPE (range_types[i]);
+ }
}
/* Understand Dwarf2 support for vector types (like they occur on
@@ -4914,9 +4934,9 @@ read_subrange_type (struct die_info *die
{
struct type *base_type;
struct type *range_type;
- struct attribute *attr;
- int low = 0;
- int high = -1;
+ struct attribute *attr, *byte_stride_attr;
+ int low, high, byte_stride_int;
+ enum dwarf2_get_attr_constant_value high_type, byte_stride_type;
char *name;
/* If we have already decoded this die, then nothing more to do. */
@@ -4933,42 +4953,99 @@ read_subrange_type (struct die_info *die
gdbarch_addr_bit (current_gdbarch) / 8, cu);
}
- if (cu->language == language_fortran)
- {
- /* FORTRAN implies a lower bound of 1, if not given. */
- low = 1;
- }
+ /* DW_AT_bit_stride is unsupported as if it would be non-constant we would
+ have to wrap it by the division by 8 or provide another value type etc. */
+ byte_stride_attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
+ byte_stride_type = dwarf2_get_attr_constant_value (byte_stride_attr,
+ &byte_stride_int);
+
+ range_type = create_range_type_nfields
+ (NULL, base_type, byte_stride_type == dwarf2_attr_unknown ? 2 : 3);
- /* FIXME: For variable sized arrays either of these could be
- a variable rather than a constant value. We'll allow it,
- but we don't know how to handle it. */
attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
- if (attr)
- low = dwarf2_get_attr_constant_value (attr, 0);
+ switch (dwarf2_get_attr_constant_value (attr, &low))
+ {
+ case dwarf2_attr_unknown:
+ if (cu->language == language_fortran)
+ {
+ /* FORTRAN implies a lower bound of 1, if not given. */
+ low = 1;
+ }
+ else
+ {
+ /* According to DWARF3 we should assume the value 0 only for
+ LANGUAGE_C and LANGUAGE_CPLUS. */
+ low = 0;
+ }
+ /* PASSTHRU */
+ case dwarf2_attr_const:
+ TYPE_LOW_BOUND_RAW (range_type) = low;
+ if (low >= 0)
+ TYPE_FLAGS (range_type) |= TYPE_FLAG_UNSIGNED;
+ break;
+ case dwarf2_attr_block:
+ TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 0)
+ |= TYPE_BOUND_IS_DWARF_BLOCK_MASK;
+ TYPE_FIELD_DWARF_BLOCK (range_type, 0) = DW_BLOCK (attr);
+ /* For auto-detection of possibly missing DW_AT_upper_bound. */
+ low = 0;
+ break;
+ }
attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
- if (attr)
- {
- if (attr->form == DW_FORM_block1)
- {
- /* GCC encodes arrays with unspecified or dynamic length
- with a DW_FORM_block1 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 = low - 1;
- }
- else
- high = dwarf2_get_attr_constant_value (attr, 1);
+ high_type = dwarf2_get_attr_constant_value (attr, &high);
+ if (high_type == dwarf2_attr_unknown)
+ {
+ int count;
+
+ attr = dwarf2_attr (die, DW_AT_count, cu);
+ high_type = dwarf2_get_attr_constant_value (attr, &count);
+ switch (high_type)
+ {
+ case dwarf2_attr_unknown:
+ break;
+ case dwarf2_attr_const:
+ /* We do not handle LOW being set as DW_BLOCK here. */
+ high = low + count - 1;
+ /* PASSTHRU */
+ case dwarf2_attr_block:
+ TYPE_HIGH_BOUND_IS_COUNT_VAR (range_type)
+ |= TYPE_HIGH_BOUND_IS_COUNT_MASK;
+ break;
+ }
+ }
+ switch (high_type)
+ {
+ case dwarf2_attr_unknown:
+ /* It needs to get propagated to he array type owning us. */
+ TYPE_ARRAY_UPPER_BOUND_TYPE (range_type) = BOUND_CANNOT_BE_DETERMINED;
+ high = low - 1;
+ /* PASSTHRU */
+ case dwarf2_attr_const:
+ TYPE_HIGH_BOUND_RAW (range_type) = high;
+ break;
+ case dwarf2_attr_block:
+ TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 1)
+ |= TYPE_BOUND_IS_DWARF_BLOCK_MASK;
+ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = DW_BLOCK (attr);
+ break;
}
- range_type = create_range_type (NULL, base_type, low, high);
+ switch (byte_stride_type)
+ {
+ case dwarf2_attr_unknown:
+ break;
+ case dwarf2_attr_const:
+ if (byte_stride_int == 0)
+ warning (_("Found DW_AT_byte_stride with unsupported value 0"));
+ TYPE_HIGH_BOUND_RAW (range_type) = byte_stride_int;
+ break;
+ case dwarf2_attr_block:
+ TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 2)
+ |= TYPE_BOUND_IS_DWARF_BLOCK_MASK;
+ TYPE_FIELD_DWARF_BLOCK (range_type, 2) = DW_BLOCK (byte_stride_attr);
+ break;
+ }
name = dwarf2_name (die, cu);
if (name)
@@ -8978,26 +9055,35 @@ dwarf2_get_ref_die_offset (struct attrib
return result;
}
-/* Return the constant value held by the given attribute. Return -1
- if the value held by the attribute is not constant. */
+/* *VAL_RETURN is filled only for DWARF2_ATTR_CONST. */
-static int
-dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+static enum dwarf2_get_attr_constant_value
+dwarf2_get_attr_constant_value (struct attribute *attr, int *val_return)
{
+ if (attr == NULL)
+ return dwarf2_attr_unknown;
if (attr->form == DW_FORM_sdata)
- return DW_SND (attr);
- else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- return DW_UNSND (attr);
- else
{
- complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"),
- dwarf_form_name (attr->form));
- return default_value;
+ *val_return = DW_SND (attr);
+ return dwarf2_attr_const;
}
+ if (attr->form == DW_FORM_udata
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ {
+ *val_return = DW_UNSND (attr);
+ return dwarf2_attr_const;
+ }
+ if (attr->form == DW_FORM_block
+ || attr->form == DW_FORM_block1
+ || attr->form == DW_FORM_block2
+ || attr->form == DW_FORM_block4)
+ return dwarf2_attr_block;
+ complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"),
+ dwarf_form_name (attr->form));
+ return dwarf2_attr_unknown;
}
static struct die_info *
Index: sources/gdb/gdbtypes.h
===================================================================
--- sources.orig/gdb/gdbtypes.h 2007-11-23 22:07:47.000000000 +0100
+++ sources/gdb/gdbtypes.h 2007-11-23 22:08:01.000000000 +0100
@@ -458,6 +458,9 @@ struct main_type
CORE_ADDR physaddr;
char *physname;
+
+ /* For dynamically-sized arrays. Passed to DWARF_BLOCK_EXEC. */
+ struct dwarf_block *dwarf_block;
}
loc;
@@ -468,7 +471,11 @@ struct main_type
/* This flag is zero for non-static fields, 1 for fields whose location
is specified by the label loc.physname, and 2 for fields whose location
- is specified by loc.physaddr. */
+ is specified by loc.physaddr.
+ For range bounds bit 0 cleared is for loc.bitpos and bit 0 set is for
+ loc.dwarf_block (TYPE_BOUND_IS_DWARF_BLOCK_MASK).
+ For range bounds bit 1 cleared is for DW_AT_upper_bound and bit 1 set is
+ for DW_AT_count (TYPE_HIGH_BOUND_IS_COUNT_MASK). */
unsigned int static_kind : 2;
@@ -807,9 +814,9 @@ extern void allocate_cplus_struct_type (
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
#define TYPE_CHAIN(thistype) (thistype)->chain
-/* Note that if thistype is a TYPEDEF type, you have to call check_typedef.
- But check_typedef does set the TYPE_LENGTH of the TYPEDEF type,
- so you only have to call check_typedef once. Since allocate_value
+/* Note that if thistype is a TYPEDEF or ARRAY type, you have to call
+ check_typedef. But check_typedef does set the TYPE_LENGTH of the TYPEDEF
+ type, so you only have to call check_typedef once. Since allocate_value
calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */
#define TYPE_LENGTH(thistype) (thistype)->length
#define TYPE_OBJFILE(thistype) TYPE_MAIN_TYPE(thistype)->objfile
@@ -823,8 +830,25 @@ extern void allocate_cplus_struct_type (
#define TYPE_INSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->instantiations
#define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0)
-#define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0)
-#define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1)
+#define TYPE_LOW_BOUND_RAW(range_type) TYPE_FIELD_BITPOS (range_type, 0)
+#define TYPE_HIGH_BOUND_RAW(range_type) TYPE_FIELD_BITPOS (range_type, 1)
+/* `TYPE_NFIELDS (range_type) >= 3' check is required before accessing it: */
+#define TYPE_BYTE_STRIDE_RAW(range_type) TYPE_FIELD_BITPOS (range_type, 2)
+#define TYPE_LOW_BOUND(range_type) \
+ ((int) range_type_any_field_internal ((range_type), 0))
+#define TYPE_HIGH_BOUND(range_type) \
+ range_type_high_bound_internal ((range_type))
+#define TYPE_COUNT_BOUND(range_type) \
+ range_type_count_bound_internal ((range_type))
+#define TYPE_BYTE_STRIDE(type) \
+ range_type_byte_stride_internal ((type))
+
+#define TYPE_BOUND_IS_DWARF_BLOCK_MASK 1
+#define TYPE_BOUND_IS_DWARF_BLOCK_VAR(range_type, fieldno) \
+ TYPE_FIELD_STATIC_KIND (range_type, fieldno)
+#define TYPE_HIGH_BOUND_IS_COUNT_MASK 2
+#define TYPE_HIGH_BOUND_IS_COUNT_VAR(range_type) \
+ TYPE_FIELD_STATIC_KIND (range_type, 1)
/* Moto-specific stuff for FORTRAN arrays */
@@ -833,11 +857,12 @@ extern void allocate_cplus_struct_type (
#define TYPE_ARRAY_LOWER_BOUND_TYPE(thistype) \
TYPE_MAIN_TYPE(thistype)->lower_bound_type
-#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
- (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),1))
-
#define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \
- (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),0))
+ (TYPE_LOW_BOUND(TYPE_INDEX_TYPE(arraytype)))
+#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
+ (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE(arraytype)))
+#define TYPE_ARRAY_BYTE_STRIDE_VALUE(arraytype) \
+ (TYPE_BYTE_STRIDE(TYPE_INDEX_TYPE(arraytype)))
/* C++ */
@@ -867,6 +892,7 @@ extern void allocate_cplus_struct_type (
#define FIELD_TYPE(thisfld) ((thisfld).type)
#define FIELD_NAME(thisfld) ((thisfld).name)
#define FIELD_BITPOS(thisfld) ((thisfld).loc.bitpos)
+#define FIELD_DWARF_BLOCK(thisfld) ((thisfld).loc.dwarf_block)
#define FIELD_ARTIFICIAL(thisfld) ((thisfld).artificial)
#define FIELD_BITSIZE(thisfld) ((thisfld).bitsize)
#define FIELD_STATIC_KIND(thisfld) ((thisfld).static_kind)
@@ -880,6 +906,7 @@ extern void allocate_cplus_struct_type (
#define TYPE_FIELD_TYPE(thistype, n) FIELD_TYPE(TYPE_FIELD(thistype, n))
#define TYPE_FIELD_NAME(thistype, n) FIELD_NAME(TYPE_FIELD(thistype, n))
#define TYPE_FIELD_BITPOS(thistype, n) FIELD_BITPOS(TYPE_FIELD(thistype,n))
+#define TYPE_FIELD_DWARF_BLOCK(thistype, n) FIELD_DWARF_BLOCK(TYPE_FIELD(thistype,n))
#define TYPE_FIELD_ARTIFICIAL(thistype, n) FIELD_ARTIFICIAL(TYPE_FIELD(thistype,n))
#define TYPE_FIELD_BITSIZE(thistype, n) FIELD_BITSIZE(TYPE_FIELD(thistype,n))
#define TYPE_FIELD_PACKED(thistype, n) (FIELD_BITSIZE(TYPE_FIELD(thistype,n))!=0)
@@ -1290,12 +1317,25 @@ extern struct type *make_function_type (
extern struct type *lookup_function_type (struct type *);
+extern struct type *create_range_type_nfields (struct type *result_type,
+ struct type *index_type,
+ int nfields);
+
extern struct type *create_range_type (struct type *, struct type *, int,
int);
extern struct type *create_array_type (struct type *, struct type *,
struct type *);
+extern CORE_ADDR range_type_any_field_internal (struct type *range_type,
+ int fieldno);
+
+extern int range_type_high_bound_internal (struct type *range_type);
+
+extern int range_type_count_bound_internal (struct type *range_type);
+
+extern CORE_ADDR range_type_byte_stride_internal (struct type *range_type);
+
extern struct type *create_string_type (struct type *, struct type *);
extern struct type *create_set_type (struct type *, struct type *);