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] [VLA 1/2] Read in the DW_FORM_block* type attributes


Hi,

this patch provides the reader part for simple C variable length arrays (VLA).

Two FIXMEs put there as the code can be more simplified based on new
dwarf2_get_attr_value(), together with replacing decode_locdesc() by the full
DW_FORM_block* runtime interpreter.  This part is not written so far, though.

While this part could be applied separately it has a regression without 2/2 on:
  gdb.ada/null_array.exp: print my_table
which expects a VLA there to be empty.  With the current FSF GDB code it gets
present this way but after this patch it fails on a garbage output due to an
uninterpreted read-in DWARF block.

Regression tested on x86_64-unknown-linux-gnu, Fedora gcc-4.3.2-7.


Thanks,
Jan


gdb/
2009-01-13  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Read in the DW_FORM_block* type attributes.
	* dwarf2read.c (enum dwarf2_get_attr_value): New.
	(dwarf2_get_attr_constant_value): Rename to ...
	(dwarf2_get_attr_value): ... and make its return value returned by
	a reference parameter, remove the former default value parameter.
	Support now also the attribute types DW_FORM_block, DW_FORM_block1,
	DW_FORM_block2 and DW_FORM_block4,
	(dwarf2_add_field): Update the caller.
	(read_subrange_type): Variables low and high are no longer initialized.
	Update the call of dwarf2_get_attr_value.  Support its new result type
	dwarf2_attr_block.
	(attr_form_is_block, attr_form_is_section_offset): New comment that they
	should be removed.
	(attr_form_is_constant): Remove the function.
	(dwarf2_symbol_mark_computed): Move the attr_form_is_block part to ...
	(dwarf_block_to_locexpr_baton): ... a new function here.
	* gdbtypes.h (TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED)
	(TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED): New.
	(TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED)
	(TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED): Base them on the define above.

--- gdb-cvs-clean/gdb/dwarf2read.c	2009-01-05 16:35:22.000000000 +0100
+++ gdb-cvs-dwarf2_get_attr_constant_value/gdb/dwarf2read.c	2009-01-12 22:57:30.000000000 +0100
@@ -1024,7 +1024,14 @@ static void store_in_ref_table (struct d
 
 static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
 
-static int dwarf2_get_attr_constant_value (struct attribute *, int);
+enum dwarf2_get_attr_value
+  {
+    dwarf2_attr_unknown,
+    dwarf2_attr_const,
+    dwarf2_attr_block
+  };
+static enum dwarf2_get_attr_value dwarf2_get_attr_value (struct attribute *attr,
+							 int *val_return);
 
 static struct die_info *follow_die_ref (struct die_info *,
 					struct attribute *,
@@ -1050,8 +1057,6 @@ static int attr_form_is_block (struct at
 
 static int attr_form_is_section_offset (struct attribute *);
 
-static int attr_form_is_constant (struct attribute *);
-
 static void dwarf2_symbol_mark_computed (struct attribute *attr,
 					 struct symbol *sym,
 					 struct dwarf2_cu *cu);
@@ -1098,6 +1103,9 @@ static void dwarf2_clear_marks (struct d
 
 static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
 
+static struct dwarf2_locexpr_baton *dwarf_block_to_locexpr_baton
+  (struct dwarf_block *dwarf_block, struct dwarf2_cu *cu);
+
 /* Try to locate the sections we need for DWARF 2 debugging
    information and return true if we have enough to do something.  */
 
@@ -3623,10 +3631,17 @@ dwarf2_add_field (struct field_info *fip
               dwarf2_complex_location_expr_complaint ();
               byte_offset = 0;
             }
-          else if (attr_form_is_constant (attr))
-            byte_offset = dwarf2_get_attr_constant_value (attr, 0);
-          else
-            byte_offset = decode_locdesc (DW_BLOCK (attr), cu);
+	  else switch (dwarf2_get_attr_value (attr, &byte_offset))
+	    {
+	    case dwarf2_attr_const:
+	      break;
+	    case dwarf2_attr_block:
+	      byte_offset = decode_locdesc (DW_BLOCK (attr), cu);
+	      break;
+	    case dwarf2_attr_unknown:
+	      /* complaint has been called by dwarf2_get_attr_value.  */
+	      break;
+	    }
 
           SET_FIELD_BITPOS (*fp, byte_offset * bits_per_byte);
 	}
@@ -5114,8 +5129,7 @@ read_subrange_type (struct die_info *die
   struct type *base_type;
   struct type *range_type;
   struct attribute *attr;
-  int low = 0;
-  int high = -1;
+  int low, high;
   char *name;
   
   base_type = die_type (die, cu);
@@ -5128,42 +5142,54 @@ read_subrange_type (struct die_info *die
 		     0, NULL, cu->objfile);
     }
 
-  if (cu->language == language_fortran)
-    { 
-      /* FORTRAN implies a lower bound of 1, if not given.  */
-      low = 1;
-    }
+  /* LOW_BOUND and HIGH_BOUND are set their final values below.  */
+  range_type = create_range_type (NULL, base_type, 0, - 1);
 
-  /* 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);
-
-  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;
-        }
+  switch (dwarf2_get_attr_value (attr, &low))
+    {
+    case dwarf2_attr_unknown:
+      TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (range_type) = 1;
+      if (cu->language == language_fortran)
+	{
+	  /* FORTRAN implies a lower bound of 1, if not given.  */
+	  low = 1;
+	}
       else
-        high = dwarf2_get_attr_constant_value (attr, 1);
+	{
+	  /* According to DWARF we should assume the value 0 only for
+	     LANGUAGE_C and LANGUAGE_CPLUS.  */
+	  low = 0;
+	}
+      /* PASSTHRU */
+    case dwarf2_attr_const:
+      TYPE_LOW_BOUND (range_type) = low;
+      if (low >= 0)
+	TYPE_UNSIGNED (range_type) = 1;
+      break;
+    case dwarf2_attr_block:
+      SET_FIELD_DWARF_BLOCK (TYPE_FIELD (range_type, 0),
+			     dwarf_block_to_locexpr_baton (DW_BLOCK (attr),
+							   cu));
+      break;
     }
 
-  range_type = create_range_type (NULL, base_type, low, high);
+  attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
+  switch (dwarf2_get_attr_value (attr, &high))
+    {
+    case dwarf2_attr_unknown:
+      TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type) = 1;
+      high = low - 1;
+      /* PASSTHRU */
+    case dwarf2_attr_const:
+      TYPE_HIGH_BOUND (range_type) = high;
+      break;
+    case dwarf2_attr_block:
+      SET_FIELD_DWARF_BLOCK (TYPE_FIELD (range_type, 1),
+			     dwarf_block_to_locexpr_baton (DW_BLOCK (attr),
+							   cu));
+      break;
+    }
 
   name = dwarf2_name (die, cu);
   if (name)
@@ -9292,25 +9318,39 @@ 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.  */
+/* Return the simplified type of value being held by the given attribute ATTR.
+   VAL_RETURN is filled only for the type dwarf2_attr_const.  */
 
-static int
-dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+static enum dwarf2_get_attr_value
+dwarf2_get_attr_value (struct attribute *attr, int *val_return)
 {
-  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
+  if (attr == NULL)
+    return dwarf2_attr_unknown;
+
+  switch (attr->form)
     {
+    case DW_FORM_sdata:
+      *val_return = DW_SND (attr);
+      return dwarf2_attr_const;
+
+    case DW_FORM_udata:
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+      *val_return = DW_UNSND (attr);
+      return dwarf2_attr_const;
+
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+      return dwarf2_attr_block;
+
+    default:
       complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"),
-                 dwarf_form_name (attr->form));
-      return default_value;
+		 dwarf_form_name (attr->form));
+      return dwarf2_attr_unknown;
     }
 }
 
@@ -10033,7 +10073,9 @@ dwarf_decode_macros (struct line_header 
 }
 
 /* Check if the attribute's form is a DW_FORM_block*
-   if so return true else false. */
+   if so return true else false.
+
+   FIXME: Unify with dwarf2_get_attr_value.  */
 static int
 attr_form_is_block (struct attribute *attr)
 {
@@ -10051,7 +10093,9 @@ attr_form_is_block (struct attribute *at
    Section 7.5.4, "Attribute Encodings", explains that no attribute
    may have a value that belongs to more than one of these classes; it
    would be ambiguous if we did, because we use the same forms for all
-   of them.  */
+   of them.
+
+   FIXME: Unify with dwarf2_get_attr_value.  */
 static int
 attr_form_is_section_offset (struct attribute *attr)
 {
@@ -10059,34 +10103,28 @@ attr_form_is_section_offset (struct attr
           || attr->form == DW_FORM_data8);
 }
 
+/* Convert type dwarf_block type into struct dwarf2_locexpr_baton.  
 
-/* Return non-zero if ATTR's value falls in the 'constant' class, or
-   zero otherwise.  When this function returns true, you can apply
-   dwarf2_get_attr_constant_value to it.
-
-   However, note that for some attributes you must check
-   attr_form_is_section_offset before using this test.  DW_FORM_data4
-   and DW_FORM_data8 are members of both the constant class, and of
-   the classes that contain offsets into other debug sections
-   (lineptr, loclistptr, macptr or rangelistptr).  The DWARF spec says
-   that, if an attribute's can be either a constant or one of the
-   section offset classes, DW_FORM_data4 and DW_FORM_data8 should be
-   taken as section offsets, not constants.  */
-static int
-attr_form_is_constant (struct attribute *attr)
+   Note that we're just copying the block's data pointer here, not the actual
+   data.  We're still pointing into the info_buffer for CU's objfile; right now
+   we never release that buffer, but when we do clean up properly this may need
+   to change.  */
+
+static struct dwarf2_locexpr_baton *
+dwarf_block_to_locexpr_baton (struct dwarf_block *dwarf_block,
+			      struct dwarf2_cu *cu)
 {
-  switch (attr->form)
-    {
-    case DW_FORM_sdata:
-    case DW_FORM_udata:
-    case DW_FORM_data1:
-    case DW_FORM_data2:
-    case DW_FORM_data4:
-    case DW_FORM_data8:
-      return 1;
-    default:
-      return 0;
-    }
+  struct dwarf2_locexpr_baton *baton;
+
+  baton = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (*baton));
+  baton->per_cu = cu->per_cu;
+  baton->size = dwarf_block->size;
+  baton->data = dwarf_block->data;
+
+  gdb_assert (baton->per_cu != NULL);
+  gdb_assert (baton->size == 0 || baton->data != NULL);
+
+  return baton;
 }
 
 static void
@@ -10118,6 +10156,12 @@ dwarf2_symbol_mark_computed (struct attr
       SYMBOL_OPS (sym) = &dwarf2_loclist_funcs;
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
+  else if (attr_form_is_block (attr))
+    {
+      SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs;
+      SYMBOL_LOCATION_BATON (sym)
+        = dwarf_block_to_locexpr_baton (DW_BLOCK (attr), cu);
+    }
   else
     {
       struct dwarf2_locexpr_baton *baton;
@@ -10127,24 +10171,11 @@ dwarf2_symbol_mark_computed (struct attr
       baton->per_cu = cu->per_cu;
       gdb_assert (baton->per_cu);
 
-      if (attr_form_is_block (attr))
-	{
-	  /* Note that we're just copying the block's data pointer
-	     here, not the actual data.  We're still pointing into the
-	     info_buffer for SYM's objfile; right now we never release
-	     that buffer, but when we do clean up properly this may
-	     need to change.  */
-	  baton->size = DW_BLOCK (attr)->size;
-	  baton->data = DW_BLOCK (attr)->data;
-	}
-      else
-	{
-	  dwarf2_invalid_attrib_class_complaint ("location description",
-						 SYMBOL_NATURAL_NAME (sym));
-	  baton->size = 0;
-	  baton->data = NULL;
-	}
-      
+      dwarf2_invalid_attrib_class_complaint ("location description",
+					     SYMBOL_NATURAL_NAME (sym));
+      baton->size = 0;
+      baton->data = NULL;
+
       SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs;
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
--- gdb-cvs-clean/gdb/gdbtypes.h	2009-01-05 16:35:25.000000000 +0100
+++ gdb-cvs-dwarf2_get_attr_constant_value/gdb/gdbtypes.h	2009-01-11 19:37:36.000000000 +0100
@@ -812,18 +812,20 @@ extern void allocate_cplus_struct_type (
 #define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0)
 #define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1)
 
-/* Moto-specific stuff for FORTRAN arrays */
-
-#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \
-   (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),1))
+/* Use these for unbound arrays such as GCC array[] at the end of struct.  */
+#define TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED(rangetype) \
+   TYPE_FIELD_ARTIFICIAL((rangetype),0)
+#define TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED(rangetype) \
+   TYPE_FIELD_ARTIFICIAL((rangetype),1)
 #define TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED(arraytype) \
-   (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),0))
-
-#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
-   (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE((arraytype))))
+   TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype))
+#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \
+   TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype))
 
 #define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \
    (TYPE_LOW_BOUND(TYPE_INDEX_TYPE((arraytype))))
+#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
+   (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE((arraytype))))
 
 /* C++ */
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]