This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch] [VLA 1/2] Read in the DW_FORM_block* type attributes
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Cc: Joel Brobecker <brobecker at adacore dot com>, Ulrich Weigand <uweigand at de dot ibm dot com>, Jim Blandy <jimb at red-bean dot com>, Tobias Burnus <burnus at net-b dot de>
- Date: Tue, 13 Jan 2009 02:39:14 +0100
- Subject: [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++ */