Index: breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.142 diff -u -p -r1.142 breakpoint.c --- breakpoint.c 6 Nov 2003 18:35:05 -0000 1.142 +++ breakpoint.c 19 Nov 2003 00:51:08 -0000 @@ -119,6 +119,8 @@ static void condition_command (char *, i static int get_number_trailer (char **, int); +static int do_captured_parse_breakpoint (void *); + void set_breakpoint_count (int); typedef enum @@ -2572,7 +2574,8 @@ bpstat_stop_status (CORE_ADDR *pc, int n { if (b->enable_state == bp_disabled || b->enable_state == bp_shlib_disabled - || b->enable_state == bp_call_disabled) + || b->enable_state == bp_call_disabled + || b->enable_state == bp_shlib_pending) continue; if (b->type != bp_watchpoint @@ -3300,7 +3303,7 @@ print_one_breakpoint (struct breakpoint static char *bpdisps[] = {"del", "dstp", "dis", "keep"}; - static char bpenables[] = "nynny"; + static char bpenables[] = "nynnyn"; char wrap_indent[80]; struct ui_stream *stb = ui_out_stream_new (uiout); struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb); @@ -3454,7 +3457,15 @@ print_one_breakpoint (struct breakpoint if (addressprint) { annotate_field (4); - ui_out_field_core_addr (uiout, "addr", b->loc->address); + if (b->enable_state == bp_shlib_pending) + { + if (TARGET_ADDR_BIT <= 32) + ui_out_field_string (uiout, "addr", " "); + else + ui_out_field_string (uiout, "addr", " "); + } + else + ui_out_field_core_addr (uiout, "addr", b->loc->address); } annotate_field (5); *last_addr = b->loc->address; @@ -3473,6 +3484,10 @@ print_one_breakpoint (struct breakpoint ui_out_text (uiout, ":"); ui_out_field_int (uiout, "line", b->line_number); } + else if (b->enable_state == bp_shlib_pending) + { + ui_out_field_string (uiout, "pending", b->addr_string); + } else { print_address_symbolic (b->loc->address, stb->stream, demangle, ""); @@ -3740,14 +3755,14 @@ describe_other_breakpoints (CORE_ADDR pc ALL_BREAKPOINTS (b) if (b->loc->address == pc) /* address match / overlay match */ - if (!overlay_debugging || b->loc->section == section) + if (b->enable_state != bp_shlib_pending && (!overlay_debugging || b->loc->section == section)) others++; if (others > 0) { printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : ""); ALL_BREAKPOINTS (b) if (b->loc->address == pc) /* address match / overlay match */ - if (!overlay_debugging || b->loc->section == section) + if (b->enable_state != bp_shlib_pending && (!overlay_debugging || b->loc->section == section)) { others--; printf_filtered ("%d%s%s ", @@ -3836,6 +3851,7 @@ check_duplicates (struct breakpoint *bpt ALL_BP_LOCATIONS (b) if (b->owner->enable_state != bp_disabled && b->owner->enable_state != bp_shlib_disabled + && b->owner->enable_state != bp_shlib_pending && b->owner->enable_state != bp_call_disabled && b->address == address /* address / overlay match */ && (!overlay_debugging || b->section == section) @@ -3870,6 +3886,7 @@ check_duplicates (struct breakpoint *bpt { if (b->owner->enable_state != bp_disabled && b->owner->enable_state != bp_shlib_disabled + && b->owner->enable_state != bp_shlib_pending && b->owner->enable_state != bp_call_disabled && b->address == address /* address / overlay match */ && (!overlay_debugging || b->section == section) @@ -4284,22 +4301,84 @@ disable_breakpoints_in_shlibs (int silen } } +struct captured_parse_breakpoint_args + { + char **arg_p; + struct symtabs_and_lines *sals_p; + char ***addr_string_p; + }; + /* Try to reenable any breakpoints in shared libraries. */ void re_enable_breakpoints_in_shlibs (void) { struct breakpoint *b; + struct breakpoint *del_b = NULL; ALL_BREAKPOINTS (b) + { + if (del_b) + { + delete_breakpoint (del_b); + del_b = NULL; + if (b == NULL) + break; + } if (b->enable_state == bp_shlib_disabled) - { - char buf[1]; + { + char buf[1]; + + /* Do not reenable the breakpoint if the shared library + is still not mapped in. */ + if (target_read_memory (b->loc->address, buf, 1) == 0) + b->enable_state = bp_enabled; + } + else if (b->enable_state == bp_shlib_pending) + { + /* Try and reparse the breakpoint in case the shared library + is now loaded. */ + struct symtabs_and_lines sals; + struct symtab_and_line pending_sal; + /* Pointers in arg to the start, and one past the end, of the + condition. */ + char **cond_string = (char **) NULL; + char *copy_arg = b->addr_string; + char **addr_string; + struct captured_parse_breakpoint_args parse_args; + int rc; + + sals.sals = NULL; + sals.nelts = 0; + addr_string = NULL; + + parse_args.arg_p = ©_arg; + parse_args.sals_p = &sals; + parse_args.addr_string_p = &addr_string; + + rc = catch_errors (do_captured_parse_breakpoint, &parse_args, + NULL, RETURN_MASK_ALL); - /* Do not reenable the breakpoint if the shared library - is still not mapped in. */ - if (target_read_memory (b->loc->address, buf, 1) == 0) - b->enable_state = bp_enabled; - } + if (rc == GDB_RC_OK) + { + enum language old_language = current_language->la_language; + int old_input_radix = input_radix; + + printf_filtered ("Pending breakpoint <%s> resolved\n", b->addr_string); + + /* Set language, input-radix, then reissue breakpoint command. Following the + command, restore the language and input-radix. */ + set_language (b->language); + input_radix = b->input_radix; + break_command_1 (b->addr_string, b->flag, b->from_tty); + set_language (old_language); + input_radix = old_input_radix; + del_b = b; /* Delete on next pass. */ + } + } + } + + if (del_b) + delete_breakpoint (del_b); } #endif @@ -4712,14 +4791,21 @@ mention (struct breakpoint *b) if (say_where) { - if (addressprint || b->source_file == NULL) + if (b->enable_state == bp_shlib_pending) { - printf_filtered (" at "); - print_address_numeric (b->loc->address, 1, gdb_stdout); + printf_filtered (" (%s) pending.", b->addr_string); + } + else + { + if (addressprint || b->source_file == NULL) + { + printf_filtered (" at "); + print_address_numeric (b->loc->address, 1, gdb_stdout); + } + if (b->source_file) + printf_filtered (": file %s, line %d.", + b->source_file, b->line_number); } - if (b->source_file) - printf_filtered (": file %s, line %d.", - b->source_file, b->line_number); } do_cleanups (old_chain); if (ui_out_is_mi_like_p (uiout)) @@ -4892,6 +4978,16 @@ breakpoint_sals_to_pc (struct symtabs_an } } +static int +do_captured_parse_breakpoint (void *data) +{ + struct captured_parse_breakpoint_args *args = data; + + parse_breakpoint_sals (args->arg_p, args->sals_p, args->addr_string_p); + + return GDB_RC_OK; +} + /* Set a breakpoint according to ARG (function, linenum or *address) flag: first bit : 0 non-temporary, 1 temporary. second bit : 0 normal breakpoint, 1 hardware breakpoint. */ @@ -4902,14 +4998,18 @@ break_command_1 (char *arg, int flag, in int tempflag, hardwareflag; struct symtabs_and_lines sals; struct expression **cond = 0; + struct symtab_and_line pending_sal; /* Pointers in arg to the start, and one past the end, of the condition. */ char **cond_string = (char **) NULL; + char *copy_arg; char *addr_start = arg; char **addr_string; struct cleanup *old_chain; struct cleanup *breakpoint_chain = NULL; - int i; + struct captured_parse_breakpoint_args parse_args; + int i, rc; + int pending = 0; int thread = -1; int ignore_count = 0; @@ -4919,19 +5019,40 @@ break_command_1 (char *arg, int flag, in sals.sals = NULL; sals.nelts = 0; addr_string = NULL; - parse_breakpoint_sals (&arg, &sals, &addr_string); - if (!sals.nelts) + parse_args.arg_p = &arg; + parse_args.sals_p = &sals; + parse_args.addr_string_p = &addr_string; + + rc = catch_errors (do_captured_parse_breakpoint, &parse_args, + NULL, RETURN_MASK_ALL); + + if (rc != GDB_RC_OK) + { + if (!query ("Make breakpoint pending? ")) + return; + copy_arg = (char *)xmalloc (strlen (addr_start)); + strcpy (copy_arg, addr_start); + addr_string = ©_arg; + sals.nelts = 1; + sals.sals = &pending_sal; + pending_sal.pc = 0; + pending = 1; + } + else if (!sals.nelts) return; /* Create a chain of things that always need to be cleaned up. */ old_chain = make_cleanup (null_cleanup, 0); - /* Make sure that all storage allocated to SALS gets freed. */ - make_cleanup (xfree, sals.sals); - - /* Cleanup the addr_string array but not its contents. */ - make_cleanup (xfree, addr_string); + if (!pending) + { + /* Make sure that all storage allocated to SALS gets freed. */ + make_cleanup (xfree, sals.sals); + + /* Cleanup the addr_string array but not its contents. */ + make_cleanup (xfree, addr_string); + } /* Allocate space for all the cond expressions. */ cond = xcalloc (sals.nelts, sizeof (struct expression *)); @@ -4958,7 +5079,8 @@ break_command_1 (char *arg, int flag, in /* Resolve all line numbers to PC's and verify that the addresses are ok for the target. */ - breakpoint_sals_to_pc (&sals, addr_start); + if (!pending) + breakpoint_sals_to_pc (&sals, addr_start); /* Verify that condition can be parsed, before setting any breakpoints. Allocate a separate condition expression for each @@ -5009,11 +5131,34 @@ break_command_1 (char *arg, int flag, in } } - create_breakpoints (sals, addr_string, cond, cond_string, - hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, - tempflag ? disp_del : disp_donttouch, - thread, ignore_count, from_tty); + if (pending) + { + struct symtab_and_line sal; + struct breakpoint *b; + + sal.symtab = NULL; + sal.pc = 0; + b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint : bp_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->cond = *cond; + b->thread = thread; + b->addr_string = *addr_string; + b->cond_string = *cond_string; + b->ignore_count = ignore_count; + b->enable_state = bp_shlib_pending; + b->disposition = tempflag ? disp_del : disp_donttouch; + b->from_tty = from_tty; + b->flag = flag; + mention (b); + } + else + create_breakpoints (sals, addr_string, cond, cond_string, + hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, + tempflag ? disp_del : disp_donttouch, + thread, ignore_count, from_tty); + if (sals.nelts > 1) { warning ("Multiple breakpoints were set."); @@ -6759,6 +6904,7 @@ delete_breakpoint (struct breakpoint *bp && !b->loc->duplicate && b->enable_state != bp_disabled && b->enable_state != bp_shlib_disabled + && b->enable_state != bp_shlib_pending && b->enable_state != bp_call_disabled) { int val; @@ -6964,8 +7110,12 @@ breakpoint_re_set_one (void *bint) shlib_disabled breakpoint though. There's a fair chance we can't re-set it if the shared library it's in hasn't been loaded yet. */ + + if (b->enable_state == bp_shlib_pending) + break; + save_enable = b->enable_state; - if (b->enable_state != bp_shlib_disabled) + if (b->enable_state != bp_shlib_disabled) b->enable_state = bp_disabled; set_language (b->language); Index: breakpoint.h =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.h,v retrieving revision 1.26 diff -u -p -r1.26 breakpoint.h --- breakpoint.h 6 Nov 2003 18:24:55 -0000 1.26 +++ breakpoint.h 19 Nov 2003 00:51:08 -0000 @@ -158,11 +158,14 @@ enum enable_state automatically enabled and reset when the call "lands" (either completes, or stops at another eventpoint). */ - bp_permanent /* There is a breakpoint instruction hard-wired into + bp_permanent, /* There is a breakpoint instruction hard-wired into the target's code. Don't try to write another breakpoint instruction on top of it, or restore its value. Step over it using the architecture's SKIP_INSN macro. */ + bp_shlib_pending, /* The eventpoint could not be set as an shlib has + not yet been loaded the first time. When the + shlib is loaded, it will be reissued. */ }; @@ -385,6 +388,12 @@ struct breakpoint /* Methods associated with this breakpoint. */ struct breakpoint_ops *ops; + + /* Initial from_tty value. */ + int from_tty; + + /* Initial flag value. */ + int flag; }; /* The following stuff is an abstract data type "bpstat" ("breakpoint