This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] DW_AT_byte_size for array type entries


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
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 11:00:18 -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 11:00:18 -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 11:00:19 -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 11:00:19 -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 11:00:19 -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 11:00:19 -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 11:00:19 -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 11:00:19 -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 11:00:19 -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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]