From patchwork Tue May 9 17:46:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Arnez X-Patchwork-Id: 20349 Received: (qmail 120957 invoked by alias); 9 May 2017 17:55:55 -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 120945 invoked by uid 89); 9 May 2017 17:55:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy= 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; Tue, 09 May 2017 17:55:53 +0000 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v49Hrp4A013352 for ; Tue, 9 May 2017 13:55:55 -0400 Received: from e06smtp12.uk.ibm.com (e06smtp12.uk.ibm.com [195.75.94.108]) by mx0a-001b2d01.pphosted.com with ESMTP id 2abhb9jywt-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 09 May 2017 13:55:55 -0400 Received: from localhost by e06smtp12.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 9 May 2017 18:55:52 +0100 Received: from b06cxnps3075.portsmouth.uk.ibm.com (9.149.109.195) by e06smtp12.uk.ibm.com (192.168.101.142) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 9 May 2017 18:55:51 +0100 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v49HtouR20382176 for ; Tue, 9 May 2017 17:55:50 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 12EE152043 for ; Tue, 9 May 2017 17:53:14 +0100 (BST) Received: from oc1027705133.ibm.com (unknown [9.152.212.109]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTP id ED7B35203F for ; Tue, 9 May 2017 17:53:13 +0100 (BST) From: Andreas Arnez To: gdb-patches@sourceware.org Subject: [PATCH v2 13/19] Fix handling of DWARF register pieces on big-endian targets Date: Tue, 9 May 2017 19:46:09 +0200 In-Reply-To: <1494352015-10465-1-git-send-email-arnez@linux.vnet.ibm.com> References: <1494352015-10465-1-git-send-email-arnez@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17050917-0008-0000-0000-0000044189A3 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17050917-0009-0000-0000-00001D99A96B Message-Id: <1494352015-10465-14-git-send-email-arnez@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-05-09_14:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1703280000 definitions=main-1705090098 X-IsSubscribed: yes For big-endian targets the logic in read/write_pieced_value tries to take a register piece from the LSB end. This requires offsets and sizes to be adjusted accordingly, and that's where the current implementation has some issues: * The formulas for recalculating the bit- and byte-offsets into the register are wrong. They just happen to yield correct results if everything is byte-aligned and the piece's last byte belongs to the given value. * After recalculating the bit offset into the register, the number of bytes to be copied from the register is not recalculated. Of course this does not matter if everything (particularly the piece size) is byte-aligned. These issues are fixed. The size calculation is performed with a new helper function bits_to_bytes(). gdb/ChangeLog: * dwarf2loc.c (bits_to_bytes): New function. (read_pieced_value): Fix offset calculations for register pieces on big-endian targets. (write_pieced_value): Likewise. gdb/testsuite/ChangeLog: * gdb.dwarf2/var-access.exp: Add test for non-byte-aligned register pieces. --- gdb/dwarf2loc.c | 56 ++++++++++++++++++++------------- gdb/testsuite/gdb.dwarf2/var-access.exp | 25 +++++++++++++++ 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 5c29cf6..62462f0 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -1752,6 +1752,15 @@ copy_bitwise_tests (void) #endif /* GDB_SELF_TEST */ +/* Return the number of bytes overlapping a contiguous chunk of N_BITS + bits whose first bit is located at bit offset START. */ + +static size_t +bits_to_bytes (ULONGEST start, ULONGEST n_bits) +{ + return (start % 8 + n_bits + 7) / 8; +} + static void read_pieced_value (struct value *v) { @@ -1804,7 +1813,7 @@ read_pieced_value (struct value *v) if (this_size_bits > max_offset - offset) this_size_bits = max_offset - offset; - this_size = (this_size_bits + source_offset_bits % 8 + 7) / 8; + this_size = bits_to_bytes (source_offset_bits, this_size_bits); buffer.reserve (this_size); source_offset = source_offset_bits / 8; intermediate_buffer = buffer.data (); @@ -1817,20 +1826,20 @@ read_pieced_value (struct value *v) struct frame_info *frame = frame_find_by_id (c->frame_id); struct gdbarch *arch = get_frame_arch (frame); int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno); + ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum); int optim, unavail; - LONGEST reg_offset = source_offset; if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG - && this_size < register_size (arch, gdb_regnum)) + && p->size < reg_bits) { /* Big-endian, and we want less than full size. */ - reg_offset = register_size (arch, gdb_regnum) - this_size; - /* We want the lower-order THIS_SIZE_BITS of the bytes - we extract from the register. */ - source_offset_bits += 8 * this_size - this_size_bits; + source_offset_bits += reg_bits - p->size; } + this_size = bits_to_bytes (source_offset_bits, this_size_bits); + buffer.reserve (this_size); - if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, + if (!get_frame_register_bytes (frame, gdb_regnum, + source_offset_bits / 8, this_size, buffer.data (), &optim, &unavail)) { @@ -1844,7 +1853,7 @@ read_pieced_value (struct value *v) } copy_bitwise (contents, dest_offset_bits, - intermediate_buffer, source_offset_bits % 8, + buffer.data (), source_offset_bits % 8, this_size_bits, bits_big_endian); } break; @@ -1969,7 +1978,7 @@ write_pieced_value (struct value *to, struct value *from) if (this_size_bits > max_offset - offset) this_size_bits = max_offset - offset; - this_size = (this_size_bits + dest_offset_bits % 8 + 7) / 8; + this_size = bits_to_bytes (dest_offset_bits, this_size_bits); source_offset = source_offset_bits / 8; dest_offset = dest_offset_bits / 8; if (dest_offset_bits % 8 == 0 && source_offset_bits % 8 == 0 @@ -1992,20 +2001,25 @@ write_pieced_value (struct value *to, struct value *from) struct frame_info *frame = frame_find_by_id (c->frame_id); struct gdbarch *arch = get_frame_arch (frame); int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno); - int reg_offset = dest_offset; + ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum); if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG - && this_size <= register_size (arch, gdb_regnum)) + && p->size <= reg_bits) { /* Big-endian, and we want less than full size. */ - reg_offset = register_size (arch, gdb_regnum) - this_size; + dest_offset_bits += reg_bits - p->size; } + this_size = bits_to_bytes (dest_offset_bits, this_size_bits); + buffer.reserve (this_size); - if (need_bitwise) + if (dest_offset_bits % 8 != 0 || this_size_bits % 8 != 0) { + /* Data is copied non-byte-aligned into the register. + Need some bits from original register value. */ int optim, unavail; - if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, + if (!get_frame_register_bytes (frame, gdb_regnum, + dest_offset_bits / 8, this_size, buffer.data (), &optim, &unavail)) { @@ -2020,14 +2034,14 @@ write_pieced_value (struct value *to, struct value *from) "bitfield; containing word " "is unavailable")); } - copy_bitwise (buffer.data (), dest_offset_bits, - contents, source_offset_bits, - this_size_bits, - bits_big_endian); } - put_frame_register_bytes (frame, gdb_regnum, reg_offset, - this_size, source_buffer); + copy_bitwise (buffer.data (), dest_offset_bits % 8, + contents, source_offset_bits, + this_size_bits, bits_big_endian); + put_frame_register_bytes (frame, gdb_regnum, + dest_offset_bits / 8, + this_size, buffer.data ()); } break; case DWARF_VALUE_MEMORY: diff --git a/gdb/testsuite/gdb.dwarf2/var-access.exp b/gdb/testsuite/gdb.dwarf2/var-access.exp index 3ba2c08..c533b8d 100644 --- a/gdb/testsuite/gdb.dwarf2/var-access.exp +++ b/gdb/testsuite/gdb.dwarf2/var-access.exp @@ -215,6 +215,19 @@ Dwarf::assemble $asm_file { piece 1 } SPECIAL_expr} } + # Register pieces for bitfield access: 4 bytes optimized + # out, 3 bytes from r0, and 1 byte from r1. + DW_TAG_variable { + {name "t2"} + {type :$struct_t_label} + {location { + piece 4 + regx [lindex $dwarf_regnum 0] + piece 3 + regx [lindex $dwarf_regnum 1] + piece 1 + } SPECIAL_expr} + } } } } @@ -279,3 +292,15 @@ switch $endian { # val gdb_test "print/x a" " = \\{0x0, ${val}, 0x0, 0x0\\}" \ "verify st1 through a" + +switch $endian { big {set val 0x7ffc} little {set val 0x3ffe00} } +gdb_test_no_output "set var \$[lindex $regname 0] = $val" \ + "init t2, first piece" +gdb_test_no_output "set var \$[lindex $regname 1] = 0" \ + "init t2, second piece" +gdb_test "print/d t2" " = \\{u = , x = 0, y = -1, z = 0\\}" \ + "initialized t2 from regs" +gdb_test_no_output "set var t2.y = 2641" +gdb_test_no_output "set var t2.z = -400" +gdb_test_no_output "set var t2.x = 200" +gdb_test "print t2.x + t2.y + t2.z" " = 2441"