diff options
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r-- | gdb/gdbserver/ChangeLog | 16 | ||||
-rw-r--r-- | gdb/gdbserver/mem-break.c | 85 | ||||
-rw-r--r-- | gdb/gdbserver/mem-break.h | 5 |
3 files changed, 80 insertions, 26 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index ad6c68e..77d88bc 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,5 +1,21 @@ 2010-03-24 Pedro Alves <pedro@codesourcery.com> + * mem-break.c (enum bkpt_type): New. + (struct breakpoint): New field `type'. + (set_breakpoint_at): Change return type to struct breakpoint + pointer. Set type to `other_breakpoint' by default. + (delete_breakpoint): Rewrite, supporting more than one breakpoint + in the breakpoint list. + (delete_reinsert_breakpoints): Only delete reinsert breakpoints. + (reinsert_breakpoint): Rename to ... + (reinsert_raw_breakpoint): ... this. + (reinsert_breakpoints_at): Adjust. + * mem-break.h (struct breakpoint): Declare. + (set_breakpoint_at): Change return type to struct breakpoint + pointer. + +2010-03-24 Pedro Alves <pedro@codesourcery.com> + * server.c (handle_query): Assign, not compare. 2010-03-24 Pedro Alves <pedro@codesourcery.com> diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c index 40d421c..33de80c 100644 --- a/gdb/gdbserver/mem-break.c +++ b/gdb/gdbserver/mem-break.c @@ -26,6 +26,17 @@ int breakpoint_len; #define MAX_BREAKPOINT_LEN 8 +/* The type of a breakpoint. */ +enum bkpt_type + { + /* A basic-software-single-step breakpoint. */ + reinsert_breakpoint, + + /* Any other breakpoint type that doesn't require specific + treatment goes here. E.g., an event breakpoint. */ + other_breakpoint, + }; + struct breakpoint { struct breakpoint *next; @@ -36,11 +47,16 @@ struct breakpoint inferior. */ int inserted; + /* The breakpoint's type. */ + enum bkpt_type type; + /* Function to call when we hit this breakpoint. If it returns 1, the breakpoint shall be deleted; 0, it will be left inserted. */ int (*handler) (CORE_ADDR); }; +static void uninsert_breakpoint (struct breakpoint *bp); + static struct breakpoint * set_raw_breakpoint_at (CORE_ADDR where) { @@ -86,7 +102,7 @@ set_raw_breakpoint_at (CORE_ADDR where) return bp; } -void +struct breakpoint * set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR)) { struct process_info *proc = current_process (); @@ -97,42 +113,45 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR)) if (bp == NULL) { /* warn? */ - return; + return NULL; } bp = xcalloc (1, sizeof (struct breakpoint)); + bp->type = other_breakpoint; bp->handler = handler; bp->next = proc->breakpoints; proc->breakpoints = bp; + + return bp; } static void -delete_breakpoint (struct breakpoint *bp) +delete_breakpoint (struct breakpoint *todel) { struct process_info *proc = current_process (); - struct breakpoint *cur; + struct breakpoint *bp, **bp_link; - if (proc->breakpoints == bp) - { - proc->breakpoints = bp->next; - (*the_target->write_memory) (bp->pc, bp->old_data, - breakpoint_len); - free (bp); - return; - } - cur = proc->breakpoints; - while (cur->next) + bp = proc->breakpoints; + bp_link = &proc->breakpoints; + + while (bp) { - if (cur->next == bp) + if (bp == todel) { - cur->next = bp->next; - (*the_target->write_memory) (bp->pc, bp->old_data, - breakpoint_len); + *bp_link = bp->next; + + uninsert_breakpoint (bp); free (bp); return; } + else + { + bp_link = &bp->next; + bp = *bp_link; + } } + warning ("Could not find breakpoint in list."); } @@ -163,7 +182,11 @@ delete_breakpoint_at (CORE_ADDR addr) void set_reinsert_breakpoint (CORE_ADDR stop_at) { - set_breakpoint_at (stop_at, NULL); + struct breakpoint *bp; + + bp = set_breakpoint_at (stop_at, NULL); + + bp->type = reinsert_breakpoint; } void @@ -177,9 +200,23 @@ delete_reinsert_breakpoints (void) while (bp) { - *bp_link = bp->next; - delete_breakpoint (bp); - bp = *bp_link; + if (bp->type == reinsert_breakpoint) + { + *bp_link = bp->next; + + /* If something goes wrong, maybe this is a shared library + breakpoint, and the shared library has been unmapped. + Assume the breakpoint is gone anyway. */ + uninsert_breakpoint (bp); + free (bp); + + bp = *bp_link; + } + else + { + bp_link = &bp->next; + bp = *bp_link; + } } } @@ -228,7 +265,7 @@ uninsert_breakpoints_at (CORE_ADDR pc) } static void -reinsert_breakpoint (struct breakpoint *bp) +reinsert_raw_breakpoint (struct breakpoint *bp) { int err; @@ -263,7 +300,7 @@ reinsert_breakpoints_at (CORE_ADDR pc) return; } - reinsert_breakpoint (bp); + reinsert_raw_breakpoint (bp); } void diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h index 2b88034..2953d03 100644 --- a/gdb/gdbserver/mem-break.h +++ b/gdb/gdbserver/mem-break.h @@ -23,6 +23,7 @@ #define MEM_BREAK_H /* Breakpoints are opaque. */ +struct breakpoint; /* Returns TRUE if breakpoints are supported on this target. */ @@ -41,8 +42,8 @@ int breakpoint_inserted_here (CORE_ADDR addr); it is hit. HANDLER should return 1 if the breakpoint should be deleted, 0 otherwise. */ -void set_breakpoint_at (CORE_ADDR where, - int (*handler) (CORE_ADDR)); +struct breakpoint *set_breakpoint_at (CORE_ADDR where, + int (*handler) (CORE_ADDR)); /* Delete a breakpoint previously inserted at ADDR with set_breakpoint_at. */ |