From patchwork Mon Feb 13 19:00:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Arnez X-Patchwork-Id: 19243 Received: (qmail 5328 invoked by alias); 13 Feb 2017 19:00:52 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 5310 invoked by uid 89); 13 Feb 2017 19:00:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.3 required=5.0 tests=AWL, BAYES_05, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=cu, 776, 508, DW_TAG_variable X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 13 Feb 2017 19:00:41 +0000 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v1DIwXRQ003088 for ; Mon, 13 Feb 2017 14:00:39 -0500 Received: from e06smtp12.uk.ibm.com (e06smtp12.uk.ibm.com [195.75.94.108]) by mx0a-001b2d01.pphosted.com with ESMTP id 28kjhy81uj-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 13 Feb 2017 14:00:39 -0500 Received: from localhost by e06smtp12.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 13 Feb 2017 19:00:37 -0000 Received: from d06dlp02.portsmouth.uk.ibm.com (9.149.20.14) by e06smtp12.uk.ibm.com (192.168.101.142) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 13 Feb 2017 19:00:33 -0000 Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by d06dlp02.portsmouth.uk.ibm.com (Postfix) with ESMTP id 60DEA2190019; Mon, 13 Feb 2017 18:59:36 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v1DJ0XE165667236; Mon, 13 Feb 2017 19:00:33 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 10D18A405D; Mon, 13 Feb 2017 19:00:30 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D8379A4055; Mon, 13 Feb 2017 19:00:29 +0000 (GMT) Received: from oc1027705133.ibm.com (unknown [9.152.212.222]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTPS; Mon, 13 Feb 2017 19:00:29 +0000 (GMT) From: Andreas Arnez To: gdb-patches@sourceware.org Cc: Jan Kratochvil Subject: [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value Date: Mon, 13 Feb 2017 20:00:30 +0100 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1 (gnu/linux) MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17021319-0008-0000-0000-000003E79290 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17021319-0009-0000-0000-00001C716AF0 Message-Id: X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-02-13_10:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=3 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1702130182 X-IsSubscribed: yes Recently I fixed a bug that caused a DW_OP_implicit_pointer with non-zero offset into a DW_OP_implicit_value to be handled incorrectly on big-endian targets. GDB ignored the offset and copied the wrong bytes: https://sourceware.org/ml/gdb-patches/2017-01/msg00251.html But there is still a similar issue when a DW_OP_implicit_pointer points into a DW_OP_stack_value instead; and again, the offset is ignored. There is an important difference, though: While implicit values are treated like blocks of data and anchored at the lowest-addressed byte, stack values traditionally contain integer numbers and are anchored at the *least significant* byte. Also, stack values do not come in varying sizes, but are cut down appropriately when used. Thus, on big-endian targets the scenario looks like this (higher addresses shown right): |<- - - - - Stack value - - - - - - ->| | | |<- original object ->| | | offset ->|####| ^^^^ de-referenced implicit pointer (Note how the original object's size influences the position of the de-referenced implicit pointer within the stack value. This is not the case for little-endian targets, where the original object starts at offset zero within the stack value.) This patch implements the logic indicated in the above diagram and adds an appropriate test case. A new function dwarf2_fetch_die_type_sect_off is added; it is used for retrieving the original object's type, so its size can be determined. That type is passed to dwarf2_evaluate_loc_desc_full via a new parameter. gdb/ChangeLog: * dwarf2loc.c (indirect_synthetic_pointer): Get data type of pointed-to DIE and pass it to dwarf2_evaluate_loc_desc_full. (dwarf2_evaluate_loc_desc_full): Add parameter 'orig_type'. Fix the handling of DWARF_VALUE_STACK on big-endian targets when coming via an implicit pointer. (dwarf2_evaluate_loc_desc): Adjust call to dwarf2_evaluate_loc_desc_full. * dwarf2loc.h (dwarf2_fetch_die_type_sect_off): New declaration. * dwarf2read.c (dwarf2_fetch_die_type_sect_off): New function. gdb/testsuite/ChangeLog: Andreas Arnez * gdb.dwarf2/nonvar-access.exp: Add test for stack value location and implicit pointer into such a location. --- gdb/dwarf2loc.c | 39 +++++++++++++++--------------- gdb/dwarf2loc.h | 3 +++ gdb/dwarf2read.c | 25 +++++++++++++++++++ gdb/testsuite/gdb.dwarf2/nonvar-access.exp | 26 +++++++++++++++++++- 4 files changed, 72 insertions(+), 21 deletions(-) diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index c1e02eb..65479d8 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -50,7 +50,8 @@ static struct value *dwarf2_evaluate_loc_desc_full (struct type *type, const gdb_byte *data, size_t size, struct dwarf2_per_cu_data *per_cu, - LONGEST byte_offset); + LONGEST byte_offset, + struct type *orig_type); static struct call_site_parameter *dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, @@ -2098,13 +2099,16 @@ indirect_synthetic_pointer (sect_offset die, LONGEST byte_offset, = dwarf2_fetch_die_loc_sect_off (die, per_cu, get_frame_address_in_block_wrapper, frame); + /* Get type of pointed-to DIE. */ + struct type *orig_type = dwarf2_fetch_die_type_sect_off (die, per_cu); + /* If pointed-to DIE has a DW_AT_location, evaluate it and return the resulting value. Otherwise, it may have a DW_AT_const_value instead, or it may've been optimized out. */ if (baton.data != NULL) return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame, baton.data, baton.size, baton.per_cu, - byte_offset); + byte_offset, orig_type); else return fetch_const_value_from_synthetic_pointer (die, byte_offset, per_cu, type); @@ -2269,7 +2273,7 @@ static struct value * dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, const gdb_byte *data, size_t size, struct dwarf2_per_cu_data *per_cu, - LONGEST byte_offset) + LONGEST byte_offset, struct type *orig_type) { struct value *retval; struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); @@ -2404,18 +2408,15 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, case DWARF_VALUE_STACK: { struct value *value = ctx.fetch (0); - gdb_byte *contents; - const gdb_byte *val_bytes; size_t n = TYPE_LENGTH (value_type (value)); + size_t len = TYPE_LENGTH (type); + size_t max = orig_type ? TYPE_LENGTH (orig_type) : len; + struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile); struct cleanup *cleanup; - if (byte_offset + TYPE_LENGTH (type) > n) + if (byte_offset + len > max) invalid_synthetic_pointer (); - val_bytes = value_contents_all (value); - val_bytes += byte_offset; - n -= byte_offset; - /* Preserve VALUE because we are going to free values back to the mark, but we still need the value contents below. */ @@ -2424,16 +2425,13 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, cleanup = make_cleanup_value_free (value); retval = allocate_value (type); - contents = value_contents_raw (retval); - if (n > TYPE_LENGTH (type)) - { - struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile); - if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG) - val_bytes += n - TYPE_LENGTH (type); - n = TYPE_LENGTH (type); - } - memcpy (contents, val_bytes, n); + /* The given offset is relative to the actual object. */ + if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG) + byte_offset += n - max; + + memcpy (value_contents_raw (retval), + value_contents_all (value) + byte_offset, len); do_cleanups (cleanup); } @@ -2482,7 +2480,8 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, const gdb_byte *data, size_t size, struct dwarf2_per_cu_data *per_cu) { - return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0); + return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, + 0, NULL); } /* Evaluates a dwarf expression and stores the result in VAL, expecting diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index d6cdbd2..d669d1e 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -77,6 +77,9 @@ extern const gdb_byte *dwarf2_fetch_constant_bytes (sect_offset, struct obstack *, LONGEST *); +struct type *dwarf2_fetch_die_type_sect_off (sect_offset, + struct dwarf2_per_cu_data *); + struct type *dwarf2_get_die_type (cu_offset die_offset, struct dwarf2_per_cu_data *per_cu); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 774ed73..bdaac19 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -20258,6 +20258,31 @@ dwarf2_fetch_constant_bytes (sect_offset offset, return result; } +/* Return the type of the die at OFFSET in PER_CU. Return NULL if no + valid type for this die is found. */ + +struct type * +dwarf2_fetch_die_type_sect_off (sect_offset offset, + struct dwarf2_per_cu_data *per_cu) +{ + struct dwarf2_cu *cu; + struct die_info *die; + + dw2_setup (per_cu->objfile); + + if (per_cu->cu == NULL) + load_cu (per_cu); + cu = per_cu->cu; + if (!cu) + return NULL; + + die = follow_die_offset (offset, per_cu->is_dwz, &cu); + if (!die) + return NULL; + + return die_type (die, cu); +} + /* Return the type of the DIE at DIE_OFFSET in the CU named by PER_CU. */ diff --git a/gdb/testsuite/gdb.dwarf2/nonvar-access.exp b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp index 3cb5c49..633c6b3 100644 --- a/gdb/testsuite/gdb.dwarf2/nonvar-access.exp +++ b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp @@ -33,7 +33,7 @@ Dwarf::assemble $asm_file { } { declare_labels int_type_label char_type_label \ struct_s_label struct_t_label array_a9_label \ - char_ptr_label implicit_a_label + char_ptr_label implicit_a_label stack_b_label int_type_label: base_type { {name "int"} @@ -162,6 +162,23 @@ Dwarf::assemble $asm_file { GNU_implicit_pointer $implicit_a_label 5 } SPECIAL_expr} } + # Stack-value location. + stack_b_label: DW_TAG_variable { + {name def_stack_b} + {type :$struct_t_label} + {location { + const4u 0x1a2b3c4d + stack_value + } SPECIAL_expr} + } + # Implicit pointer into stack value. + DW_TAG_variable { + {name implicit_b_ptr} + {type :$char_ptr_label} + {location { + GNU_implicit_pointer $stack_b_label 1 + } SPECIAL_expr} + } } } } @@ -194,6 +211,13 @@ gdb_test "print/x def_implicit_a" \ gdb_test "print/x def_implicit_a\[5\]" " = 0x56" gdb_test "print/x *(char (*)\[5\]) implicit_a_ptr" \ " = \\{0x56, 0x67, 0x78, 0x89, 0x9a\\}" +switch $endian { + big {set val "a = 52, b = 2833485"} + little {set val "a = 77, b = 857502"} +} +gdb_test "print def_stack_b" " = \\{$val\\}" +switch $endian {big {set val 0x2b} little {set val 0x3c}} +gdb_test "print/x *implicit_b_ptr" " = $val" # Byte-aligned fields, pieced together from DWARF stack values. gdb_test "print def_s" " = \\{a = 0, b = -1\\}"