[V2 02/23] dwarf: add DW_AT_data_location support

Keven Boell keven.boell@intel.com
Fri Jul 11 09:22:00 GMT 2014


An object might have a descriptor proceeding the actual value.
To point the debugger to the actually value of an object
DW_AT_data_location is used for. For example the compile may
emit for this entity:

  1| int foo[N];

the following descriptor:

struct array {
  size_t size;
  void*  data; // DW_AT_data_location describes this location
}

This allows GDB to print the actual data of an type.
E.g. for the related dwarf output of a dynamic array
using DW_AT_data_location:

 <1><b1>: Abbrev Number: 8 (DW_TAG_array_type)
    <b2>   DW_AT_data_location: 2 byte block: 97 6
		(DW_OP_push_object_address; DW_OP_deref)

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

	* dwarf2read.c (set_die_type): Parse and save DW_AT_data_location
	attribute.
	* gdbtypes.c (is_dynamic_type): Consider a type being dynamic if
	the data location has not yet been resolved.
	(resolve_dynamic_type): Evaluate data location baton
	if present and save its value.
	* gdbtypes.h <main_type>: Add data_location.
	(TYPE_DATA_LOCATION): New macro.
	(TYPE_DATA_LOCATION_ADDR): New macro.
	(TYPE_DATA_LOCATION_IS_ADDRESS): New macro.
	* value.c: Include dwarf2loc.h.
	(value_fetch_lazy): Use data location addres to read value from
	memory.
	(coerce_ref): Construct new value from data location.

Change-Id: Ic633fa125efdb5e438204e4f80bb3a1c97758b12

Signed-off-by: Keven Boell <keven.boell@intel.com>
---
 gdb/dwarf2read.c |   11 +++++++++++
 gdb/gdbtypes.c   |   33 ++++++++++++++++++++++++++++++---
 gdb/gdbtypes.h   |   15 +++++++++++++++
 gdb/value.c      |    8 +++++++-
 4 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 276d2f1..20886b0 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -21673,6 +21673,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 {
   struct dwarf2_per_cu_offset_and_type **slot, ofs;
   struct objfile *objfile = cu->objfile;
+  struct attribute *attr;
+  struct dynamic_prop prop;
 
   /* For Ada types, make sure that the gnat-specific data is always
      initialized (if not already set).  There are a few types where
@@ -21687,6 +21689,15 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
       && !HAVE_GNAT_AUX_INFO (type))
     INIT_GNAT_SPECIFIC (type);
 
+  /* Read DW_AT_data_location and set in type.  */
+  attr = dwarf2_attr (die, DW_AT_data_location, cu);
+  if (attr_to_dynamic_prop (attr, die, cu, &prop))
+    {
+      TYPE_DATA_LOCATION (type)
+        = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
+      *TYPE_DATA_LOCATION (type) = prop;
+    }
+
   if (dwarf2_per_objfile->die_type_hash == NULL)
     {
       dwarf2_per_objfile->die_type_hash =
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 08e5884..f4da142 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1630,11 +1630,19 @@ is_dynamic_type (struct type *type)
       {
 	gdb_assert (TYPE_NFIELDS (type) == 1);
 
-	/* The array is dynamic if either the bounds are dynamic,
-	   or the elements it contains have a dynamic contents.  */
+	/* The array is dynamic if either
+     - the bounds are dynamic,
+	   - the elements it contains have a dynamic contents
+     - a data_locaton attribute was found.  */
 	if (is_dynamic_type (TYPE_INDEX_TYPE (type)))
 	  return 1;
-	return is_dynamic_type (TYPE_TARGET_TYPE (type));
+	else if (TYPE_DATA_LOCATION (type) != NULL
+	         && (TYPE_DATA_LOCATION_KIND (type) == PROP_LOCEXPR
+	             || TYPE_DATA_LOCATION_KIND (type) == PROP_LOCLIST))
+    return 1;
+  else
+    return is_dynamic_type (TYPE_TARGET_TYPE (type));
+	break;
       }
 
     case TYPE_CODE_STRUCT:
@@ -1830,6 +1838,8 @@ resolve_dynamic_type (struct type *type, CORE_ADDR addr)
 {
   struct type *real_type = check_typedef (type);
   struct type *resolved_type = type;
+  const struct dynamic_prop *prop;
+  CORE_ADDR value;
 
   if (!is_dynamic_type (real_type))
     return type;
@@ -1869,6 +1879,16 @@ resolve_dynamic_type (struct type *type, CORE_ADDR addr)
       break;
     }
 
+  /* Resolve data_location attribute.  */
+  prop = TYPE_DATA_LOCATION (resolved_type);
+  if (dwarf2_evaluate_property (prop, addr, &value))
+    {
+      TYPE_DATA_LOCATION_ADDR (resolved_type) = value;
+      TYPE_DATA_LOCATION_KIND (resolved_type) = PROP_CONST;
+    }
+  else
+    TYPE_DATA_LOCATION (resolved_type) = NULL;
+
   return resolved_type;
 }
 
@@ -4078,6 +4098,13 @@ copy_type_recursive (struct objfile *objfile,
       *TYPE_RANGE_DATA (new_type) = *TYPE_RANGE_DATA (type);
     }
 
+  /* Copy the data location information.  */
+  if (TYPE_DATA_LOCATION (type) != NULL)
+    {
+      TYPE_DATA_LOCATION (new_type) = xmalloc (sizeof (struct dynamic_prop));
+      *TYPE_DATA_LOCATION (new_type) = *TYPE_DATA_LOCATION (type);
+    }
+
   /* Copy pointers to other types.  */
   if (TYPE_TARGET_TYPE (type))
     TYPE_TARGET_TYPE (new_type) = 
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index bb6352d..17b9fe0 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -725,6 +725,11 @@ struct main_type
 
     struct func_type *func_stuff;
   } type_specific;
+
+  /* * Contains a location description value for the current type. Evaluating
+     this field yields to the location of the data for an object.  */
+
+  struct dynamic_prop *data_location;
 };
 
 /* * A ``struct type'' describes a particular instance of a type, with
@@ -1204,6 +1209,16 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_LOW_BOUND_KIND(range_type) \
   TYPE_RANGE_DATA(range_type)->low.kind
 
+/* Attribute accessors for the type data location.  */
+#define TYPE_DATA_LOCATION(thistype) \
+  TYPE_MAIN_TYPE(thistype)->data_location
+#define TYPE_DATA_LOCATION_BATON(thistype) \
+  TYPE_DATA_LOCATION (thistype)->data.baton
+#define TYPE_DATA_LOCATION_ADDR(thistype) \
+  TYPE_DATA_LOCATION (thistype)->data.const_val
+#define TYPE_DATA_LOCATION_KIND(thistype) \
+  TYPE_DATA_LOCATION (thistype)->kind
+
 /* Moto-specific stuff for FORTRAN arrays.  */
 
 #define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \
diff --git a/gdb/value.c b/gdb/value.c
index 557056f..3c73683 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3699,8 +3699,14 @@ value_fetch_lazy (struct value *val)
     }
   else if (VALUE_LVAL (val) == lval_memory)
     {
-      CORE_ADDR addr = value_address (val);
       struct type *type = check_typedef (value_enclosing_type (val));
+      CORE_ADDR addr;
+
+      if (TYPE_DATA_LOCATION (type) != NULL
+	  && TYPE_DATA_LOCATION_KIND (type) == PROP_CONST)
+	addr = TYPE_DATA_LOCATION_ADDR (type);
+      else
+	addr = value_address (val);
 
       if (TYPE_LENGTH (type))
 	read_value_memory (val, 0, value_stack (val),
-- 
1.7.9.5



More information about the Gdb-patches mailing list