This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] Handle bitfields inside inner structs for internalvars
- From: Sergio Durigan Junior <sergiodj at redhat dot com>
- To: GDB Patches <gdb-patches at sourceware dot org>
- Cc: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- Date: Wed, 06 Feb 2013 18:39:10 -0200
- Subject: [PATCH] Handle bitfields inside inner structs for internalvars
Hi,
<https://bugzilla.redhat.com/show_bug.cgi?id=903734>
(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 <sergiodj@redhat.com>
* valops.c (value_assign): Handling bitfield offset in
`lval_internalvar_component' case.
gdb/testsuite/
2013-02-06 Sergio Durigan Junior <sergiodj@redhat.com>
* 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