diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2019-05-08 13:16:03 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2019-07-12 12:09:54 +0100 |
commit | 9a49df9d4bfc7ff03fed751e12b1bc32fbee4fb2 (patch) | |
tree | 8cc573908053c52a291263c54c6a214541b2ab1c /gdb/dwarf2read.c | |
parent | b86352cfc17fb7f07d5da9efcfd59f8b2bd08eee (diff) | |
download | gdb-9a49df9d4bfc7ff03fed751e12b1bc32fbee4fb2.zip gdb-9a49df9d4bfc7ff03fed751e12b1bc32fbee4fb2.tar.gz gdb-9a49df9d4bfc7ff03fed751e12b1bc32fbee4fb2.tar.bz2 |
gdb: Carry default property type around with dynamic properties
This commit is preparation for the next one, with the aim of better
supporting signed dynamic properties on targets where the address size
specified in the DWARF headers is smaller than a CORE_ADDR, for
example debugging an i386 application on x86-64.
Consider this small Fortran program 'bounds.f90':
program test
integer, allocatable :: array (:)
allocate (array (-5:5))
array(3) = 1
end program test
Compiled with 'gfortran -m32 -g3 -O0 -o bounds bounds.f90'. The DWARF
for 'array' looks like this:
<2><97>: Abbrev Number: 10 (DW_TAG_variable)
<98> DW_AT_name : (indirect string, offset: 0x0): array
<9c> DW_AT_decl_file : 1
<9d> DW_AT_decl_line : 2
<9e> DW_AT_type : <0xaf>
<a2> DW_AT_location : 2 byte block: 91 58 (DW_OP_fbreg: -40)
<2><a5>: Abbrev Number: 11 (DW_TAG_lexical_block)
<a6> DW_AT_low_pc : 0x80485c3
<aa> DW_AT_high_pc : 0x8b
<2><ae>: Abbrev Number: 0
<1><af>: Abbrev Number: 12 (DW_TAG_array_type)
<b0> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref)
<b3> DW_AT_allocated : 4 byte block: 97 6 30 2e (DW_OP_push_object_address; DW_OP_deref; DW_OP_lit0; DW_OP_ne)
<b8> DW_AT_type : <0x2a>
<2><bc>: Abbrev Number: 13 (DW_TAG_subrange_type)
<bd> DW_AT_lower_bound : 4 byte block: 97 23 10 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 16; DW_OP_deref)
<c2> DW_AT_upper_bound : 4 byte block: 97 23 14 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 20; DW_OP_deref)
<c7> DW_AT_byte_stride : 6 byte block: 97 23 c 6 34 1e (DW_OP_push_object_address; DW_OP_plus_uconst: 12; DW_OP_deref; DW_OP_lit4; DW_OP_mul)
<2><ce>: Abbrev Number: 0
If we look at the DW_AT_lower_bound attribute, which will become a
dynamic property that GDB evaluates when needed by calling
dwarf2_evaluate_property.
The process of evaluating a dynamic property requires GDB to execute
each DW_OP_* operation, the results of these operations is held on a
stack of 'struct value *'s.
When the entire expression is evaluated the result is on top of the
stack.
If we look at DW_AT_lower_bound then the last operation is
DW_OP_deref, this loads a signed address the size of which matches the
DWARF address size, and so in our i386 on x86-64 situation, the top of
the stack will be a signed 4-byte value.
The problem is how these values are fetched from the stack. Currently
they are always fetched by a call to dwarf_expr_context::fetch_address,
which converts the value to an unsigned value with a length matching
the values current length, before converting to a CORE_ADDR. This
means we loose the signed nature of the property.
I wonder if the best solution for dealing with signed properties will
be to move away from an over reliance on fetch_address, and instead
come up with a new solution that considers the current type of the
value on the stack, and the type that the value needs to become;
basically a solution built around casting rather than assuming we
always want an address.
However, before we can start to even think about moving away from
fetch_address, there is a more urgent issue to fix, which is we don't
currently know what type each property should be. We just hold the
value of the property in a CORE_ADDR as returned by fetch_address, and
rely on higher level code (outside of the DWARF expression evaluation
code) to fix things up for us. This is what this patch aims to
address.
When creating a dynamic property (see attr_to_dynamic_prop in
dwarf2read.c) we can sometimes figure out the type of a property; if
the property is a reference to another DIE then it will have a
DW_AT_type attribute.
However, the DW_AT_lower_bound case above isn't a reference to another
DIE, it's just a DWARF expression. We don't have any indication for
what type the property should have.
Luckily, the DWARF spec helps us out, for the lower and upper bounds
5.13 of the DWARFv5 spec tells us that without any other type
information the bounds are signed integers the same size as a DWARF
address.
It is my belief that we can find a suitable default type for every
dynamic property, either specified explicitly in the DWARF spec, or we
can infer an obvious choice if the spec doesn't help us.
This commit extends the creation of all dynamic properties to include
suggesting a suitable default type, all dynamic properties now always
carry their type around with them.
In later commits we can use this property type to ensure that the
value we extract from the DWARF stack is handled in a suitable manor
to correctly maintain its sign extension.
There should be no user visible changes from this commit. The actual
fix to correctly support negative array bounds will come later.
gdb/ChangeLog:
* dwarf2loc.c (dwarf2_evaluate_property): Update to take account
of changes to field names, and use new is_reference field to
decide if a property is a reference or not.
* dwarf2loc.h (struct dwarf2_locexpr_baton): Add 'is_reference'
field.
(struct dwarf2_property_baton): Update header comment, rename
'referenced_type' to 'property_type' and update comments.
* dwarf2read.c (attr_to_dynamic_prop): Add extra parameter to hold
default property type, store in property baton, update to take
accound of renamed field.
(read_func_scope): Update call to attr_to_dynamic_prop.
(read_array_type): Likewise.
(dwarf2_per_cu_addr_sized_int_type): New function.
(read_subrange_index_type): Move type finding code to
dwarf2_per_cu_addr_sized_int_type.
(read_subrange_type): Update calls to attr_to_dynamic_prop.
(dwarf2_per_cu_addr_type): New function.
(set_die_type): Update calls to attr_to_dynamic_prop.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 120 |
1 files changed, 82 insertions, 38 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index e918792..3d90d63 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1810,7 +1810,7 @@ static void read_signatured_type (struct signatured_type *); static int attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, struct dwarf2_cu *cu, - struct dynamic_prop *prop); + struct dynamic_prop *prop, struct type *type); /* memory allocation interface */ @@ -1890,6 +1890,10 @@ static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu, static void process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile); +static struct type *dwarf2_per_cu_addr_type (struct dwarf2_per_cu_data *per_cu); +static struct type *dwarf2_per_cu_addr_sized_int_type + (struct dwarf2_per_cu_data *per_cu, bool unsigned_p); + /* Class, the destructor of which frees all allocated queue entries. This will only have work to do if an error was thrown while processing the dwarf. If no error was thrown then the queue entries should have all @@ -13683,7 +13687,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { newobj->static_link = XOBNEW (&objfile->objfile_obstack, struct dynamic_prop); - attr_to_dynamic_prop (attr, die, cu, newobj->static_link); + attr_to_dynamic_prop (attr, die, cu, newobj->static_link, + dwarf2_per_cu_addr_type (cu->per_cu)); } cu->list_in_scope = cu->get_builder ()->get_local_symbols (); @@ -16439,10 +16444,13 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) if (attr != NULL) { int stride_ok; + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); byte_stride_prop = (struct dynamic_prop *) alloca (sizeof (struct dynamic_prop)); - stride_ok = attr_to_dynamic_prop (attr, die, cu, byte_stride_prop); + stride_ok = attr_to_dynamic_prop (attr, die, cu, byte_stride_prop, + prop_type); if (!stride_ok) { complaint (_("unable to read array DW_AT_byte_stride " @@ -17654,22 +17662,26 @@ read_base_type (struct die_info *die, 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) + struct dwarf2_cu *cu, struct dynamic_prop *prop, + struct type *default_type) { struct dwarf2_property_baton *baton; struct obstack *obstack = &cu->per_cu->dwarf2_per_objfile->objfile->objfile_obstack; + gdb_assert (default_type != NULL); + if (attr == NULL || prop == NULL) return 0; if (attr_form_is_block (attr)) { baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = NULL; + baton->property_type = default_type; baton->locexpr.per_cu = cu->per_cu; baton->locexpr.size = DW_BLOCK (attr)->size; baton->locexpr.data = DW_BLOCK (attr)->data; + baton->locexpr.is_reference = false; prop->data.baton = baton; prop->kind = PROP_LOCEXPR; gdb_assert (prop->data.baton != NULL); @@ -17694,7 +17706,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, if (attr_form_is_section_offset (target_attr)) { baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = die_type (target_die, target_cu); + baton->property_type = die_type (target_die, target_cu); fill_in_loclist_baton (cu, &baton->loclist, target_attr); prop->data.baton = baton; prop->kind = PROP_LOCLIST; @@ -17703,10 +17715,11 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, else if (attr_form_is_block (target_attr)) { baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = die_type (target_die, target_cu); + baton->property_type = die_type (target_die, target_cu); baton->locexpr.per_cu = cu->per_cu; baton->locexpr.size = DW_BLOCK (target_attr)->size; baton->locexpr.data = DW_BLOCK (target_attr)->data; + baton->locexpr.is_reference = true; prop->data.baton = baton; prop->kind = PROP_LOCEXPR; gdb_assert (prop->data.baton != NULL); @@ -17727,7 +17740,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, return 0; baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = read_type_die (target_die->parent, + baton->property_type = read_type_die (target_die->parent, target_cu); baton->offset_info.offset = offset; baton->offset_info.type = die_type (target_die, target_cu); @@ -17752,6 +17765,37 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, return 1; } +/* Find an integer type the same size as the address size given in the + compilation unit header for PER_CU. UNSIGNED_P controls if the integer + is unsigned or not. */ + +static struct type * +dwarf2_per_cu_addr_sized_int_type (struct dwarf2_per_cu_data *per_cu, + bool unsigned_p) +{ + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile; + int addr_size = dwarf2_per_cu_addr_size (per_cu); + struct type *int_type; + + /* Helper macro to examine the various builtin types. */ +#define TRY_TYPE(F) \ + int_type = (unsigned_p \ + ? objfile_type (objfile)->builtin_unsigned_ ## F \ + : objfile_type (objfile)->builtin_ ## F); \ + if (int_type != NULL && TYPE_LENGTH (int_type) == addr_size) \ + return int_type + + TRY_TYPE (char); + TRY_TYPE (short); + TRY_TYPE (int); + TRY_TYPE (long); + TRY_TYPE (long_long); + +#undef TRY_TYPE + + gdb_assert_not_reached ("unable to find suitable integer type"); +} + /* Read the DW_AT_type attribute for a sub-range. If this attribute is not present (which is valid) then compute the default type based on the compilation units address size. */ @@ -17774,30 +17818,7 @@ read_subrange_index_type (struct die_info *die, struct dwarf2_cu *cu) FIXME: muller/2010-05-28: Possible references to object for low bound, high bound or count are not yet handled by this code. */ if (TYPE_CODE (index_type) == TYPE_CODE_VOID) - { - struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - int addr_size = gdbarch_addr_bit (gdbarch) /8; - struct type *int_type = objfile_type (objfile)->builtin_int; - - /* Test "int", "long int", and "long long int" objfile types, - and select the first one having a size above or equal to the - architecture address size. */ - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - index_type = int_type; - else - { - int_type = objfile_type (objfile)->builtin_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - index_type = int_type; - else - { - int_type = objfile_type (objfile)->builtin_long_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - index_type = int_type; - } - } - } + index_type = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); return index_type; } @@ -17866,7 +17887,7 @@ 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, base_type); else if (!low_default_is_valid) complaint (_("Missing DW_AT_lower_bound " "- DIE at %s [in module %s]"), @@ -17875,10 +17896,10 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) struct attribute *attr_ub, *attr_count; attr = attr_ub = 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, base_type)) { attr = attr_count = 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, base_type)) { /* If bounds are constant do the final calculation here. */ if (low.kind == PROP_CONST && high.kind == PROP_CONST) @@ -25241,6 +25262,24 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu) return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); } +/* Return a type that is a generic pointer type, the size of which matches + the address size given in the compilation unit header for PER_CU. */ +static struct type * +dwarf2_per_cu_addr_type (struct dwarf2_per_cu_data *per_cu) +{ + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile; + struct type *void_type = objfile_type (objfile)->builtin_void; + struct type *addr_type = lookup_pointer_type (void_type); + int addr_size = dwarf2_per_cu_addr_size (per_cu); + + if (TYPE_LENGTH (addr_type) == addr_size) + return addr_type; + + addr_type + = dwarf2_per_cu_addr_sized_int_type (per_cu, TYPE_UNSIGNED (addr_type)); + return addr_type; +} + /* Return DWARF version number of PER_CU. */ short @@ -25507,7 +25546,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_allocated, cu); if (attr_form_is_block (attr)) { - if (attr_to_dynamic_prop (attr, die, cu, &prop)) + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); + if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type)) add_dyn_prop (DYN_PROP_ALLOCATED, prop, type); } else if (attr != NULL) @@ -25521,7 +25562,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_associated, cu); if (attr_form_is_block (attr)) { - if (attr_to_dynamic_prop (attr, die, cu, &prop)) + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); + if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type)) add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type); } else if (attr != NULL) @@ -25533,7 +25576,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) /* 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)) + if (attr_to_dynamic_prop (attr, die, cu, &prop, + dwarf2_per_cu_addr_type (cu->per_cu))) add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type); if (dwarf2_per_objfile->die_type_hash == NULL) |