This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] problem fetching inferior memory due to breakpoint


Hello,

This happens on Windows XP with the cygwin debugger. Consider the
following code:

        #include <stdio.h>
        
        void
        hello (void)
        {
          printf ("Hello world.\n");
        }
        
        int
        main (void)
        {
          hello ();
        
          return 0;
        }

Break at the first instruction of hello(), and then do a couple of
stepi's:

        (gdb) b *hello
        Breakpoint 1 at 0x401050: file foo.c, line 5.
        (gdb) run
        Starting program: /[...]/foo.exe 
        
        Breakpoint 1, hello () at foo.c:5
        5       {
        (gdb) stepi
        0x00401051      5       {
        (gdb) bt
        #0  0x00401051 in hello () at foo.c:5
        #1  0x00401093 in main () at foo.c:12
        (gdb) stepi
        0x00401053 in hello () at foo.c:5
        5       {

So we're at the third instruction of the function. Here is the backtrace
we get when I request it:

        (gdb) bt
        #0  0x00401053 in hello () at foo.c:5
        #1  0x0022ee88 in ?? ()
        #2  0x00401093 in main () at foo.c:12

We get an extra frame between hello() and main().

The reason for this is that the i386 code tries to scan the prologue
of hello during the step operation. So it tries reading the first few
bytes of the function, and hits a snag, because at the time when we do
the memory read, the breakpoint instruction is still inserted, and hence
we fail to recognize the prologue....

We actually scan the function prologue during the step operation as
opposed to during the "bt", because we need to determine where we are,
and that causes us to create the frame ID for frame 0, which means
scanning the function prologue (not actually verified, all from memory,
may be incorrect - but the fact is correct: we compute the frame ID
during the step).

I'm not exactly sure yet as to why we don't see this problem on x86-linux.
But all works fine there as far as I can tell.

I'm not entirely sure as to how to fix this problem. Since this problem
seems confined to win32, perhaps the fix should be in win32-nat.c, in
the xfer_memory routine, when I would then have to check for breakpoints.
Seems ok, except that I would then end up duplicating the logic of
deprecated_read_memory_nobpt.

I looked at the gdb-patches archives, and Andrew said at the time
that we should use get_frame_memory. The problem is that I don't see
how get_frame_memory() will help, since all it does is calling
read_memory(), which brings us back to our initial problem.

The simplest solution that seems to work is to modify read_memory to
use deprecated_read_memory_nobpt() instead of target_read_memory().
Seems a bit of a shame to check all breakpoints for each and every
memory read, though... But the overhead should be pretty negligible,
assuming that most sessions only have a few breakpoints, not millions of
them. Perhaps add a check for breakpoints inserted before doing the
breakpoints check.

Another solution would be have the win32 native code remove breakpoints
when handling all events, and then re-insert them as we resume execution.
Seems dangerous because we may miss some resume entry points.

We could apply this same later idea to the generic code instead of the
win32 code. Perhaps other targets are affected as well. But I suspect
that this would negatively impact certain targets that wouldn't need
this, especially remote targets with a slow communication link.

Any suggestions?

Thanks,
-- 
Joel


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]