This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
[RFC] stepping over permanent breakpoint
- From: Aleksandar Ristovski <aristovski at qnx dot com>
- To: gdb at sources dot redhat dot com
- Date: Mon, 16 Mar 2009 13:40:49 -0400
- Subject: [RFC] stepping over permanent breakpoint
Hello,
When there is a hard-coded breakpoint in code, like in this
example (for x86):
#include <stdio.h>
int main()
{
__asm(" int $0x03\n");
printf("Hello World\n");
return 0;
}
gdb on linux will appear to work correctly.
However, on systems that do not need pc adjustment after
break (like QNX) gdb will not be able to step over that
breakpoint unless user explicitly sets a breakpoint on top
of it.
I think that in case of linux it is actually working by
accident - because kernel does not back-up instruction
pointer after hard-coded breakpoint instruction was
executed. Gdb will receive SIGTRAP but will not really know why.
Attached patch fixes this for systems where
gdbarch_decr_pc_after_break (gdbarch) == 0
I am still not sure this is the final fix. Wouldn't it be
better if we recognized a hard-coded breakpoint as a
breakpoint? There would be an issue since it is not in the
breakpoint list, but maybe we should either automatically
add it when we encounter it, or perhaps print with some
"special" number (to make it clear to the user it is not one
of the user-generated breakpoints).
Thanks,
Aleksandar Ristovski
QNX Software Systems
ChangeLog for your reference:
* infrun.c (adjust_pc_after_break): On systems with adjusted
PC after break, make sure hard-coded breakpoint is stepped-over.
Index: gdb/infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.361
diff -u -p -r1.361 infrun.c
--- gdb/infrun.c 1 Mar 2009 23:18:36 -0000 1.361
+++ gdb/infrun.c 16 Mar 2009 17:33:22 -0000
@@ -2089,14 +2089,29 @@ adjust_pc_after_break (struct execution_
we have nothing to do. */
regcache = get_thread_regcache (ecs->ptid);
gdbarch = get_regcache_arch (regcache);
- if (gdbarch_decr_pc_after_break (gdbarch) == 0)
- return;
/* Find the location where (if we've hit a breakpoint) the
breakpoint would be. */
breakpoint_pc = regcache_read_pc (regcache)
- gdbarch_decr_pc_after_break (gdbarch);
+ if (gdbarch_decr_pc_after_break (gdbarch) == 0)
+ {
+ /* Check if we have stopped at a permanent breakpoint. */
+ int len;
+ const gdb_byte *brk;
+ gdb_byte *target_mem = alloca(32);
+
+ brk = gdbarch_breakpoint_from_pc (gdbarch, &breakpoint_pc, &len);
+ if (!target_read_memory (breakpoint_pc, target_mem, len)
+ && memcmp (target_mem, brk, len) == 0)
+ {
+ breakpoint_pc += len;
+ regcache_write_pc (regcache, breakpoint_pc);
+ }
+ return;
+ }
+
/* Check whether there actually is a software breakpoint inserted at
that location.