From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31095 invoked by alias); 6 Feb 2013 20:39:21 -0000 Received: (qmail 31046 invoked by uid 22791); 6 Feb 2013 20:39:19 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_SPAMHAUS_DROP,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,RP_MATCHES_RCVD,SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 06 Feb 2013 20:39:13 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r16KdDqP005546 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 6 Feb 2013 15:39:13 -0500 Received: from psique (ovpn-113-130.phx2.redhat.com [10.3.113.130]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r16KdABO002636; Wed, 6 Feb 2013 15:39:11 -0500 From: Sergio Durigan Junior To: GDB Patches Cc: Jan Kratochvil Subject: [PATCH] Handle bitfields inside inner structs for internalvars User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) X-URL: http://www.redhat.com Date: Wed, 06 Feb 2013 20:39:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2013-02/txt/msg00164.txt.bz2 Hi, (The bug is marked as private, I believe you won't be able to see it.) This is a very specific bug. It occurs when one tries to set the value of an internal variable's bitfield which is declared inside an inner structure, i.e., a structure declared inside another. For example: struct foo { int a; struct { unsigned int b : 1; } inner; }; Now, consider that we create an internal variable out of this structure: (gdb) set $p = (struct foo) {0} (gdb) print $p $1 = {a = 0, inner = {b = 0}} Now, if we try to set the bitfield `b': (gdb) set $p.inner.b = 1 (gdb) p $p $2 = {a = 1, inner = {b = 0}} This happens because of some miscalculations of offsets inside gdb/valops.c:value_assign: GDB forgets to add the offset of the `inner' struct to the offset of the bitfield, thus setting the wrong field. The patch below fixes it, and includes some new tests for this specific scenario. I ran a regression test on my Fedora 16 box (x86, x86_64 with and without -m32, gdbserver for both), and found no regressions. OK to apply? -- Sergio gdb/ 2013-02-06 Sergio Durigan Junior * valops.c (value_assign): Handling bitfield offset in `lval_internalvar_component' case. gdb/testsuite/ 2013-02-06 Sergio Durigan Junior * gdb.base/bitfields.c (struct internalvartest): New declaration. * gdb.base/bitfields.exp (bitfield_internalvar): New function. --- gdb/testsuite/gdb.base/bitfields.c | 16 ++++++++++++++++ gdb/testsuite/gdb.base/bitfields.exp | 26 ++++++++++++++++++++++++++ gdb/valops.c | 17 ++++++++++++----- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/gdb/testsuite/gdb.base/bitfields.c b/gdb/testsuite/gdb.base/bitfields.c index ed1634c..3a6b76f 100644 --- a/gdb/testsuite/gdb.base/bitfields.c +++ b/gdb/testsuite/gdb.base/bitfields.c @@ -23,6 +23,22 @@ struct fields signed char sc ; } flags; +struct internalvartest +{ + unsigned int a : 1; + struct + { + unsigned int b : 1; + struct + { + unsigned int c : 1; + signed int d : 1; + } deep; + signed int e : 1; + } inner; + signed int f : 1; +} dummy_internalvartest; + void break1 () { } diff --git a/gdb/testsuite/gdb.base/bitfields.exp b/gdb/testsuite/gdb.base/bitfields.exp index 9095736..c2e1c63 100644 --- a/gdb/testsuite/gdb.base/bitfields.exp +++ b/gdb/testsuite/gdb.base/bitfields.exp @@ -245,6 +245,31 @@ proc bitfield_at_offset {} { gdb_test "print container.two.u3" ".* = 3" } +proc bitfield_internalvar {} { + global gdb_prompt + + # First, we create an internal var holding an instance of + # the struct (zeroed out). + gdb_test "set \$myvar = \(struct internalvartest\) \{0\}" "" \ + "set internal var" + + # Now, we set the proper bits. + gdb_test_no_output "set \$myvar.a = 0" + gdb_test_no_output "set \$myvar.inner.b = 1" + gdb_test_no_output "set \$myvar.inner.deep.c = 0" + gdb_test_no_output "set \$myvar.inner.deep.d = -1" + gdb_test_no_output "set \$myvar.inner.e = 1" + gdb_test_no_output "set \$myvar.f = 1" + + # Here comes the true testing. + gdb_test "print \$myvar.a" "\\$\[0-9\]\+ = 0" + gdb_test "print \$myvar.inner.b" "\\$\[0-9\]\+ = 1" + gdb_test "print \$myvar.inner.deep.c" "\\$\[0-9\]\+ = 0" + gdb_test "print \$myvar.inner.deep.d" "\\$\[0-9\]\+ = -1" + gdb_test "print \$myvar.inner.e" "\\$\[0-9\]\+ = -1" + gdb_test "print \$myvar.f" "\\$\[0-9\]\+ = -1" +} + gdb_start gdb_reinitialize_dir $srcdir/$subdir gdb_load ${binfile} @@ -256,3 +281,4 @@ bitfield_containment bitfield_unsignedness bitfield_signedness bitfield_at_offset +bitfield_internalvar diff --git a/gdb/valops.c b/gdb/valops.c index 2132f3e..625e8d6 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1233,11 +1233,18 @@ value_assign (struct value *toval, struct value *fromval) VALUE_INTERNALVAR (toval)); case lval_internalvar_component: - set_internalvar_component (VALUE_INTERNALVAR (toval), - value_offset (toval), - value_bitpos (toval), - value_bitsize (toval), - fromval); + { + int offset = value_offset (toval); + + if (value_bitsize (toval)) + offset += value_offset (value_parent (toval)); + + set_internalvar_component (VALUE_INTERNALVAR (toval), + offset, + value_bitpos (toval), + value_bitsize (toval), + fromval); + } break; case lval_memory: -- 1.7.7.6