This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [patch] DW_AT_byte_size for array type entries
- From: Ken Werner <ken at linux dot vnet dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 19 Oct 2010 20:16:05 +0200
- Subject: Re: [patch] DW_AT_byte_size for array type entries
- References: <201010191323.57251.ken@linux.vnet.ibm.com>
On Tuesday, October 19, 2010 1:23:57 pm Ken Werner wrote:
> Hi,
>
> Section 5.4 of the DWARF standard allows to specify extra padding bytes for
> array type entries by using the DW_AT_byte_size attribute. This is used for
> example to specify the types for OpenCL 3-component vectors whose size and
> alignment are those of 4-component vectors. Currently the GDB does not
> understand this mechanism and the attached patch attempts to fix this. It
> extends the DWARF reader (dwarf2read.c:read_array_type) to respect the
> DW_AT_byte_size attribute and set the length of the array accordingly. This
> breaks the code that assumes that the number of elements of an array is
> simply the length of the array type divided by the length of the element
> type. Therefore the patch queries the number of array elements using the
> get_array_bounds function that has been enhanced to only return the bounds
> if they are defined (TYPE_ARRAY_[LOWER|UPPER]_BOUND_IS_UNDEFINED). In
> order to prevent the inclusion of the valprint.h header the
> get_array_bounds function has been moved from valprint.[c|h] to
> gdbtypes.[c|h].
> Tested on i686-*-linux-gnu with no regressions.
>
> Regards
> Ken Werner
Hm, that patch lacks the chunk that changes the c_type_print_varspec_suffix
function. Here is the full version.
Regards
Ken
ChangeLog:
2010-10-19 Ken Werner <ken.werner@de.ibm.com>
* dwarf2read.c (read_array_type): Read the DW_AT_byte_size from the
DIE and set the length of the type.
* gdbtypes.h (get_array_bounds): Move here from valprint.h.
* gdbtypes.c (get_array_bounds): Move here from valprint.c and
return 0 if the corresponding bounds of the type are undefined.
* valprint.h (get_array_bounds): Move declaration to gdbtypes.h.
* valprint.c (get_array_bounds): Move implementation to gdbtypes.c.
(val_print_array_elements): Use get_array_bounds to compute the number
of array elements instead of dividing the length of the array by the
length of the element types.
* valarith.c (vector_binop): Likewise.
* valops.c (value_cast): Likewise.
* c-valprint.c (c_val_print): Likewise.
* c-typeprint.c (c_type_print_varspec_suffix): Likewise.
testsuite/ChangeLog:
2010-10-19 Ken Werner <ken.werner@de.ibm.com>
* gdb.base/gnu_vector.exp: Adjust expect messages.
Index: gdb/c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.74
diff -p -u -r1.74 c-valprint.c
--- gdb/c-valprint.c 15 Oct 2010 18:54:12 -0000 1.74
+++ gdb/c-valprint.c 19 Oct 2010 12:15:30 -0000
@@ -171,8 +171,13 @@ c_val_print (struct type *type, const gd
elttype = check_typedef (unresolved_elttype);
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (unresolved_elttype) > 0)
{
+ LONGEST low_bound, high_bound;
+
+ if (!get_array_bounds(type, &low_bound, &high_bound))
+ error (_("Could not determine the array high bound"));
+
eltlen = TYPE_LENGTH (elttype);
- len = TYPE_LENGTH (type) / eltlen;
+ len = high_bound - low_bound + 1;
if (options->prettyprint_arrays)
{
print_spaces_filtered (2 + 2 * recurse, stream);
Index: gdb/dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.472
diff -p -u -r1.472 dwarf2read.c
--- gdb/dwarf2read.c 17 Oct 2010 18:49:46 -0000 1.472
+++ gdb/dwarf2read.c 19 Oct 2010 12:15:31 -0000
@@ -7194,6 +7194,19 @@ read_array_type (struct die_info *die, s
if (attr)
make_vector_type (type);
+ /* The DIE may have DW_AT_byte_size set. For example an OpenCL
+ implementation may choose to implement triple vectors using this
+ attribute. */
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+ if (attr)
+ {
+ if (DW_UNSND (attr) >= TYPE_LENGTH (type))
+ TYPE_LENGTH (type) = DW_UNSND (attr);
+ else
+ complaint (&symfile_complaints, _("\
+DW_AT_byte_size for array type smaller than the total size of elements"));
+ }
+
name = dwarf2_name (die, cu);
if (name)
TYPE_NAME (type) = name;
Index: gdb/gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.203
diff -p -u -r1.203 gdbtypes.c
--- gdb/gdbtypes.c 15 Oct 2010 17:48:47 -0000 1.203
+++ gdb/gdbtypes.c 19 Oct 2010 12:15:31 -0000
@@ -802,6 +802,50 @@ get_discrete_bounds (struct type *type,
}
}
+/* Assuming TYPE is a simple, non-empty array type, compute its upper
+ and lower bound. Save the low bound into LOW_BOUND if not NULL.
+ Save the high bound into HIGH_BOUND if not NULL.
+
+ Return 1 if the operation was successful. Return zero otherwise,
+ in which case the values of LOW_BOUND and HIGH_BOUNDS are unmodified.
+
+ We now simply use get_discrete_bounds call to get the values
+ of the low and high bounds.
+ get_discrete_bounds can return three values:
+ 1, meaning that index is a range,
+ 0, meaning that index is a discrete type,
+ or -1 for failure. */
+
+int
+get_array_bounds (struct type *type, LONGEST *low_bound, LONGEST *high_bound)
+{
+ struct type *index = TYPE_INDEX_TYPE (type);
+ LONGEST low = 0;
+ LONGEST high = 0;
+ int res;
+
+ if (index == NULL)
+ return 0;
+
+ res = get_discrete_bounds (index, &low, &high);
+ if (res == -1)
+ return 0;
+
+ /* Check if the array bounds are undefined. */
+ if (res == 1
+ && ((low_bound && TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED (type))
+ || (high_bound && TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))))
+ return 0;
+
+ if (low_bound)
+ *low_bound = low;
+
+ if (high_bound)
+ *high_bound = high;
+
+ return 1;
+}
+
/* Create an array type using either a blank type supplied in
RESULT_TYPE, or creating a new type, inheriting the objfile from
RANGE_TYPE.
Index: gdb/gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.137
diff -p -u -r1.137 gdbtypes.h
--- gdb/gdbtypes.h 15 Oct 2010 17:48:47 -0000 1.137
+++ gdb/gdbtypes.h 19 Oct 2010 12:15:31 -0000
@@ -1383,6 +1383,9 @@ extern int get_vptr_fieldno (struct type
extern int get_discrete_bounds (struct type *, LONGEST *, LONGEST *);
+extern int get_array_bounds (struct type *type, LONGEST *low_bound,
+ LONGEST *high_bound);
+
extern int class_types_same_p (const struct type *, const struct type *);
extern int is_ancestor (struct type *, struct type *);
Index: gdb/valarith.c
===================================================================
RCS file: /cvs/src/src/gdb/valarith.c,v
retrieving revision 1.87
diff -p -u -r1.87 valarith.c
--- gdb/valarith.c 8 Oct 2010 16:50:53 -0000 1.87
+++ gdb/valarith.c 19 Oct 2010 12:15:31 -0000
@@ -1388,7 +1388,8 @@ vector_binop (struct value *val1, struct
{
struct value *val, *tmp, *mark;
struct type *type1, *type2, *eltype1, *eltype2, *result_type;
- int t1_is_vec, t2_is_vec, elsize, n, i;
+ int t1_is_vec, t2_is_vec, elsize, i;
+ LONGEST low_bound1, high_bound1, low_bound2, high_bound2;
type1 = check_typedef (value_type (val1));
type2 = check_typedef (value_type (val2));
@@ -1401,23 +1402,23 @@ vector_binop (struct value *val1, struct
if (!t1_is_vec || !t2_is_vec)
error (_("Vector operations are only supported among vectors"));
+ if (!get_array_bounds (type1, &low_bound1, &high_bound1)
+ || !get_array_bounds (type2, &low_bound2, &high_bound2))
+ error (_("Could not determine the vector bounds"));
+
eltype1 = check_typedef (TYPE_TARGET_TYPE (type1));
eltype2 = check_typedef (TYPE_TARGET_TYPE (type2));
+ elsize = TYPE_LENGTH (eltype1);
if (TYPE_CODE (eltype1) != TYPE_CODE (eltype2)
- || TYPE_LENGTH (eltype1) != TYPE_LENGTH (eltype2)
- || TYPE_UNSIGNED (eltype1) != TYPE_UNSIGNED (eltype2))
+ || elsize != TYPE_LENGTH (eltype2)
+ || TYPE_UNSIGNED (eltype1) != TYPE_UNSIGNED (eltype2)
+ || low_bound1 != low_bound2 || high_bound1 != high_bound2)
error (_("Cannot perform operation on vectors with different types"));
- elsize = TYPE_LENGTH (eltype1);
- n = TYPE_LENGTH (type1) / elsize;
-
- if (n != TYPE_LENGTH (type2) / TYPE_LENGTH (eltype2))
- error (_("Cannot perform operation on vectors with different sizes"));
-
val = allocate_value (type1);
mark = value_mark ();
- for (i = 0; i < n; i++)
+ for (i = 0; i < high_bound1 - low_bound1 + 1; i++)
{
tmp = value_binop (value_subscript (val1, i),
value_subscript (val2, i), op);
Index: gdb/valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.252
diff -p -u -r1.252 valops.c
--- gdb/valops.c 8 Oct 2010 16:50:53 -0000 1.252
+++ gdb/valops.c 19 Oct 2010 12:15:32 -0000
@@ -543,14 +543,17 @@ value_cast (struct type *type, struct va
/* Widen the scalar to a vector. */
struct type *eltype;
struct value *val;
- int i, n;
+ LONGEST low_bound, high_bound;
+ int i;
+
+ if (!get_array_bounds (type, &low_bound, &high_bound))
+ error (_("Could not determine the vector bounds"));
eltype = check_typedef (TYPE_TARGET_TYPE (type));
arg2 = value_cast (eltype, arg2);
val = allocate_value (type);
- n = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
- for (i = 0; i < n; i++)
+ for (i = 0; i < high_bound - low_bound + 1; i++)
{
/* Duplicate the contents of arg2 into the destination vector. */
memcpy (value_contents_writeable (val) + (i * TYPE_LENGTH (eltype)),
Index: gdb/valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/valprint.c,v
retrieving revision 1.97
diff -p -u -r1.97 valprint.c
--- gdb/valprint.c 18 Oct 2010 19:14:02 -0000 1.97
+++ gdb/valprint.c 19 Oct 2010 12:15:32 -0000
@@ -1067,44 +1067,6 @@ print_char_chars (struct ui_file *stream
}
}
-/* Assuming TYPE is a simple, non-empty array type, compute its upper
- and lower bound. Save the low bound into LOW_BOUND if not NULL.
- Save the high bound into HIGH_BOUND if not NULL.
-
- Return 1 if the operation was successful. Return zero otherwise,
- in which case the values of LOW_BOUND and HIGH_BOUNDS are unmodified.
-
- We now simply use get_discrete_bounds call to get the values
- of the low and high bounds.
- get_discrete_bounds can return three values:
- 1, meaning that index is a range,
- 0, meaning that index is a discrete type,
- or -1 for failure. */
-
-int
-get_array_bounds (struct type *type, LONGEST *low_bound, LONGEST *high_bound)
-{
- struct type *index = TYPE_INDEX_TYPE (type);
- LONGEST low = 0;
- LONGEST high = 0;
- int res;
-
- if (index == NULL)
- return 0;
-
- res = get_discrete_bounds (index, &low, &high);
- if (res == -1)
- return 0;
-
- if (low_bound)
- *low_bound = low;
-
- if (high_bound)
- *high_bound = high;
-
- return 1;
-}
-
/* Print on STREAM using the given OPTIONS the index for the element
at INDEX of an array whose index type is INDEX_TYPE. */
@@ -1149,38 +1111,19 @@ val_print_array_elements (struct type *t
unsigned int rep1;
/* Number of repetitions we have detected so far. */
unsigned int reps;
- LONGEST low_bound_index = 0;
+ LONGEST low_bound, high_bound;
elttype = TYPE_TARGET_TYPE (type);
eltlen = TYPE_LENGTH (check_typedef (elttype));
index_type = TYPE_INDEX_TYPE (type);
- /* Compute the number of elements in the array. On most arrays,
- the size of its elements is not zero, and so the number of elements
- is simply the size of the array divided by the size of the elements.
- But for arrays of elements whose size is zero, we need to look at
- the bounds. */
- if (eltlen != 0)
- len = TYPE_LENGTH (type) / eltlen;
+ if (get_array_bounds (type, &low_bound, &high_bound))
+ len = high_bound - low_bound + 1;
else
{
- LONGEST low, hi;
-
- if (get_array_bounds (type, &low, &hi))
- len = hi - low + 1;
- else
- {
- warning (_("unable to get bounds of array, assuming null array"));
- len = 0;
- }
- }
-
- /* Get the array low bound. This only makes sense if the array
- has one or more element in it. */
- if (len > 0 && !get_array_bounds (type, &low_bound_index, NULL))
- {
- warning (_("unable to get low bound of array, using zero as default"));
- low_bound_index = 0;
+ warning (_("unable to get bounds of array, assuming null array"));
+ low_bound = 0;
+ len = 0;
}
annotate_array_section_begin (i, elttype);
@@ -1200,7 +1143,7 @@ val_print_array_elements (struct type *t
}
}
wrap_here (n_spaces (2 + 2 * recurse));
- maybe_print_array_index (index_type, i + low_bound_index,
+ maybe_print_array_index (index_type, i + low_bound,
stream, options);
rep1 = i + 1;
Index: gdb/valprint.h
===================================================================
RCS file: /cvs/src/src/gdb/valprint.h,v
retrieving revision 1.27
diff -p -u -r1.27 valprint.h
--- gdb/valprint.h 11 Jun 2010 15:36:05 -0000 1.27
+++ gdb/valprint.h 19 Oct 2010 12:15:32 -0000
@@ -109,9 +109,6 @@ extern void get_raw_print_options (struc
extern void get_formatted_print_options (struct value_print_options *opts,
char format);
-extern int get_array_bounds (struct type *type, LONGEST *low_bound,
- LONGEST *high_bound);
-
extern void maybe_print_array_index (struct type *index_type, LONGEST index,
struct ui_file *stream,
const struct value_print_options *options);
Index: gdb/testsuite/gdb.base/gnu_vector.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/gnu_vector.exp,v
retrieving revision 1.3
diff -p -u -r1.3 gnu_vector.exp
--- gdb/testsuite/gdb.base/gnu_vector.exp 8 Oct 2010 16:50:55 -0000 1.3
+++ gdb/testsuite/gdb.base/gnu_vector.exp 19 Oct 2010 12:15:32 -0000
@@ -119,8 +119,8 @@ gdb_test "print f4a + d2" "Cannot perfor
gdb_test "print d2 + f4a" "Cannot perform operation on vectors with different types"
gdb_test "print ui4 + i4a" "Cannot perform operation on vectors with different types"
gdb_test "print i4a + ui4" "Cannot perform operation on vectors with different types"
-gdb_test "print i4a + i2" "Cannot perform operation on vectors with different sizes"
-gdb_test "print i2 + i4a" "Cannot perform operation on vectors with different sizes"
-gdb_test "print f4a + f2" "Cannot perform operation on vectors with different sizes"
-gdb_test "print f2 + f4a" "Cannot perform operation on vectors with different sizes"
+gdb_test "print i4a + i2" "Cannot perform operation on vectors with different types"
+gdb_test "print i2 + i4a" "Cannot perform operation on vectors with different types"
+gdb_test "print f4a + f2" "Cannot perform operation on vectors with different types"
+gdb_test "print f2 + f4a" "Cannot perform operation on vectors with different types"
Index: gdb/c-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-typeprint.c,v
retrieving revision 1.63
diff -p -u -r1.63 c-typeprint.c
--- gdb/c-typeprint.c 19 Oct 2010 04:22:20 -0000 1.63
+++ gdb/c-typeprint.c 19 Oct 2010 17:52:38 -0000
@@ -572,19 +572,20 @@ c_type_print_varspec_suffix (struct type
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
- if (passed_a_ptr)
- fprintf_filtered (stream, ")");
+ {
+ LONGEST low_bound, high_bound;
- fprintf_filtered (stream, "[");
- if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0
- && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
- fprintf_filtered (stream, "%d",
- (TYPE_LENGTH (type)
- / TYPE_LENGTH (TYPE_TARGET_TYPE (type))));
- fprintf_filtered (stream, "]");
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
- c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
- 0, 0);
+ fprintf_filtered (stream, "[");
+ if (get_array_bounds (type, &low_bound, &high_bound))
+ fprintf_filtered (stream, "%d", (int) (high_bound - low_bound + 1));
+ fprintf_filtered (stream, "]");
+
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
+ 0, 0);
+ }
break;
case TYPE_CODE_MEMBERPTR: