Bug 15299 - Verify breakpoint bytes when removing the breakpoint
Summary: Verify breakpoint bytes when removing the breakpoint
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: 7.5
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-03-24 08:15 UTC by SztfG
Modified: 2013-03-27 18:28 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
assembly (308 bytes, text/plain)
2013-03-24 08:15 UTC, SztfG
Details
GDB log (952 bytes, text/plain)
2013-03-24 09:15 UTC, SztfG
Details
Various recent GDBs (726 bytes, text/plain)
2013-03-24 09:25 UTC, Jan Kratochvil
Details
testing GDB (2.17 KB, text/plain)
2013-03-25 21:46 UTC, SztfG
Details

Note You need to log in before you can comment on or make changes to this bug.
Description SztfG 2013-03-24 08:15:50 UTC
Created attachment 6942 [details]
assembly

When debugging, it writes wrong bytes. See my assemby. It runs fine without gdb
Comment 1 Jan Kratochvil 2013-03-24 08:51:36 UTC
It works but you probably mean you have put "break *_start" breakpoint there, it crashes then.
Use "hbreak *_start" and it will work.
GDB could verify the breakpoint byte has not changed when removing the breakpoint.
Comment 2 SztfG 2013-03-24 09:15:32 UTC
Created attachment 6943 [details]
GDB log

It still crash with hbreak *_start
Comment 3 Jan Kratochvil 2013-03-24 09:25:24 UTC
Created attachment 6944 [details]
Various recent GDBs

I can't speak for gdb-7.2, that is really too old release.
Moreover it is SuSE variant which is heavily patched and such bugreport belongs more to the SuSE bugtracker.

With trunk FSF GDB I have found hbreak no longer can be placed.  It works with hbreak with Fedora GDB as it has it patched but that is irrelevant here.

With trunk FSF GDB it is most easier to just remove the breakpoint.

See the attached example runs.
Comment 4 SztfG 2013-03-24 09:56:24 UTC
Why hbreak feathure was removed in newest version? It will be returned?
Comment 5 Jan Kratochvil 2013-03-24 11:13:11 UTC
hbreak is dependent on target arch.  And target arch is known only after the target is running.  If you do "start" then "hbreak" works in FSF GDB.

Yes, sometimes it should be fixed in FSF GDB, you can submit an appropriate patch to gdb-patches, the Fedora one is:
http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-bz541866-rwatch-before-run.patch
Comment 6 SztfG 2013-03-24 13:45:22 UTC
There are very similar bug about software break point
http://sourceware.org/bugzilla/show_bug.cgi?id=14959

I found this:
http://www.sourceware.org/gdb/onlinedocs/gdbint.html#Algorithms
It says:
>Software breakpoints require gdb to do somewhat more work. The basic theory is that gdb will replace a program instruction with a trap, illegal divide, or some other instruction that will cause an exception, and then when it's encountered, gdb will take the exception and stop the program. When the user says to continue, gdb will restore the original instruction, single-step, re-insert the trap, and continue on.

>Since it literally overwrites the program being tested, the program area must be writable, so this technique won't work on programs in ROM. It can also distort the behavior of programs that examine themselves, although such a situation would be highly unusual. 

So, there are bug with restoring the original instruction
Comment 7 SztfG 2013-03-24 17:07:24 UTC
Hmm... Maybe I can write a GDB plugin that doing many "stepi" and checks each instruction working with RAM on the subject of whether it is trying to read or write from/to position of software breakpoints. And if it do so, plugin interrupts this "stepi-check_opcode" loop. It is possible? Where can I read about GDB plugin api? And another question. Why does my program in assembler does not overwrite the bytes of software breakpoint?
Comment 8 Jan Kratochvil 2013-03-25 12:22:28 UTC
(In reply to comment #7)
> Hmm... Maybe I can write a GDB plugin that doing many "stepi" and checks each
> instruction working with RAM on the subject of whether it is trying to read or
> write from/to position of software breakpoints. And if it do so, plugin
> interrupts this "stepi-check_opcode" loop.

I see it overcomplicated.  Just patch default_memory_remove_breakpoint in gdb/mem-break.c so that it:
 * Temporarily sets show_memory_breakpoints.
 * Uses target_read_memory to fetch the data from inferior.
 * Compares the read in bytes with what gdbarch_breakpoint_from_pc returns
   and if it does not match it prints some warning and prevents the current
   call of target_write_raw_memory with shadow_contents.
 * Restores show_memory_breakpoints (see make_show_memory_breakpoints_cleanup).

And it should be configurable as it will be a performance hit primarily with remote targets.

See also several *-tdep.c files using set_gdbarch_memory_remove_breakpoint as they have something more specific than default_memory_remove_breakpoint.


> Why does my program in assembler
> does not overwrite the bytes of software breakpoint?

 * GDB inserts breakpoint:
   * GDB saves original (old) instruction.
   * GDB writes there breakpoint
 * Your code overwrites the breakpoint by new instruction.
 * GDB removes breakpoint:
   * GDB writes there the original (old) instruction.
     - Your new instruction is lost.
Comment 9 SztfG 2013-03-25 21:46:36 UTC
Created attachment 6948 [details]
testing GDB

(In reply to comment #8)
> (In reply to comment #7)
> > Hmm... Maybe I can write a GDB plugin that doing many "stepi" and checks each
> > instruction working with RAM on the subject of whether it is trying to read or
> > write from/to position of software breakpoints. And if it do so, plugin
> > interrupts this "stepi-check_opcode" loop.
> 
> I see it overcomplicated.  Just patch default_memory_remove_breakpoint in
> gdb/mem-break.c so that it:
>  * Temporarily sets show_memory_breakpoints.
>  * Uses target_read_memory to fetch the data from inferior.
>  * Compares the read in bytes with what gdbarch_breakpoint_from_pc returns
>    and if it does not match it prints some warning and prevents the current
>    call of target_write_raw_memory with shadow_contents.
>  * Restores show_memory_breakpoints (see make_show_memory_breakpoints_cleanup).
> 
> And it should be configurable as it will be a performance hit primarily with
> remote targets.
> 
> See also several *-tdep.c files using set_gdbarch_memory_remove_breakpoint as
> they have something more specific than default_memory_remove_breakpoint.
> 
Yes, this is good idea if memory write check is enough, but how can it help if the program read from software breakpoint address (integrity check)?
What happens if instruction under breakpoint "wants" read or overwrite himself? I'll check it. I'm going to read the GDB Internals Manual and try to do something

> 
> > Why does my program in assembler
> > does not overwrite the bytes of software breakpoint?
> 
>  * GDB inserts breakpoint:
>    * GDB saves original (old) instruction.
>    * GDB writes there breakpoint
>  * Your code overwrites the breakpoint by new instruction.
>  * GDB removes breakpoint:
>    * GDB writes there the original (old) instruction.
>      - Your new instruction is lost.
It behaves differently. If GDB step into another breakpoint, then it rewrite breakpoints. See attached. Why?
Comment 10 Jan Kratochvil 2013-03-27 18:28:14 UTC
(In reply to comment #9)
> Yes, this is good idea if memory write check is enough, but how can it help if
> the program read from software breakpoint address (integrity check)?

It is never perfect but it should at least improve the situation.


> It behaves differently. If GDB step into another breakpoint, then it rewrite
> breakpoints. See attached. Why?

I do not see exactly what do you want to know.

For example if you have a breakpoint at address X and GDB is currently stopped at that address X during "continue" the breakpoint at address X is removed, single-stepped, breakpoint is put back to address X and only then the inferior is continued.  You can see it if you use "set debug infrun 1".