* [PATCH] Handle bitfields inside inner structs for internalvars
@ 2013-02-06 20:39 Sergio Durigan Junior
2013-02-08 20:47 ` Jan Kratochvil
0 siblings, 1 reply; 6+ messages in thread
From: Sergio Durigan Junior @ 2013-02-06 20:39 UTC (permalink / raw)
To: GDB Patches; +Cc: Jan Kratochvil
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
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Handle bitfields inside inner structs for internalvars
2013-02-06 20:39 [PATCH] Handle bitfields inside inner structs for internalvars Sergio Durigan Junior
@ 2013-02-08 20:47 ` Jan Kratochvil
2013-02-09 4:52 ` Sergio Durigan Junior
0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2013-02-08 20:47 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: GDB Patches
On Wed, 06 Feb 2013 21:39:10 +0100, Sergio Durigan Junior wrote:
> 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.
OK for check-in with the bits below.
> --- 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\}" "" \
Backslashes are excessive here, parentheses are not special characters for the
TCL interpretation and this string is not regexp:
gdb_test "set \$myvar = (struct internalvartest) \{0\}" "" \
> + "set internal var"
> +
> + # Now, we set the proper bits.
[...]
> --- 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));
value_address rather tests for value_parent existence; although value_bitsize
is right as value_parent is currently not used elsewhere.
if (value_parent (toval))
{
/* VALUE_INTERNALVAR below corresponds to the parent value while
offset is relative to the parent value. */
gdb_assert (value_parent (value_parent (toval)) == NULL);
offset += value_offset (value_parent (toval));
}
And it was not so clear to me on the first look so I have added this comment
if you are OK with it.
> +
> + set_internalvar_component (VALUE_INTERNALVAR (toval),
> + offset,
> + value_bitpos (toval),
> + value_bitsize (toval),
> + fromval);
> + }
> break;
>
Thanks,
Jan
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Handle bitfields inside inner structs for internalvars
2013-02-08 20:47 ` Jan Kratochvil
@ 2013-02-09 4:52 ` Sergio Durigan Junior
2013-02-09 7:39 ` Jan Kratochvil
0 siblings, 1 reply; 6+ messages in thread
From: Sergio Durigan Junior @ 2013-02-09 4:52 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: GDB Patches
On Friday, February 08 2013, Jan Kratochvil wrote:
> On Wed, 06 Feb 2013 21:39:10 +0100, Sergio Durigan Junior wrote:
>> --- 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\}" "" \
>
> Backslashes are excessive here, parentheses are not special characters for the
> TCL interpretation and this string is not regexp:
> gdb_test "set \$myvar = (struct internalvartest) \{0\}" "" \
Thanks for the review. These extra backslashes were added by me while
testing a failure that I was seeing, sorry for letting those sneak in.
>> --- 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));
>
> value_address rather tests for value_parent existence; although value_bitsize
> is right as value_parent is currently not used elsewhere.
>
> if (value_parent (toval))
Do you think it's clearer to use `value_parent' here instead of
`value_bitsize'?
> {
> /* VALUE_INTERNALVAR below corresponds to the parent value while
> offset is relative to the parent value. */
> gdb_assert (value_parent (value_parent (toval)) == NULL);
> offset += value_offset (value_parent (toval));
> }
>
> And it was not so clear to me on the first look so I have added this comment
> if you are OK with it.
Thanks, the comment is fine by me. I'll wait for your reply to the
question above, and then proceed.
--
Sergio
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Handle bitfields inside inner structs for internalvars
2013-02-09 4:52 ` Sergio Durigan Junior
@ 2013-02-09 7:39 ` Jan Kratochvil
2013-02-11 18:06 ` Sergio Durigan Junior
0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2013-02-09 7:39 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: GDB Patches
On Sat, 09 Feb 2013 05:52:32 +0100, Sergio Durigan Junior wrote:
> On Friday, February 08 2013, Jan Kratochvil wrote:
> >> + if (value_bitsize (toval))
> >> + offset += value_offset (value_parent (toval));
> >
> > value_address rather tests for value_parent existence; although value_bitsize
> > is right as value_parent is currently not used elsewhere.
> >
> > if (value_parent (toval))
>
> Do you think it's clearer to use `value_parent' here instead of
> `value_bitsize'?
Choose any way but therefore put there a comment that value_parent is non-NULL
iff value_bitsize is non-zero.
Otherwise I was curious - what to do if value_parent exists but TOVAL is not
a bitfield? Isn't it a forgotten case? (It is not but...)
Thanks,
Jan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Handle bitfields inside inner structs for internalvars
2013-02-09 7:39 ` Jan Kratochvil
@ 2013-02-11 18:06 ` Sergio Durigan Junior
2013-02-11 18:11 ` Jan Kratochvil
0 siblings, 1 reply; 6+ messages in thread
From: Sergio Durigan Junior @ 2013-02-11 18:06 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: GDB Patches
On Saturday, February 09 2013, Jan Kratochvil wrote:
> On Sat, 09 Feb 2013 05:52:32 +0100, Sergio Durigan Junior wrote:
>> On Friday, February 08 2013, Jan Kratochvil wrote:
>> >> + if (value_bitsize (toval))
>> >> + offset += value_offset (value_parent (toval));
>> >
>> > value_address rather tests for value_parent existence; although value_bitsize
>> > is right as value_parent is currently not used elsewhere.
>> >
>> > if (value_parent (toval))
>>
>> Do you think it's clearer to use `value_parent' here instead of
>> `value_bitsize'?
>
> Choose any way but therefore put there a comment that value_parent is non-NULL
> iff value_bitsize is non-zero.
Ok, thanks, I committed the patch below.
> Otherwise I was curious - what to do if value_parent exists but TOVAL is not
> a bitfield? Isn't it a forgotten case? (It is not but...)
According to comments in gdb/value.{c,h}, value_parent is only used iff
the we are dealing with bitfields, so I guess this case is covered
(otherwise it is a bug). Was it a rhetorical question?
Checked-in:
http://sourceware.org/ml/gdb-cvs/2013-02/msg00071.html
Thanks,
--
Sergio
2013-02-11 Sergio Durigan Junior <sergiodj@redhat.com>
* valops.c (value_assign): Handling bitfield offset in
`lval_internalvar_component' case.
2013-02-11 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 | 26 +++++++++++++++++++++-----
3 files changed, 63 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..82f7b10 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..93c09d8 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1233,11 +1233,27 @@ 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);
+
+ /* Are we dealing with a bitfield?
+
+ It is important to mention that `value_parent (toval)' is
+ non-NULL iff `value_bitsize (toval)' is non-zero. */
+ if (value_bitsize (toval))
+ {
+ /* VALUE_INTERNALVAR below refers to the parent value, while
+ the offset is relative to this parent value. */
+ gdb_assert (value_parent (value_parent (toval)) == NULL);
+ 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
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Handle bitfields inside inner structs for internalvars
2013-02-11 18:06 ` Sergio Durigan Junior
@ 2013-02-11 18:11 ` Jan Kratochvil
0 siblings, 0 replies; 6+ messages in thread
From: Jan Kratochvil @ 2013-02-11 18:11 UTC (permalink / raw)
To: Sergio Durigan Junior; +Cc: GDB Patches
On Mon, 11 Feb 2013 19:05:58 +0100, Sergio Durigan Junior wrote:
> On Saturday, February 09 2013, Jan Kratochvil wrote:
> > Otherwise I was curious - what to do if value_parent exists but TOVAL is not
> > a bitfield? Isn't it a forgotten case? (It is not but...)
>
> According to comments in gdb/value.{c,h}, value_parent is only used iff
> the we are dealing with bitfields, so I guess this case is covered
> (otherwise it is a bug). Was it a rhetorical question?
I expected a future reader may have such a question.
I just believed the code was worth some comment, thanks for it. If it were
absolutely clear the bug would not happen there in the first place.
Thanks,
Jan
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2013-02-11 18:11 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-06 20:39 [PATCH] Handle bitfields inside inner structs for internalvars Sergio Durigan Junior
2013-02-08 20:47 ` Jan Kratochvil
2013-02-09 4:52 ` Sergio Durigan Junior
2013-02-09 7:39 ` Jan Kratochvil
2013-02-11 18:06 ` Sergio Durigan Junior
2013-02-11 18:11 ` Jan Kratochvil
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox