diff -r c9da7894e8d5 gdb/ada-lang.c --- a/gdb/ada-lang.c Sun Oct 05 16:06:42 2008 -0700 +++ b/gdb/ada-lang.c Mon Oct 06 13:05:03 2008 -0400 @@ -10145,6 +10145,9 @@ print_mention_catch_exception (struct br static struct breakpoint_ops catch_exception_breakpoint_ops = { + NULL, /* insert */ + NULL, /* remove */ + NULL, /* breakpoint_hit */ print_it_catch_exception, print_one_catch_exception, print_mention_catch_exception @@ -10171,6 +10174,9 @@ print_mention_catch_exception_unhandled } static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = { + NULL, /* insert */ + NULL, /* remove */ + NULL, /* breakpoint_hit */ print_it_catch_exception_unhandled, print_one_catch_exception_unhandled, print_mention_catch_exception_unhandled @@ -10197,6 +10203,9 @@ print_mention_catch_assert (struct break } static struct breakpoint_ops catch_assert_breakpoint_ops = { + NULL, /* insert */ + NULL, /* remove */ + NULL, /* breakpoint_hit */ print_it_catch_assert, print_one_catch_assert, print_mention_catch_assert diff -r c9da7894e8d5 gdb/breakpoint.c --- a/gdb/breakpoint.c Sun Oct 05 16:06:42 2008 -0700 +++ b/gdb/breakpoint.c Mon Oct 06 13:05:03 2008 -0400 @@ -159,10 +159,6 @@ static void awatch_command (char *, int) static void do_enable_breakpoint (struct breakpoint *, enum bpdisp); -static void create_fork_vfork_event_catchpoint (int tempflag, - char *cond_string, - enum bptype bp_kind); - static void stop_command (char *arg, int from_tty); static void stopin_command (char *arg, int from_tty); @@ -801,11 +797,9 @@ insert_catchpoint (struct ui_out *uo, vo switch (b->type) { - case bp_catch_fork: - target_insert_fork_catchpoint (PIDGET (inferior_ptid)); - break; - case bp_catch_vfork: - target_insert_vfork_catchpoint (PIDGET (inferior_ptid)); + case bp_catchpoint: + gdb_assert (b->ops != NULL && b->ops->insert != NULL); + b->ops->insert (b); break; case bp_catch_exec: target_insert_exec_catchpoint (PIDGET (inferior_ptid)); @@ -1248,8 +1242,7 @@ Note: automatically using hardware break bpt->inserted = (val != -1); } - else if (bpt->owner->type == bp_catch_fork - || bpt->owner->type == bp_catch_vfork + else if (bpt->owner->type == bp_catchpoint || bpt->owner->type == bp_catch_exec) { struct gdb_exception e = catch_exception (uiout, insert_catchpoint, @@ -1505,6 +1498,14 @@ update_breakpoints_after_exec (void) continue; } + if (b->type == bp_catchpoint) + { + /* For now, none of the bp_catchpoint breakpoints need to + do anything at this point. In the future, if some of + the catchpoints need to something, we will need to add + a new method, and call this method from here. */ + } + /* Don't delete an exec catchpoint, because else the inferior won't stop when it ought! @@ -1513,9 +1514,7 @@ update_breakpoints_after_exec (void) seen, but only when the subsequent exec is seen. (And because deleting fork catchpoints here but not vfork catchpoints will seem mysterious to users, keep those too.) */ - if ((b->type == bp_catch_exec) || - (b->type == bp_catch_vfork) || - (b->type == bp_catch_fork)) + if (b->type == bp_catch_exec) { continue; } @@ -1690,21 +1689,24 @@ remove_breakpoint (struct bp_location *b warning (_("Could not remove hardware watchpoint %d."), b->owner->number); } - else if ((b->owner->type == bp_catch_fork || - b->owner->type == bp_catch_vfork || - b->owner->type == bp_catch_exec) + else if (b->owner->type == bp_catchpoint + && breakpoint_enabled (b->owner) + && !b->duplicate) + { + gdb_assert (b->owner->ops != NULL && b->owner->ops->remove != NULL); + + val = b->owner->ops->remove (b->owner); + if (val) + return val; + b->inserted = (is == mark_inserted); + } + else if (b->owner->type == bp_catch_exec && breakpoint_enabled (b->owner) && !b->duplicate) { val = -1; switch (b->owner->type) { - case bp_catch_fork: - val = target_remove_fork_catchpoint (PIDGET (inferior_ptid)); - break; - case bp_catch_vfork: - val = target_remove_vfork_catchpoint (PIDGET (inferior_ptid)); - break; case bp_catch_exec: val = target_remove_exec_catchpoint (PIDGET (inferior_ptid)); break; @@ -1952,11 +1954,9 @@ int int ep_is_catchpoint (struct breakpoint *ep) { - return - (ep->type == bp_catch_load) + return (ep->type == bp_catchpoint) + || (ep->type == bp_catch_load) || (ep->type == bp_catch_unload) - || (ep->type == bp_catch_fork) - || (ep->type == bp_catch_vfork) || (ep->type == bp_catch_exec); /* ??rehrauer: Add more kinds here, as are implemented... */ @@ -2348,22 +2348,6 @@ print_it_typical (bpstat bs) printf_filtered (_("\nCatchpoint %d (unloaded %s), "), b->number, b->triggered_dll_pathname); - return PRINT_SRC_AND_LOC; - break; - - case bp_catch_fork: - annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (forked process %d), "), - b->number, - ptid_get_pid (b->forked_inferior_pid)); - return PRINT_SRC_AND_LOC; - break; - - case bp_catch_vfork: - annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (vforked process %d), "), - b->number, - ptid_get_pid (b->forked_inferior_pid)); return PRINT_SRC_AND_LOC; break; @@ -2793,8 +2777,7 @@ bpstat_check_location (const struct bp_l && b->type != bp_read_watchpoint && b->type != bp_access_watchpoint && b->type != bp_hardware_breakpoint - && b->type != bp_catch_fork - && b->type != bp_catch_vfork + && b->type != bp_catchpoint && b->type != bp_catch_exec) /* a non-watchpoint bp */ { if (bl->address != bp_addr) /* address doesn't match */ @@ -2827,7 +2810,7 @@ bpstat_check_location (const struct bp_l && !section_is_mapped (bl->section)) return 0; } - + /* Is this a catchpoint of a load or unload? If so, did we get a load or unload of the specified library? If not, ignore it. */ @@ -2855,16 +2838,13 @@ bpstat_check_location (const struct bp_l ) return 0; - if ((b->type == bp_catch_fork) - && !inferior_has_forked (inferior_ptid, - &b->forked_inferior_pid)) - return 0; - - if ((b->type == bp_catch_vfork) - && !inferior_has_vforked (inferior_ptid, - &b->forked_inferior_pid)) - return 0; - + if (b->type == bp_catchpoint) + { + gdb_assert (b->ops != NULL && b->ops->breakpoint_hit != NULL); + if (!b->ops->breakpoint_hit (b)) + return 0; + } + if ((b->type == bp_catch_exec) && !inferior_has_execd (inferior_ptid, &b->exec_pathname)) return 0; @@ -3393,8 +3373,7 @@ bpstat_what (bpstat bs) else bs_class = no_effect; break; - case bp_catch_fork: - case bp_catch_vfork: + case bp_catchpoint: case bp_catch_exec: if (bs->stop) { @@ -3573,10 +3552,9 @@ print_one_breakpoint_location (struct br {bp_shlib_event, "shlib events"}, {bp_thread_event, "thread events"}, {bp_overlay_event, "overlay events"}, + {bp_catchpoint, "catchpoint"}, {bp_catch_load, "catch load"}, {bp_catch_unload, "catch unload"}, - {bp_catch_fork, "catch fork"}, - {bp_catch_vfork, "catch vfork"}, {bp_catch_exec, "catch exec"} }; @@ -3708,23 +3686,6 @@ print_one_breakpoint_location (struct br ui_out_text (uiout, "library \""); ui_out_field_string (uiout, "what", b->dll_pathname); ui_out_text (uiout, "\" "); - } - break; - - case bp_catch_fork: - case bp_catch_vfork: - /* Field 4, the address, is omitted (which makes the columns - not line up too nicely with the headers, but the effect - is relatively readable). */ - if (addressprint) - ui_out_field_skip (uiout, "addr"); - annotate_field (5); - if (!ptid_equal (b->forked_inferior_pid, null_ptid)) - { - ui_out_text (uiout, "process "); - ui_out_field_int (uiout, "what", - ptid_get_pid (b->forked_inferior_pid)); - ui_out_spaces (uiout, 1); } break; @@ -3939,10 +3900,9 @@ user_settable_breakpoint (const struct b user_settable_breakpoint (const struct breakpoint *b) { return (b->type == bp_breakpoint + || b->type == bp_catchpoint || b->type == bp_catch_load || b->type == bp_catch_unload - || b->type == bp_catch_fork - || b->type == bp_catch_vfork || b->type == bp_catch_exec || b->type == bp_hardware_breakpoint || b->type == bp_watchpoint @@ -4150,8 +4110,8 @@ set_default_breakpoint (int valid, CORE_ bp_hardware_watchpoint bp_read_watchpoint bp_access_watchpoint + bp_catchpoint bp_catch_exec - bp_catch_fork bp_catch_vork */ static int @@ -4163,9 +4123,8 @@ breakpoint_address_is_meaningful (struct && type != bp_hardware_watchpoint && type != bp_read_watchpoint && type != bp_access_watchpoint - && type != bp_catch_exec - && type != bp_catch_fork - && type != bp_catch_vfork); + && type != bp_catchpoint + && type != bp_catch_exec); } /* Rescan breakpoints at the same address and section as BPT, @@ -4280,8 +4239,7 @@ adjust_breakpoint_address (CORE_ADDR bpa || bptype == bp_hardware_watchpoint || bptype == bp_read_watchpoint || bptype == bp_access_watchpoint - || bptype == bp_catch_fork - || bptype == bp_catch_vfork + || bptype == bp_catchpoint || bptype == bp_catch_exec) { /* Watchpoints and the various bp_catch_* eventpoints should not @@ -4348,8 +4306,7 @@ allocate_bp_location (struct breakpoint loc->loc_type = bp_loc_hardware_watchpoint; break; case bp_watchpoint: - case bp_catch_fork: - case bp_catch_vfork: + case bp_catchpoint: case bp_catch_exec: loc->loc_type = bp_loc_other; break; @@ -4750,45 +4707,210 @@ disable_breakpoints_in_unloaded_shlib (s } } -static void -create_fork_vfork_event_catchpoint (int tempflag, char *cond_string, - enum bptype bp_kind) -{ - struct symtab_and_line sal; - struct breakpoint *b; - int thread = -1; /* All threads. */ +/* FORK & VFORK catchpoints. */ + +/* Implement the "insert" breakpoint_ops method for fork catchpoints. */ + +static void +insert_catch_fork (struct breakpoint *b) +{ + target_insert_fork_catchpoint (PIDGET (inferior_ptid)); +} + +/* Implement the "remove" breakpoint_ops method for fork catchpoints. */ + +static int +remove_catch_fork (struct breakpoint *b) +{ + return target_remove_fork_catchpoint (PIDGET (inferior_ptid)); +} + +/* Implement the "breakpoint_hit" breakpoint_ops method for fork + catchpoints. */ + +static int +breakpoint_hit_catch_fork (struct breakpoint *b) +{ + return inferior_has_forked (inferior_ptid, &b->forked_inferior_pid); +} + +/* Implement the "print_it" breakpoint_ops method for fork catchpoints. */ + +static enum print_stop_action +print_it_catch_fork (struct breakpoint *b) +{ + annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (forked process %d), "), + b->number, ptid_get_pid (b->forked_inferior_pid)); + return PRINT_SRC_AND_LOC; +} + +/* Implement the "print_one" breakpoint_ops method for fork catchpoints. */ + +static void +print_one_catch_fork (struct breakpoint *b, CORE_ADDR *last_addr) +{ + /* Field 4, the address, is omitted (which makes the columns + not line up too nicely with the headers, but the effect + is relatively readable). */ + if (addressprint) + ui_out_field_skip (uiout, "addr"); + annotate_field (5); + ui_out_text (uiout, "fork"); + if (!ptid_equal (b->forked_inferior_pid, null_ptid)) + { + ui_out_text (uiout, ", process "); + ui_out_field_int (uiout, "what", + ptid_get_pid (b->forked_inferior_pid)); + ui_out_spaces (uiout, 1); + } +} + +/* Implement the "print_mention" breakpoint_ops method for fork + catchpoints. */ + +static void +print_mention_catch_fork (struct breakpoint *b) +{ + printf_filtered (_("Catchpoint %d (fork)"), b->number); +} + +/* The breakpoint_ops structure to be used in fork catchpoints. */ + +static struct breakpoint_ops catch_fork_breakpoint_ops = +{ + insert_catch_fork, + remove_catch_fork, + breakpoint_hit_catch_fork, + print_it_catch_fork, + print_one_catch_fork, + print_mention_catch_fork +}; + +/* Implement the "insert" breakpoint_ops method for vfork catchpoints. */ + +static void +insert_catch_vfork (struct breakpoint *b) +{ + target_insert_vfork_catchpoint (PIDGET (inferior_ptid)); +} + +/* Implement the "remove" breakpoint_ops method for vfork catchpoints. */ + +static int +remove_catch_vfork (struct breakpoint *b) +{ + return target_remove_vfork_catchpoint (PIDGET (inferior_ptid)); +} + +/* Implement the "breakpoint_hit" breakpoint_ops method for vfork + catchpoints. */ + +static int +breakpoint_hit_catch_vfork (struct breakpoint *b) +{ + return inferior_has_vforked (inferior_ptid, &b->forked_inferior_pid); +} + +/* Implement the "print_it" breakpoint_ops method for vfork catchpoints. */ + +static enum print_stop_action +print_it_catch_vfork (struct breakpoint *b) +{ + annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (vforked process %d), "), + b->number, ptid_get_pid (b->forked_inferior_pid)); + return PRINT_SRC_AND_LOC; +} + +/* Implement the "print_one" breakpoint_ops method for vfork catchpoints. */ + +static void +print_one_catch_vfork (struct breakpoint *b, CORE_ADDR *last_addr) +{ + /* Field 4, the address, is omitted (which makes the columns + not line up too nicely with the headers, but the effect + is relatively readable). */ + if (addressprint) + ui_out_field_skip (uiout, "addr"); + annotate_field (5); + ui_out_text (uiout, "vfork"); + if (!ptid_equal (b->forked_inferior_pid, null_ptid)) + { + ui_out_text (uiout, ", process "); + ui_out_field_int (uiout, "what", + ptid_get_pid (b->forked_inferior_pid)); + ui_out_spaces (uiout, 1); + } +} + +/* Implement the "print_mention" breakpoint_ops method for vfork + catchpoints. */ + +static void +print_mention_catch_vfork (struct breakpoint *b) +{ + printf_filtered (_("Catchpoint %d (vfork)"), b->number); +} + +/* The breakpoint_ops structure to be used in vfork catchpoints. */ + +static struct breakpoint_ops catch_vfork_breakpoint_ops = +{ + insert_catch_vfork, + remove_catch_vfork, + breakpoint_hit_catch_vfork, + print_it_catch_vfork, + print_one_catch_vfork, + print_mention_catch_vfork +}; + +/* Create a new breakpoint of the bp_catchpoint kind and return it. + + If TEMPFLAG is non-zero, then make the breakpoint temporary. + If COND_STRING is not NULL, then store it in the breakpoint. + OPS, if not NULL, is the breakpoint_ops structure associated + to the catchpoint. */ + +static struct breakpoint * +create_catchpoint (int tempflag, char *cond_string, + struct breakpoint_ops *ops) +{ + struct symtab_and_line sal; + struct breakpoint *b; init_sal (&sal); sal.pc = 0; sal.symtab = NULL; sal.line = 0; - b = set_raw_breakpoint (sal, bp_kind); + b = set_raw_breakpoint (sal, bp_catchpoint); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; + b->cond_string = (cond_string == NULL) ? NULL : savestring (cond_string, strlen (cond_string)); - b->thread = thread; + b->thread = -1; b->addr_string = NULL; b->enable_state = bp_enabled; b->disposition = tempflag ? disp_del : disp_donttouch; + b->ops = ops; + + mention (b); + update_global_location_list (1); + + return b; +} + +static void +create_fork_vfork_event_catchpoint (int tempflag, char *cond_string, + struct breakpoint_ops *ops) +{ + struct breakpoint *b = create_catchpoint (tempflag, cond_string, ops); + + /* FIXME: We should put this information in a breakpoint private data + area. */ b->forked_inferior_pid = null_ptid; - update_global_location_list (1); - - - mention (b); -} - -static void -create_fork_event_catchpoint (int tempflag, char *cond_string) -{ - create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_fork); -} - -static void -create_vfork_event_catchpoint (int tempflag, char *cond_string) -{ - create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_vfork); } static void @@ -5023,12 +5145,6 @@ mention (struct breakpoint *b) (b->type == bp_catch_load) ? "load" : "unload", (b->dll_pathname != NULL) ? b->dll_pathname : ""); - break; - case bp_catch_fork: - case bp_catch_vfork: - printf_filtered (_("Catchpoint %d (%s)"), - b->number, - (b->type == bp_catch_fork) ? "fork" : "vfork"); break; case bp_catch_exec: printf_filtered (_("Catchpoint %d (exec)"), @@ -6450,11 +6566,13 @@ catch_fork_command_1 (char *arg, int fro { case catch_fork_temporary: case catch_fork_permanent: - create_fork_event_catchpoint (tempflag, cond_string); + create_fork_vfork_event_catchpoint (tempflag, cond_string, + &catch_fork_breakpoint_ops); break; case catch_vfork_temporary: case catch_vfork_permanent: - create_vfork_event_catchpoint (tempflag, cond_string); + create_fork_vfork_event_catchpoint (tempflag, cond_string, + &catch_vfork_breakpoint_ops); break; default: error (_("unsupported or unknown fork kind; cannot catch it")); @@ -6651,6 +6769,9 @@ print_mention_exception_catchpoint (stru } static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = { + NULL, /* insert */ + NULL, /* remove */ + NULL, /* breakpoint_hit */ print_exception_catchpoint, print_one_exception_catchpoint, print_mention_exception_catchpoint @@ -7617,8 +7738,7 @@ breakpoint_re_set_one (void *bint) /* We needn't really do anything to reset these, since the mask that requests them is unaffected by e.g., new libraries being loaded. */ - case bp_catch_fork: - case bp_catch_vfork: + case bp_catchpoint: case bp_catch_exec: break; @@ -7888,10 +8008,9 @@ disable_command (char *args, int from_tt bpt->number); continue; case bp_breakpoint: + case bp_catchpoint: case bp_catch_load: case bp_catch_unload: - case bp_catch_fork: - case bp_catch_vfork: case bp_catch_exec: case bp_hardware_breakpoint: case bp_watchpoint: @@ -8022,10 +8141,9 @@ enable_command (char *args, int from_tty bpt->number); continue; case bp_breakpoint: + case bp_catchpoint: case bp_catch_load: case bp_catch_unload: - case bp_catch_fork: - case bp_catch_vfork: case bp_catch_exec: case bp_hardware_breakpoint: case bp_watchpoint: diff -r c9da7894e8d5 gdb/breakpoint.h --- a/gdb/breakpoint.h Sun Oct 05 16:06:42 2008 -0700 +++ b/gdb/breakpoint.h Mon Oct 06 13:05:03 2008 -0400 @@ -110,6 +110,8 @@ enum bptype bp_overlay_event, + bp_catchpoint, + /* These breakpoints are used to implement the "catch load" command on platforms whose dynamic linkers support such functionality. */ bp_catch_load, @@ -124,8 +126,6 @@ enum bptype kernels which can raise an event when a fork or exec occurs, as opposed to the debugger setting breakpoints on functions named "fork" or "exec".) */ - bp_catch_fork, - bp_catch_vfork, bp_catch_exec, }; @@ -315,6 +315,19 @@ struct bp_location struct breakpoint_ops { + /* Insert the breakpoint or activate the catchpoint. Should raise + an exception if the operation failed. */ + void (*insert) (struct breakpoint *); + + /* Remove the breakpoint/catchpoint that was previously inserted + with the "insert" method above. Return non-zero if the operation + succeeded. */ + int (*remove) (struct breakpoint *); + + /* Return non-zero if the debugger should tell the user that this + breakpoint was hit. */ + int (*breakpoint_hit) (struct breakpoint *); + /* The normal print routine for this breakpoint, called when we hit it. */ enum print_stop_action (*print_it) (struct breakpoint *); diff -r c9da7894e8d5 gdb/testsuite/gdb.base/foll-fork.exp --- a/gdb/testsuite/gdb.base/foll-fork.exp Sun Oct 05 16:06:42 2008 -0700 +++ b/gdb/testsuite/gdb.base/foll-fork.exp Mon Oct 06 13:05:03 2008 -0400 @@ -158,14 +158,11 @@ proc catch_fork_child_follow {} { # Verify that the catchpoint is mentioned in an "info breakpoints", # and further that the catchpoint mentions no process id. # - send_gdb "info breakpoints\n" - gdb_expect { - -re ".*catch fork.*keep y.*$gdb_prompt $"\ - {pass "info shows catchpoint without pid"} - -re ".*catch fork.*process .*$gdb_prompt $"\ - {fail "info shows catchpoint without pid"} - -re "$gdb_prompt $" {fail "info shows catchpoint without pid"} - timeout {fail "(timeout) info shows catchpoint without pid"} + set test_name "info shows catchpoint without pid" + gdb_test_multiple "info breakpoints" "$test_name" { + -re ".*catchpoint.*keep y.*fork\[\r\n\]+$gdb_prompt $" { + pass "$test_name" + } } send_gdb "continue\n" @@ -179,12 +176,11 @@ proc catch_fork_child_follow {} { # Verify that the catchpoint is mentioned in an "info breakpoints", # and further that the catchpoint managed to capture a process id. # - send_gdb "info breakpoints\n" - gdb_expect { - -re ".*catch fork .*process \[0-9\]+.*$gdb_prompt $"\ - {pass "info shows catchpoint pid"} - -re "$gdb_prompt $" {fail "info shows catchpoint pid"} - timeout {fail "(timeout) info shows catchpoint pid"} + set test_name "info shows catchpoint without pid" + gdb_test_multiple "info breakpoints" "$test_name" { + -re ".*catchpoint.*keep y.*fork, process.*$gdb_prompt $" { + pass "$test_name" + } } send_gdb "set follow child\n"