This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [RFC] MI notification on register changes
On Wed, Nov 07, 2012 at 11:54:09AM -0700, Tom Tromey wrote:
> >>>>> "Marc" == Marc Khouzam <marc.khouzam@ericsson.com> writes:
>
> Marc> Since GDB allows the frontend to try to avoid a full
> Marc> refresh by giving extra information in its notifications,
> Marc> the idea of continuing with that approach seemed the right one.
> Marc> For instance, GDB could have a single =breakpoints-changed
> Marc> notif which would trigger a full refresh a breakpoints.
> Marc> Same for variable objects (see -var-update). Even
> Marc> =threads-changed (although this may be a little more
> Marc> justified if we think about it more deeply).
>
> In some cases, like breakpoints, gdb has perfect information.
> In these situations, sending small changes is easy and efficient.
>
> For memory or registers, I think the PR established pretty clearly that
> gdb doesn't have perfect information, or at the very least, that trying
> to compute it perfectly would be a lot of work, and so it is preferable
> to avoid doing so if possible.
Computing perfect updates is not possible.
GDB would need to keep track of all memory locations and registers used
to create the representation of the value, and even that would not be
perfect in the presence of "external" sources of information like the
result of system calls or similar.
> For varobjs, gdb caches the previously sent data so that it can send
> deltas.
And this is not sufficient for proper display. Consider:
In .gdbinit (or similar):
python
class Printer(object):
def __init__(self, val):
self.val = val
def to_string(self):
return ["foo", "bar"][int(gdb.parse_and_eval("d"))]
def display_hint(self):
return 'string'
def P(val):
if str(val.type) == "struct S":
return Printer(val)
return None
gdb.pretty_printers = [ P ]
end
In main.c:
int d;
struct S { } s;
int main()
{
d = 1;
d = 0;
d = 1;
d = 0;
d = 1;
d = 0;
d = 1;
d = 0;
d = 1;
d = 0;
d = 1;
}
With "full refetch" you get alternating values for s when stepping:
(gdb) display d
1: d = 0
(gdb) display s
2: s = "foo"
(gdb) n
41 d = 0;
2: s = "bar"
1: d = 1
(gdb)
42 d = 1;
2: s = "foo"
1: d = 0
(gdb)
43 d = 0;
2: s = "bar"
1: d = 1
(gdb)
44 d = 1;
2: s = "foo"
1: d = 0
(gdb)
45 d = 0;
2: s = "bar"
1: d = 1
(gdb)
Using MI varobj's you can get something like that:
(gdb) -var-create d * d
^done,name="d",numchild="0",value="0",type="int",has_more="0"
(gdb) -var-create s * s
^done,name="s",numchild="0",value="{...}",type="struct S",has_more="0"
(gdb) n
^running
*running,thread-id="all"
(gdb)
~"39\t d = 0;\n"
*stopped,frame={addr="0x080483e9",...,line="39"},....
(gdb) -var-update *
^done,changelist=[{name="d",in_scope="true",type_changed="false",has_more="0"}]
(gdb) n
^running
*running,thread-id="all"
(gdb)
~"40\t d = 1;\n"
*stopped,frame={addr="0x080483e9",...,line="40"},....
(gdb) -var-update *
^done,changelist=[{name="d",in_scope="true",type_changed="false",has_more="0"}]
Only the changes to d are announced. For the frontend there is no
indication whatsoever that the display of s would need to be updated.
The only way to get the proper alternating display is to fully refetch
everything again:
(gdb) p s
&"p s\n"
~"$1 = \"foo\"\n"
^done
(gdb) p d
&"p d\n"
~"$2 = 0"
~"\n"
^done
(gdb) n
&"n\n"
^running
*running,thread-id="all"
(gdb)
~"41\t d = 0;\n"
*stopped,frame={addr="0x080483fd",...,line="41"},....
(gdb)
p s
&"p s\n"
~"$3 = \"bar\"\n"
^done
(gdb)
Andre'