Revision | f56331b468908d1502c7ae26adab6f9b858cb13f (tree) |
---|---|
Time | 2015-12-10 01:33:21 |
Author | Kevin Buettner <kevinb@redh...> |
Commiter | Kevin Buettner |
dwarf2loc.c: Perform a pointer to address conversion for DWARF_VALUE_MEMORY.
This patch fixes the following failures for rl78-elf:
FAIL: gdb.base/vla-datatypes.exp: print int_vla
FAIL: gdb.base/vla-datatypes.exp: print unsigned_int_vla
FAIL: gdb.base/vla-datatypes.exp: print double_vla
FAIL: gdb.base/vla-datatypes.exp: print float_vla
FAIL: gdb.base/vla-datatypes.exp: print long_vla
FAIL: gdb.base/vla-datatypes.exp: print unsigned_long_vla
FAIL: gdb.base/vla-datatypes.exp: print char_vla
FAIL: gdb.base/vla-datatypes.exp: print short_vla
FAIL: gdb.base/vla-datatypes.exp: print unsigned_short_vla
FAIL: gdb.base/vla-datatypes.exp: print unsigned_char_vla
FAIL: gdb.base/vla-datatypes.exp: print foo_vla
FAIL: gdb.base/vla-datatypes.exp: print bar_vla
FAIL: gdb.base/vla-datatypes.exp: print vla_struct_object
FAIL: gdb.base/vla-datatypes.exp: print vla_union_object
FAIL: gdb.base/vla-ptr.exp: print td_vla
FAIL: gdb.mi/mi-vla-c99.exp: evaluate complete vla
The first failure in this bunch occurs due to printing an incorrect
result for a variable length array:
The result should actually be this:
When I started examining this bug, I found that printing an
individual array element worked correctly. E.g. "print int_vla[2]"
resulted in 4 being printed. I have not looked closely to see why
this is the case.
I found that evaluation of the location expression for int_vla was
causing problems. This is the relevant DWARF entry for int_vla:
<2><15a>: Abbrev Number: 10 (DW_TAG_variable)
I found that DW_OP_breg22 was providing a correct result.
DW_OP_deref_size was fetching the correct value from memory. However,
the value being fetched should be considered a pointer.
DW_OP_deref_size zero extends the fetched value prior to pushing
it onto the evaluation stack. (The DWARF-4 document specifies this
action; so GDB is faithfully implementing the DWARF-4 specification.)
However, zero extending the pointer is not sufficient for converting
that value to an address for rl78 and (perhaps) other architectures
which define a pointer_to_address' method. (I suspect that m32c
would have the same problem.)
Ideally, we would perform the pointer to address conversion in
DW_OP_deref_size. We don't, however, know the type of the object
that the address refers to in DW_OP_deref_size. I can't think
of a way to infer the type at that point in the code.
Before proceeding, I should note that there are two other DWARF
operations that could be used in place of DW_OP_deref_size. One of
these is DW_OP_GNU_deref_type. Current GDB implements this operation,
but as is obvious from the name, it is non-standard DWARF. The other
operation is DW_OP_xderef_size. Even though it's part of DWARF-2
through DWARF-4 specifications, it's not presently implemented in GDB.
Present day GCC does not output dwarf expressions containing this
operation either. [Of the two, I like DW_OP_GNU_deref_type better.
Using it avoids the need to specify an "address space identifier".
(GCC, GDB, and other non-free tools all need to agree on the meanings
of these identifiers.)]
Back to the bug analysis...
The closest consumer of the DW_OP_deref_size result is the
DWARF_VALUE_MEMORY case in dwarf2_evaluate_loc_desc_full. At that
location, we do know the object type to which the address is intended
to refer. I added code to perform a pointer to address conversion at
this location. (See the patch.)
I do have some misgivings regarding this patch. As noted earlier, it
would really be better to perform the pointer to address conversion in
DW_OP_deref_size. I can't, however, think of a way to make this work.
Changing GCC to output one of the other aforementioned operations might
be preferable but, as noted earlier, these solutions have problems as
well. Long term, I think it'd be good to have something like
DW_OP_GNU_deref_type become part of the standard. If that can't or
won't happen, we'll need to implement DW_OP_xderef_size.
But until that happens, this patch will work for expressions in which
DW_OP_deref_size occurs last. It should even work for dereferences
followed by adding an offset. I don't think it'll work for more than
one dereference in the same expression.
gdb/ChangeLog:
* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Perform a pointer
to address conversion for DWARF_VALUE_MEMORY.
@@ -1,3 +1,8 @@ | ||
1 | +2015-12-09 Kevin Buettner <kevinb@redhat.com> | |
2 | + | |
3 | + * dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Perform a pointer | |
4 | + to address conversion for DWARF_VALUE_MEMORY. | |
5 | + | |
1 | 6 | 2015-12-09 Luis Machado <lgustavo@codesourcery.com> |
2 | 7 | |
3 | 8 | * gdb/mi/mi-cmd-var.c (mi_parse_format): Handle new "zero-hexadecimal" |
@@ -2343,9 +2343,30 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, | ||
2343 | 2343 | |
2344 | 2344 | case DWARF_VALUE_MEMORY: |
2345 | 2345 | { |
2346 | + struct type *ptr_type; | |
2346 | 2347 | CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0); |
2347 | 2348 | int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); |
2348 | 2349 | |
2350 | + /* DW_OP_deref_size (and possibly other operations too) may | |
2351 | + create a pointer instead of an address. Ideally, the | |
2352 | + pointer to address conversion would be performed as part | |
2353 | + of those operations, but the type of the object to | |
2354 | + which the address refers is not known at the time of | |
2355 | + the operation. Therefore, we do the conversion here | |
2356 | + since the type is readily available. */ | |
2357 | + | |
2358 | + switch (TYPE_CODE (type)) | |
2359 | + { | |
2360 | + case TYPE_CODE_FUNC: | |
2361 | + case TYPE_CODE_METHOD: | |
2362 | + ptr_type = builtin_type (ctx->gdbarch)->builtin_func_ptr; | |
2363 | + break; | |
2364 | + default: | |
2365 | + ptr_type = builtin_type (ctx->gdbarch)->builtin_data_ptr; | |
2366 | + break; | |
2367 | + } | |
2368 | + address = value_as_address (value_from_pointer (ptr_type, address)); | |
2369 | + | |
2349 | 2370 | do_cleanups (value_chain); |
2350 | 2371 | retval = value_at_lazy (type, address + byte_offset); |
2351 | 2372 | if (in_stack_memory) |