diff mbox

[09/23] vla: changed string length semantic.

Message ID 1401861266-6240-10-git-send-email-keven.boell@intel.com
State New
Headers show

Commit Message

Keven Boell June 4, 2014, 5:54 a.m. UTC
This patch changes the semantic of the Dwarf string length
attribute to reflect the standard. This serves as pre-work
to get variable strings in Fortran to work.

2014-05-28  Keven Boell  <keven.boell@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>

	* dwarf2read.c (read_tag_string_type): changed
	semantic of DW_AT_string_length to be able to
	handle Dwarf blocks as well. Support for
	DW_AT_byte_length added to get correct length
	if specified in combination with
	DW_AT_string_length.
	(attr_to_dynamic_prop): added
	functionality to add Dwarf operators to baton
	data attribute. Added post values to baton
	as required by the string evaluation case.
	(read_subrange_type): Adapt caller.
	(set_die_type): Adapt caller.
	(add_post_values_to_baton): New function.
	* dwarf2loc.c (dwarf2_evaluate_property): Evaluate
	post processing dwarf.
	* dwarf2loc.h (struct dwarf2_property_baton): Add
	post dwarf values attribute.

Change-Id: I6edfa005f416cddc8e364d34891b9abf6b44f757

Signed-off-by: Keven Boell <keven.boell@intel.com>
---
 gdb/dwarf2loc.c  |   10 +++++
 gdb/dwarf2loc.h  |    3 ++
 gdb/dwarf2read.c |  129 +++++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 127 insertions(+), 15 deletions(-)
diff mbox

Patch

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 7ab734d..2473f80 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2533,6 +2533,11 @@  dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR address,
 
 		*value = value_as_address (val);
 	      }
+	    if (baton->post_values.data && baton->post_values.size > 0)
+	      {
+	        CORE_ADDR new_addr = *value;
+	        dwarf2_locexpr_baton_eval (&baton->post_values, new_addr, value);
+	      }
 	    return 1;
 	  }
       }
@@ -2555,6 +2560,11 @@  dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR address,
 	    if (!value_optimized_out (val))
 	      {
 		*value = value_as_address (val);
+		if (baton->post_values.data && baton->post_values.size > 0)
+		  {
+		    CORE_ADDR new_addr = *value;
+		    dwarf2_locexpr_baton_eval (&baton->post_values, new_addr, value);
+		  }
 		return 1;
 	      }
 	  }
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index fb65c5c..cf648eb 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -168,6 +168,9 @@  struct dwarf2_property_baton
     /* Location list to be evaluated in the context of REFERENCED_TYPE.  */
     struct dwarf2_loclist_baton loclist;
   };
+
+  /* Attributes, which will be pushed after evaluating locexpr or loclist.  */
+  struct dwarf2_locexpr_baton post_values;
 };
 
 extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ea66602..0b23701 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -1842,6 +1842,15 @@  static void free_dwo_file_cleanup (void *);
 static void process_cu_includes (void);
 
 static void check_producer (struct dwarf2_cu *cu);
+
+static int
+attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
+		      struct dwarf2_cu *cu, struct dynamic_prop *prop,
+		      const gdb_byte *additional_data, int additional_data_size);
+
+static void add_post_values_to_baton (struct dwarf2_property_baton *baton,
+        const gdb_byte *data, int size, struct dwarf2_cu *cu);
+
 
 /* Various complaints about symbol reading that don't abort the process.  */
 
@@ -14029,29 +14038,90 @@  read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct type *type, *range_type, *index_type, *char_type;
   struct attribute *attr;
-  unsigned int length;
+  unsigned int length = UINT_MAX;
+
+  index_type = objfile_type (objfile)->builtin_int;
+  range_type = create_static_range_type (NULL, index_type, 1, length);
 
+  /* If DW_AT_string_length is defined, the length is stored at some location
+   * in memory. */
   attr = dwarf2_attr (die, DW_AT_string_length, cu);
   if (attr)
     {
-      length = DW_UNSND (attr);
+      if (attr_form_is_block (attr))
+        {
+          struct attribute *byte_size, *bit_size;
+          struct dynamic_prop high;
+
+          byte_size = dwarf2_attr (die, DW_AT_byte_size, cu);
+          bit_size = dwarf2_attr (die, DW_AT_bit_size, cu);
+
+          /* DW_AT_byte_size should never occur together in combination with
+             DW_AT_string_length.  */
+          if ((byte_size == NULL && bit_size != NULL) ||
+                  (byte_size != NULL && bit_size == NULL))
+            complaint (&symfile_complaints, _("DW_AT_byte_size AND "
+                      "DW_AT_bit_size found together at the same time."));
+
+          /* If DW_AT_string_length AND DW_AT_byte_size exist together, it
+             describes the number of bytes that should be read from the length
+             memory location.  */
+          if (byte_size != NULL && bit_size == NULL)
+            {
+              /* Build new dwarf2_locexpr_baton structure with additions to the
+                 data attribute, to reflect DWARF specialities to get address
+                 sizes.  */
+              const gdb_byte append_ops[] = {
+                DW_OP_push_object_address,
+                /* DW_OP_deref_size: size of an address on the target machine
+                   (bytes), where the size will be specified by the next
+                   operand.  */
+                DW_OP_deref_size,
+                /* Operand for DW_OP_deref_size.  */
+                DW_UNSND (byte_size) };
+
+              if (!attr_to_dynamic_prop (attr, die, cu, &high,
+                      append_ops, ARRAY_SIZE (append_ops)))
+                complaint (&symfile_complaints,
+                        _("Could not parse DW_AT_byte_size"));
+            }
+          else if (bit_size != NULL && byte_size == NULL)
+            complaint (&symfile_complaints, _("DW_AT_string_length AND "
+                      "DW_AT_bit_size found but not supported yet."));
+          /* If DW_AT_string_length WITHOUT DW_AT_byte_size exist, the default
+             is the address size of the target machine.  */
+          else
+            {
+              if (!attr_to_dynamic_prop (attr, die, cu, &high, NULL, 0))
+                complaint (&symfile_complaints,
+                        _("Could not parse DW_AT_string_length"));
+            }
+
+          TYPE_RANGE_DATA (range_type)->high = high;
+        }
+      else
+        {
+          TYPE_HIGH_BOUND (range_type) = DW_UNSND (attr);
+          TYPE_HIGH_BOUND_KIND (range_type) = PROP_CONST;
+        }
     }
   else
     {
-      /* Check for the DW_AT_byte_size attribute.  */
+      /* Check for the DW_AT_byte_size attribute, which represents the length
+         in this case.  */
       attr = dwarf2_attr (die, DW_AT_byte_size, cu);
       if (attr)
         {
-          length = DW_UNSND (attr);
+          TYPE_HIGH_BOUND (range_type) = DW_UNSND (attr);
+          TYPE_HIGH_BOUND_KIND (range_type) = PROP_CONST;
         }
       else
         {
-          length = 1;
+          TYPE_HIGH_BOUND (range_type) = 1;
+          TYPE_HIGH_BOUND_KIND (range_type) = PROP_CONST;
         }
     }
 
-  index_type = objfile_type (objfile)->builtin_int;
-  range_type = create_static_range_type (NULL, index_type, 1, length);
   char_type = language_string_char_type (cu->language_defn, gdbarch);
   type = create_string_type (NULL, char_type, range_type);
 
@@ -14368,13 +14438,36 @@  read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   return set_die_type (die, type, cu);
 }
 
+/* Add post processing op-codes to a dwarf2_property_baton.  */
+
+static void add_post_values_to_baton (struct dwarf2_property_baton *baton,
+        const gdb_byte *data, int size, struct dwarf2_cu *cu)
+{
+  if (data != NULL && size > 0)
+    {
+      struct obstack *obstack = &cu->objfile->objfile_obstack;
+      gdb_byte *post_data;
+
+      post_data = obstack_alloc (obstack, size);
+      memcpy(post_data, data, size);
+      baton->post_values.data = post_data;
+      baton->post_values.size = size;
+      baton->post_values.per_cu = cu->per_cu;
+    } else {
+      baton->post_values.data = NULL;
+      baton->post_values.size = 0;
+      baton->post_values.per_cu = NULL;
+    }
+}
+
 /* 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_cu *cu, struct dynamic_prop *prop,
+		      const gdb_byte *additional_data, int additional_data_size)
 {
   struct dwarf2_property_baton *baton;
   struct obstack *obstack = &cu->objfile->objfile_obstack;
@@ -14387,8 +14480,10 @@  attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
       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;
+      baton->locexpr.size = DW_BLOCK (attr)->size;
+      add_post_values_to_baton (baton, additional_data,
+                                additional_data_size, cu);
       prop->data.baton = baton;
       prop->kind = PROP_LOCEXPR;
       gdb_assert (prop->data.baton != NULL);
@@ -14409,6 +14504,8 @@  attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
 	  baton = obstack_alloc (obstack, sizeof (*baton));
 	  baton->referenced_type = die_type (target_die, target_cu);
 	  fill_in_loclist_baton (cu, &baton->loclist, target_attr);
+	  add_post_values_to_baton (baton, additional_data,
+	                            additional_data_size, cu);
 	  prop->data.baton = baton;
 	  prop->kind = PROP_LOCLIST;
 	  gdb_assert (prop->data.baton != NULL);
@@ -14420,6 +14517,8 @@  attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
 	  baton->locexpr.per_cu = cu->per_cu;
 	  baton->locexpr.size = DW_BLOCK (target_attr)->size;
 	  baton->locexpr.data = DW_BLOCK (target_attr)->data;
+	  add_post_values_to_baton (baton, additional_data,
+	                            additional_data_size, cu);
 	  prop->data.baton = baton;
 	  prop->kind = PROP_LOCEXPR;
 	  gdb_assert (prop->data.baton != NULL);
@@ -14509,17 +14608,17 @@  read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 
   attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
   if (attr)
-    attr_to_dynamic_prop (attr, die, cu, &low);
+    attr_to_dynamic_prop (attr, die, cu, &low, NULL, 0);
   else if (!low_default_is_valid)
     complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
 				      "- DIE at 0x%x [in module %s]"),
 	       die->offset.sect_off, objfile_name (cu->objfile));
 
   attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
-  if (!attr_to_dynamic_prop (attr, die, cu, &high))
+  if (!attr_to_dynamic_prop (attr, die, cu, &high, NULL, 0))
     {
       attr = dwarf2_attr (die, DW_AT_count, cu);
-      if (attr_to_dynamic_prop (attr, die, cu, &high))
+      if (attr_to_dynamic_prop (attr, die, cu, &high, NULL, 0))
 	{
 	  /* If bounds are constant do the final calculation here.  */
 	  if (low.kind == PROP_CONST && high.kind == PROP_CONST)
@@ -21520,7 +21619,7 @@  set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     {
       struct dynamic_prop prop;
 
-      if (attr_to_dynamic_prop (attr, die, cu, &prop))
+      if (attr_to_dynamic_prop (attr, die, cu, &prop, NULL, 0))
         {
           TYPE_ALLOCATED_PROP (type)
             = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
@@ -21534,7 +21633,7 @@  set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     {
       struct dynamic_prop prop;
 
-      if (attr_to_dynamic_prop (attr, die, cu, &prop))
+      if (attr_to_dynamic_prop (attr, die, cu, &prop, NULL, 0))
         {
           TYPE_ASSOCIATED_PROP (type)
             = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
@@ -21548,7 +21647,7 @@  set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     {
       struct dynamic_prop prop;
 
-      if (attr_to_dynamic_prop (attr, die, cu, &prop))
+      if (attr_to_dynamic_prop (attr, die, cu, &prop, NULL, 0))
 	{
 	  TYPE_DATA_LOCATION (type)
 	    = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));