Re: [PATCH] Handle DW_TAG_subrange_type

Joel Brobecker
2003-11-24T09:51:00Z

[-- Attachment #1: Type: text/plain, Size: 929 bytes --]

> When trying to debug Ada code you often get a DW_TAG_subrange_type, which
> gdb can't handle yet.

Hmmm, I don't remember having submitted the patch to emit these subrange
types. Maybe somebody else managed to add this capability already?
Do you confirm these types are emitted for modular types (for instance
"type Mod_Type is mod 4")?

> 2003-11-22 Andreas Schwab <schwab@suse.de>
>
> * dwarf2read.c (dwarf2_non_const_array_bound_ignored_complaint):
> New function.
> (read_subrange_type): New function.
> (process_die): Handle DW_TAG_subrange_type.
> (read_type_die): Likewise.

Also, FYI, we made a very similar change in GDB to support these types.
We did factor out a bit the code that extracts constant bound values
into a function. And we also sprinkled a bit more of the handlers for
DW_TAG_subrange_type cases. I am attaching the patch (against GDB 6.0,
but shouldn't be too hard to adapt).

Cheers,
--
Joel

[-- Attachment #2: dwarf2read.c.diff --]
[-- Type: text/plain, Size: 4785 bytes --]

Index: dwarf2read.c
===================================================================
RCS file: /nile.c/cvs/Dev/gdb/gdb-6.0/gdb/dwarf2read.c,v
retrieving revision 1.1
retrieving revision 1.5
diff -u -p -r1.1 -r1.5
--- dwarf2read.c 5 Oct 2003 10:39:45 -0000 1.1
+++ dwarf2read.c 19 Nov 2003 18:02:23 -0000 1.5
@@ -783,6 +783,9 @@ static void read_typedef (struct die_inf

static void read_base_type (struct die_info *, struct objfile *);

+static void read_subrange_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header);
+
static void read_file_scope (struct die_info *, struct objfile *,
const struct comp_unit_head *);

@@ -896,6 +899,8 @@ static void dwarf2_empty_hash_tables (vo

static unsigned int dwarf2_get_ref_die_offset (struct attribute *);

+static int dwarf2_get_attr_constant_value (struct attribute *);
+
static struct die_info *follow_die_ref (unsigned int);

static struct type *dwarf2_fundamental_type (struct objfile *, int);
@@ -1418,6 +1455,7 @@ scan_partial_symbols (char *info_ptr, st
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
+ case DW_TAG_subrange_type:
if ((pdi.is_external || nesting_level == file_scope_level)
&& !pdi.is_declaration)
{
@@ -1555,6 +1595,7 @@ add_partial_symbol (struct partial_die_i
break;
case DW_TAG_typedef:
case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
@@ -1803,6 +1844,14 @@ process_die (struct die_info *die, struc
new_symbol (die, die->type, objfile, cu_header);
}
break;
+ case DW_TAG_subrange_type:
+ read_subrange_type (die, objfile, cu_header);
+ if (dwarf_attr (die, DW_AT_name))
+ {
+ /* Add a typedef symbol for the base type definition. */
+ new_symbol (die, die->type, objfile, cu_header);
+ }
+ break;
case DW_TAG_common_block:
read_common_block (die, objfile, cu_header);
break;
@@ -3644,6 +3725,47 @@ read_base_type (struct die_info *die, st
die->type = type;
}

+/* Read the given DW_AT_subrange DIE. */
+
+static void
+read_subrange_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
+{
+ struct type *base_type;
+ struct type *range_type;
+ struct attribute *attr;
+ int low = 0;
+ int high = -1;
+
+ /* If we have already decoded this die, then nothing more to do. */
+ if (die->type)
+ return;
+
+ base_type = die_type (die, objfile, cu_header);
+ if (base_type == NULL)
+ {
+ complaint (&symfile_complaints,
+ "DW_AT_type missing from DW_TAG_subrange_type");
+ return;
+ }
+
+ attr = dwarf_attr (die, DW_AT_lower_bound);
+ if (attr)
+ low = dwarf2_get_attr_constant_value (attr);
+
+ attr = dwarf_attr (die, DW_AT_upper_bound);
+ if (attr)
+ high = dwarf2_get_attr_constant_value (attr);
+
+ range_type = create_range_type (NULL, base_type, low, high);
+
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ TYPE_NAME (range_type) = DW_STRING (attr);
+
+ die->type = range_type;
+}
+
/* Read a whole compilation unit into a linked list of dies. */

static struct die_info *
case DW_TAG_variable:
@@ -5274,6 +5409,7 @@ new_symbol (struct die_info *die, struct
break;
case DW_TAG_typedef:
case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, list_in_scope);
@@ -5555,6 +5691,9 @@ read_type_die (struct die_info *die, str
case DW_TAG_typedef:
read_typedef (die, objfile, cu_header);
break;
+ case DW_TAG_subrange_type:
+ read_subrange_type (die, objfile, cu_header);
+ break;
case DW_TAG_base_type:
read_base_type (die, objfile);
break;
@@ -6693,6 +6836,27 @@ dwarf2_get_ref_die_offset (struct attrib
dwarf_form_name (attr->form));
}
return result;
+}
+
+/* Return the constant value held by the given attribute. Return -1
+ if the value held by the attribute is not constant. */
+
+static int
+dwarf2_get_attr_constant_value (struct attribute *attr)
+{
+ 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
+ {
+ complaint (&symfile_complaints, "Attribute value is not a constant");
+ return -1;
+ }
}

static struct die_info *