This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] dwarf2loc.c: Perform a pointer to address conversion for DWARF_VALUE_MEMORY.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f56331b468908d1502c7ae26adab6f9b858cb13f

commit f56331b468908d1502c7ae26adab6f9b858cb13f
Author: Kevin Buettner <kevinb@redhat.com>
Date:   Tue Nov 24 21:53:13 2015 -0700

    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:
    
        print int_vla
        $1 = {-1, -1, -1, -1, -1}
    
    The result should actually be this:
    
        $1 = {0, 2, 4, 6, 8}
    
    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)
        <15b>   DW_AT_name        : (indirect string, offset: 0xbf): int_vla
        <15f>   DW_AT_decl_file   : 1
        <160>   DW_AT_decl_line   : 35
        <161>   DW_AT_type        : <0x393>
        <165>   DW_AT_location    : 4 byte block: 86 7a 94 2  (DW_OP_breg22 (r22): -6; DW_OP_deref_size: 2)
    
    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.

Diff:
---
 gdb/ChangeLog   |  5 +++++
 gdb/dwarf2loc.c | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index bafae52..6aa90d9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-09  Kevin Buettner  <kevinb@redhat.com>
+
+	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Perform a pointer
+	to address conversion for DWARF_VALUE_MEMORY.
+
 2015-12-09  Luis Machado  <lgustavo@codesourcery.com>
 
 	* gdb/mi/mi-cmd-var.c (mi_parse_format): Handle new "zero-hexadecimal"
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index a8f5c91..b8e7fa0 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2343,9 +2343,30 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
 	case DWARF_VALUE_MEMORY:
 	  {
+	    struct type *ptr_type;
 	    CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0);
 	    int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
 
+	    /* DW_OP_deref_size (and possibly other operations too) may
+	       create a pointer instead of an address.  Ideally, the
+	       pointer to address conversion would be performed as part
+	       of those operations, but the type of the object to
+	       which the address refers is not known at the time of
+	       the operation.  Therefore, we do the conversion here
+	       since the type is readily available.  */
+
+	    switch (TYPE_CODE (type))
+	      {
+		case TYPE_CODE_FUNC:
+		case TYPE_CODE_METHOD:
+		  ptr_type = builtin_type (ctx->gdbarch)->builtin_func_ptr;
+		  break;
+		default:
+		  ptr_type = builtin_type (ctx->gdbarch)->builtin_data_ptr;
+		  break;
+	      }
+	    address = value_as_address (value_from_pointer (ptr_type, address));
+
 	    do_cleanups (value_chain);
 	    retval = value_at_lazy (type, address + byte_offset);
 	    if (in_stack_memory)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]