Index: gdb/breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.343 diff -u -p -r1.343 breakpoint.c --- gdb/breakpoint.c 17 Aug 2008 16:58:17 -0000 1.343 +++ gdb/breakpoint.c 19 Aug 2008 15:21:47 -0000 @@ -195,6 +195,8 @@ static int is_hardware_watchpoint (struc static void insert_breakpoint_locations (void); +static int bp_loc_permanent (struct bp_location *loc); + static const char * bpdisp_text (enum bpdisp disp) { @@ -1743,7 +1745,8 @@ breakpoint_init_inferior (enum inf_conte struct bp_location *bpt; ALL_BP_LOCATIONS (bpt) - bpt->inserted = 0; + if (bpt->owner->enable_state != bp_permanent) + bpt->inserted = 0; ALL_BREAKPOINTS_SAFE (b, temp) { @@ -3081,7 +3084,8 @@ bpstat_stop_status (CORE_ADDR bp_addr, p /* We will stop here */ if (b->disposition == disp_disable) { - b->enable_state = bp_disabled; + if (b->enable_state != bp_permanent) + b->enable_state = bp_disabled; update_global_location_list (0); } if (b->silent) @@ -5120,6 +5124,9 @@ create_breakpoint (struct symtabs_and_li loc = add_location_to_breakpoint (b, type, &sal); } + if (bp_loc_permanent (loc)) + make_breakpoint_permanent (b); + if (b->cond_string) { char *arg = b->cond_string; @@ -7374,6 +7381,10 @@ update_breakpoint_locations (struct brea b->line_number = sals.sals[i].line; } + /* Update locationos of permanent breakpoints. */ + if (b->enable_state == bp_permanent) + make_breakpoint_permanent (b); + /* If possible, carry over 'disable' status from existing breakpoints. */ { struct bp_location *e = existing_locations; @@ -8137,6 +8148,30 @@ single_step_breakpoint_inserted_here_p ( return 0; } +/* Determine if the location is pointing to a permanent breakpoint. */ + +static int +bp_loc_permanent (struct bp_location *loc) +{ + const int READ_SUCCESS = 0; + int len; + CORE_ADDR addr; + const gdb_byte *brk; + gdb_byte target_mem[32]; + + gdb_assert (loc != NULL); + + addr = loc->address; + brk = gdbarch_breakpoint_from_pc (current_gdbarch, &addr, &len); + + if (target_read_memory (loc->address, target_mem, len) == READ_SUCCESS + && memcmp (target_mem, brk, len) == 0) + return 1; + + return 0; +} + + /* This help string is used for the break, hbreak, tbreak and thbreak commands. It is defined as a macro to prevent duplication. Index: gdb/i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.262 diff -u -p -r1.262 i386-tdep.c --- gdb/i386-tdep.c 9 Aug 2008 16:27:39 -0000 1.262 +++ gdb/i386-tdep.c 19 Aug 2008 15:21:47 -0000 @@ -2624,6 +2624,17 @@ i386_fetch_pointer_argument (struct fram return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4); } +static void +i386_skip_permanent_breakpoint (struct regcache *regcache) +{ + CORE_ADDR current_pc = regcache_read_pc (regcache); + /* On i386, breakpoint is exactly 1 byte long, so we just + adjust the PC in the regcache. */ + current_pc += 1; + regcache_write_pc (regcache, current_pc); +} + + static struct gdbarch * i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) @@ -2812,6 +2823,9 @@ i386_gdbarch_init (struct gdbarch_info i if (tdep->mm0_regnum == 0) tdep->mm0_regnum = gdbarch_num_regs (gdbarch); + set_gdbarch_skip_permanent_breakpoint (gdbarch, + i386_skip_permanent_breakpoint); + return gdbarch; }