diff options
-rw-r--r-- | gdb/ChangeLog | 33 | ||||
-rw-r--r-- | gdb/breakpoint.c | 545 | ||||
-rw-r--r-- | gdb/breakpoint.h | 11 |
3 files changed, 440 insertions, 149 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a862bf0..7c0ded5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,36 @@ +2004-02-02 Jeff Johnston <jjohnstn@redhat.com> + + * breakpoint.h (struct breakpoint): Add new flag, from_tty, + and pending fields for pending breakpoint support. + * breakpoint.c (breakpoint_enabled): Add check for not pending. + (condition_command): Only parse condition if not a pending + breakpoint. + (print_one_breakpoint): Add support for pending breakpoints. + (describe_other_breakpoints): Add checks to verify we are not + dealing with pending breakpoints. + (check_duplicates): Don't check pending breakpoints. + (set_raw_breakpoint): Initialize pending flag. + (do_restore_lang_radix_cleanup): New cleanup routine. + (resolve_pending_breakpoint): New function. + (re_enable_breakpoints_in_shlibs): Try and resolve any + pending breakpoints via resolve_pending_breakpoint. + (mention): Add pending breakpoint support. + (parse_breakpoint_sals): Add new parameter to pass to + decode_line_1 to indicate silent errors when files or functions + are not found. Change all callers. + (do_captured_parse_breakpoint): New function. + (break_command_1): Change prototype to return an rc value and to + take an optional pending breakpoint pointer. Support creating + a pending breakpoint if a "not found" form of error occurs when + parsing the breakpoint. Also support resolving an existing pending + breakpoint and be silent if the resolution fails. + (create_breakpoints): Change prototype to take pending breakpoint + pointer. When resolving a pending breakpoint, use the new pointer + to provide a conditional or commands added by the end-user. + (delete_breakpoint): Add appropriate check for pending. + (breakpoint_re_set_one): Ditto. + (do_enable_breakpoint): Ditto. + 2004-02-02 David Carlton <carlton@kealia.com> * valops.c (enum oload_classification): New. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index ebd73f1..3c7ba46 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -89,7 +89,7 @@ extern void break_at_finish_at_depth_command (char *, int); extern void tbreak_at_finish_command (char *, int); -static void break_command_1 (char *, int, int); +static int break_command_1 (char *, int, int, struct breakpoint *); static void mention (struct breakpoint *); @@ -119,6 +119,8 @@ static void condition_command (char *, int); static int get_number_trailer (char **, int); +static int do_captured_parse_breakpoint (struct ui_out *, void *); + void set_breakpoint_count (int); typedef enum @@ -322,7 +324,7 @@ int exception_support_initialized = 0; static int breakpoint_enabled (struct breakpoint *b) { - return b->enable_state == bp_enabled; + return (b->enable_state == bp_enabled && !b->pending); } /* Set breakpoint count to NUM. */ @@ -556,9 +558,12 @@ condition_command (char *arg, int from_tty) /* I don't know if it matters whether this is the string the user typed in or the decompiled expression. */ b->cond_string = savestring (arg, strlen (arg)); - b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); - if (*arg) - error ("Junk at end of expression"); + if (!b->pending) + { + b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); + if (*arg) + error ("Junk at end of expression"); + } } breakpoints_changed (); breakpoint_modify_event (b->number); @@ -3465,7 +3470,16 @@ print_one_breakpoint (struct breakpoint *b, if (addressprint) { annotate_field (4); - ui_out_field_core_addr (uiout, "addr", b->loc->address); + if (b->pending) + { + ui_out_field_string (uiout, "addr", "<PENDING>"); + if (TARGET_ADDR_BIT <= 32) + ui_out_spaces (uiout, 2); + else + ui_out_spaces (uiout, 8); + } + else + ui_out_field_core_addr (uiout, "addr", b->loc->address); } annotate_field (5); *last_addr = b->loc->address; @@ -3484,6 +3498,10 @@ print_one_breakpoint (struct breakpoint *b, ui_out_text (uiout, ":"); ui_out_field_int (uiout, "line", b->line_number); } + else if (b->pending) + { + ui_out_field_string (uiout, "pending", b->addr_string); + } else { print_address_symbolic (b->loc->address, stb->stream, demangle, ""); @@ -3520,7 +3538,15 @@ print_one_breakpoint (struct breakpoint *b, ui_out_field_stream (uiout, "cond", stb); ui_out_text (uiout, "\n"); } - + + if (b->pending && b->cond_string) + { + annotate_field (7); + ui_out_text (uiout, "\tstop only if "); + ui_out_field_string (uiout, "cond", b->cond_string); + ui_out_text (uiout, "\n"); + } + if (b->thread != -1) { /* FIXME should make an annotation for this */ @@ -3751,14 +3777,14 @@ describe_other_breakpoints (CORE_ADDR pc, asection *section) ALL_BREAKPOINTS (b) if (b->loc->address == pc) /* address match / overlay match */ - if (!overlay_debugging || b->loc->section == section) + if (!b->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->pending && (!overlay_debugging || b->loc->section == section)) { others--; printf_filtered ("%d%s%s ", @@ -3847,6 +3873,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->pending && b->owner->enable_state != bp_call_disabled && b->address == address /* address / overlay match */ && (!overlay_debugging || b->section == section) @@ -3881,6 +3908,7 @@ check_duplicates (struct breakpoint *bpt) { if (b->owner->enable_state != bp_disabled && b->owner->enable_state != bp_shlib_disabled + && !b->owner->pending && b->owner->enable_state != bp_call_disabled && b->address == address /* address / overlay match */ && (!overlay_debugging || b->section == section) @@ -4057,6 +4085,7 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype) b->forked_inferior_pid = 0; b->exec_pathname = NULL; b->ops = NULL; + b->pending = 0; /* Add this breakpoint to the end of the chain so that a list of breakpoints will come out in order @@ -4295,23 +4324,90 @@ disable_breakpoints_in_shlibs (int silent) } } +struct captured_parse_breakpoint_args + { + char **arg_p; + struct symtabs_and_lines *sals_p; + char ***addr_string_p; + int *not_found_ptr; + }; + +struct lang_and_radix + { + enum language lang; + int radix; + }; + +/* Cleanup helper routine to restore the current language and + input radix. */ +static void +do_restore_lang_radix_cleanup (void *old) +{ + struct lang_and_radix *p = old; + set_language (p->lang); + input_radix = p->radix; +} + +/* Try and resolve a pending breakpoint. */ +static int +resolve_pending_breakpoint (struct breakpoint *b) +{ + /* Try and reparse the breakpoint in case the shared library + is now loaded. */ + struct symtabs_and_lines sals; + struct symtab_and_line pending_sal; + char **cond_string = (char **) NULL; + char *copy_arg = b->addr_string; + char **addr_string; + char *errmsg; + int rc; + int not_found = 0; + struct ui_file *old_gdb_stderr; + struct lang_and_radix old_lr; + struct cleanup *old_chain; + + /* Set language, input-radix, then reissue breakpoint command. + Ensure the language and input-radix are restored afterwards. */ + old_lr.lang = current_language->la_language; + old_lr.radix = input_radix; + old_chain = make_cleanup (do_restore_lang_radix_cleanup, &old_lr); + + set_language (b->language); + input_radix = b->input_radix; + rc = break_command_1 (b->addr_string, b->flag, b->from_tty, b); + + if (rc == GDB_RC_OK) + /* Pending breakpoint has been resolved. */ + printf_filtered ("Pending breakpoint \"%s\" resolved\n", b->addr_string); + + do_cleanups (old_chain); + return rc; +} + /* Try to reenable any breakpoints in shared libraries. */ void re_enable_breakpoints_in_shlibs (void) { - struct breakpoint *b; + struct breakpoint *b, *tmp; - ALL_BREAKPOINTS (b) + ALL_BREAKPOINTS_SAFE (b, tmp) + { if (b->enable_state == bp_shlib_disabled) - { - char buf[1], *lib; - - /* Do not reenable the breakpoint if the shared library - is still not mapped in. */ - lib = PC_SOLIB (b->loc->address); - if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0) - b->enable_state = bp_enabled; - } + { + char buf[1], *lib; + + /* Do not reenable the breakpoint if the shared library + is still not mapped in. */ + lib = PC_SOLIB (b->loc->address); + if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0) + b->enable_state = bp_enabled; + } + else if (b->pending && (b->enable_state == bp_enabled)) + { + if (resolve_pending_breakpoint (b) == GDB_RC_OK) + delete_breakpoint (b); + } + } } #endif @@ -4723,14 +4819,21 @@ mention (struct breakpoint *b) if (say_where) { - if (addressprint || b->source_file == NULL) + if (b->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)) @@ -4743,6 +4846,11 @@ mention (struct breakpoint *b) SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i], COND[i] and COND_STRING[i] values. + The parameter PENDING_BP points to a pending breakpoint that is + the basis of the breakpoints currently being created. The pending + breakpoint may contain a separate condition string or commands + that were added after the initial pending breakpoint was created. + NOTE: If the function succeeds, the caller is expected to cleanup the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the array contents). If the function fails (error() is called), the @@ -4753,7 +4861,8 @@ static void create_breakpoints (struct symtabs_and_lines sals, char **addr_string, struct expression **cond, char **cond_string, enum bptype type, enum bpdisp disposition, - int thread, int ignore_count, int from_tty) + int thread, int ignore_count, int from_tty, + struct breakpoint *pending_bp) { if (type == bp_hardware_breakpoint) { @@ -4793,6 +4902,26 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string, b->ignore_count = ignore_count; b->enable_state = bp_enabled; b->disposition = disposition; + /* If resolving a pending breakpoint, a check must be made to see if + the user has specified a new condition or commands for the + breakpoint. A new condition will override any condition that was + initially specified with the initial breakpoint command. */ + if (pending_bp) + { + char *arg; + if (pending_bp->cond_string) + { + arg = pending_bp->cond_string; + b->cond_string = savestring (arg, strlen (arg)); + b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); + if (*arg) + error ("Junk at end of pending breakpoint condition expression"); + } + /* If there are commands associated with the breakpoint, they should + be copied too. */ + if (pending_bp->commands) + b->commands = copy_command_lines (pending_bp->commands); + } mention (b); } } @@ -4806,7 +4935,8 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string, static void parse_breakpoint_sals (char **address, struct symtabs_and_lines *sals, - char ***addr_string) + char ***addr_string, + int *not_found_ptr) { char *addr_start = *address; *addr_string = NULL; @@ -4847,9 +4977,11 @@ parse_breakpoint_sals (char **address, || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, addr_string, NULL); + default_breakpoint_line, addr_string, + not_found_ptr); else - *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, addr_string, NULL); + *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, + addr_string, not_found_ptr); } /* For any SAL that didn't have a canonical string, fill one in. */ if (sals->nelts > 0 && *addr_string == NULL) @@ -4903,26 +5035,44 @@ breakpoint_sals_to_pc (struct symtabs_and_lines *sals, } } +static int +do_captured_parse_breakpoint (struct ui_out *ui, void *data) +{ + struct captured_parse_breakpoint_args *args = data; + + parse_breakpoint_sals (args->arg_p, args->sals_p, args->addr_string_p, + args->not_found_ptr); + + 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. */ + second bit : 0 normal breakpoint, 1 hardware breakpoint. -static void -break_command_1 (char *arg, int flag, int from_tty) + PENDING_BP is non-NULL when this function is being called to resolve + a pending breakpoint. */ + +static int +break_command_1 (char *arg, int flag, int from_tty, struct breakpoint *pending_bp) { int tempflag, hardwareflag; struct symtabs_and_lines sals; struct expression **cond = 0; - /* Pointers in arg to the start, and one past the end, of the - condition. */ + struct symtab_and_line pending_sal; char **cond_string = (char **) NULL; + char *copy_arg; + char *err_msg; 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; + int not_found = 0; hardwareflag = flag & BP_HARDWAREFLAG; tempflag = flag & BP_TEMPFLAG; @@ -4930,19 +5080,55 @@ break_command_1 (char *arg, int flag, int from_tty) sals.sals = NULL; sals.nelts = 0; addr_string = NULL; - parse_breakpoint_sals (&arg, &sals, &addr_string); - if (!sals.nelts) - return; + parse_args.arg_p = &arg; + parse_args.sals_p = &sals; + parse_args.addr_string_p = &addr_string; + parse_args.not_found_ptr = ¬_found; + + rc = catch_exceptions_with_msg (uiout, do_captured_parse_breakpoint, + &parse_args, NULL, &err_msg, + RETURN_MASK_ALL); + + /* If caller is interested in rc value from parse, set value. */ + + if (rc != GDB_RC_OK) + { + /* Check for file or function not found. */ + if (not_found) + { + /* If called to resolve pending breakpoint, just return error code. */ + if (pending_bp) + return rc; + + error_output_message (NULL, err_msg); + xfree (err_msg); + if (!query ("Make breakpoint pending on future shared library load? ")) + return rc; + copy_arg = xstrdup (addr_start); + addr_string = ©_arg; + sals.nelts = 1; + sals.sals = &pending_sal; + pending_sal.pc = 0; + pending = 1; + } + else + return rc; + } + else if (!sals.nelts) + return GDB_RC_FAIL; /* 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 *)); @@ -4969,62 +5155,94 @@ break_command_1 (char *arg, int flag, int from_tty) /* 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 breakpoint. */ thread = -1; /* No specific thread yet */ - for (i = 0; i < sals.nelts; i++) + if (!pending) { - char *tok = arg; - while (tok && *tok) + for (i = 0; i < sals.nelts; i++) { - char *end_tok; - int toklen; - char *cond_start = NULL; - char *cond_end = NULL; - while (*tok == ' ' || *tok == '\t') - tok++; - - end_tok = tok; - - while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') - end_tok++; - - toklen = end_tok - tok; - - if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) + char *tok = arg; + while (tok && *tok) { - tok = cond_start = end_tok + 1; - cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0); - make_cleanup (xfree, cond[i]); - cond_end = tok; - cond_string[i] = savestring (cond_start, cond_end - cond_start); - make_cleanup (xfree, cond_string[i]); - } - else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0) - { - char *tmptok; - - tok = end_tok + 1; - tmptok = tok; - thread = strtol (tok, &tok, 0); - if (tok == tmptok) - error ("Junk after thread keyword."); - if (!valid_thread_id (thread)) - error ("Unknown thread %d\n", thread); + char *end_tok; + int toklen; + char *cond_start = NULL; + char *cond_end = NULL; + while (*tok == ' ' || *tok == '\t') + tok++; + + end_tok = tok; + + while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') + end_tok++; + + toklen = end_tok - tok; + + if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) + { + tok = cond_start = end_tok + 1; + cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), + 0); + make_cleanup (xfree, cond[i]); + cond_end = tok; + cond_string[i] = savestring (cond_start, + cond_end - cond_start); + make_cleanup (xfree, cond_string[i]); + } + else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0) + { + char *tmptok; + + tok = end_tok + 1; + tmptok = tok; + thread = strtol (tok, &tok, 0); + if (tok == tmptok) + error ("Junk after thread keyword."); + if (!valid_thread_id (thread)) + error ("Unknown thread %d\n", thread); + } + else + error ("Junk at end of arguments."); } - else - error ("Junk at end of arguments."); } + create_breakpoints (sals, addr_string, cond, cond_string, + hardwareflag ? bp_hardware_breakpoint + : bp_breakpoint, + tempflag ? disp_del : disp_donttouch, + thread, ignore_count, from_tty, + pending_bp); } - - create_breakpoints (sals, addr_string, cond, cond_string, - hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, - tempflag ? disp_del : disp_donttouch, - thread, ignore_count, from_tty); - + else + { + struct symtab_and_line sal; + struct breakpoint *b; + + sal.symtab = NULL; + sal.pc = 0; + + make_cleanup (xfree, copy_arg); + + 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->pending = 1; + b->disposition = tempflag ? disp_del : disp_donttouch; + b->from_tty = from_tty; + b->flag = flag; + mention (b); + } + if (sals.nelts > 1) { warning ("Multiple breakpoints were set."); @@ -5035,6 +5253,8 @@ break_command_1 (char *arg, int flag, int from_tty) discard_cleanups (breakpoint_chain); /* But cleanup everything else. */ do_cleanups (old_chain); + + return GDB_RC_OK; } /* Set a breakpoint of TYPE/DISPOSITION according to ARG (function, @@ -5071,7 +5291,7 @@ do_captured_breakpoint (void *data) sals.nelts = 0; address_end = args->address; addr_string = NULL; - parse_breakpoint_sals (&address_end, &sals, &addr_string); + parse_breakpoint_sals (&address_end, &sals, &addr_string, 0); if (!sals.nelts) return GDB_RC_NONE; @@ -5135,7 +5355,8 @@ do_captured_breakpoint (void *data) create_breakpoints (sals, addr_string, cond, cond_string, args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, args->tempflag ? disp_del : disp_donttouch, - args->thread, args->ignore_count, 0/*from-tty*/); + args->thread, args->ignore_count, 0/*from-tty*/, + NULL/*pending_bp*/); /* That's it. Discard the cleanups for data inserted into the breakpoint. */ @@ -5227,7 +5448,7 @@ break_at_finish_at_depth_command_1 (char *arg, int flag, int from_tty) addr_string = xstrprintf ("*0x%s %s", paddr_nz (high), extra_args); else addr_string = xstrprintf ("*0x%s", paddr_nz (high)); - break_command_1 (addr_string, flag, from_tty); + break_command_1 (addr_string, flag, from_tty, NULL); xfree (addr_string); } else @@ -5310,7 +5531,7 @@ break_at_finish_command_1 (char *arg, int flag, int from_tty) extra_args); else break_string = xstrprintf ("*0x%s", paddr_nz (high)); - break_command_1 (break_string, flag, from_tty); + break_command_1 (break_string, flag, from_tty, NULL); xfree (break_string); } else @@ -5377,7 +5598,7 @@ resolve_sal_pc (struct symtab_and_line *sal) void break_command (char *arg, int from_tty) { - break_command_1 (arg, 0, from_tty); + break_command_1 (arg, 0, from_tty, NULL); } void @@ -5395,7 +5616,7 @@ break_at_finish_at_depth_command (char *arg, int from_tty) void tbreak_command (char *arg, int from_tty) { - break_command_1 (arg, BP_TEMPFLAG, from_tty); + break_command_1 (arg, BP_TEMPFLAG, from_tty, NULL); } void @@ -5407,13 +5628,13 @@ tbreak_at_finish_command (char *arg, int from_tty) static void hbreak_command (char *arg, int from_tty) { - break_command_1 (arg, BP_HARDWAREFLAG, from_tty); + break_command_1 (arg, BP_HARDWAREFLAG, from_tty, NULL); } static void thbreak_command (char *arg, int from_tty) { - break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty); + break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty, NULL); } static void @@ -5454,7 +5675,7 @@ stopin_command (char *arg, int from_tty) if (badInput) printf_filtered ("Usage: stop in <function | address>\n"); else - break_command_1 (arg, 0, from_tty); + break_command_1 (arg, 0, from_tty, NULL); } static void @@ -5486,7 +5707,7 @@ stopat_command (char *arg, int from_tty) if (badInput) printf_filtered ("Usage: stop at <line>\n"); else - break_command_1 (arg, 0, from_tty); + break_command_1 (arg, 0, from_tty, NULL); } /* accessflag: hw_write: watch write, @@ -6693,6 +6914,7 @@ delete_breakpoint (struct breakpoint *bpt) && !b->loc->duplicate && b->enable_state != bp_disabled && b->enable_state != bp_shlib_disabled + && !b->pending && b->enable_state != bp_call_disabled) { int val; @@ -6898,6 +7120,10 @@ 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->pending) + break; + save_enable = b->enable_state; if (b->enable_state != bp_shlib_disabled) b->enable_state = bp_disabled; @@ -7313,70 +7539,91 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition) error ("Hardware breakpoints used exceeds limit."); } - if (bpt->enable_state != bp_permanent) - bpt->enable_state = bp_enabled; - bpt->disposition = disposition; - check_duplicates (bpt); - breakpoints_changed (); - - if (bpt->type == bp_watchpoint || - bpt->type == bp_hardware_watchpoint || - bpt->type == bp_read_watchpoint || - bpt->type == bp_access_watchpoint) + if (bpt->pending) { - if (bpt->exp_valid_block != NULL) + if (bpt->enable_state != bp_enabled) { - struct frame_info *fr = - fr = frame_find_by_id (bpt->watchpoint_frame); - if (fr == NULL) + /* When enabling a pending breakpoint, we need to check if the breakpoint + is resolvable since shared libraries could have been loaded + after the breakpoint was disabled. */ + breakpoints_changed (); + if (resolve_pending_breakpoint (bpt) == GDB_RC_OK) { - printf_filtered ("\ -Cannot enable watchpoint %d because the block in which its expression\n\ -is valid is not currently in scope.\n", bpt->number); - bpt->enable_state = bp_disabled; + delete_breakpoint (bpt); return; } - - save_selected_frame = deprecated_selected_frame; - save_selected_frame_level = frame_relative_level (deprecated_selected_frame); - select_frame (fr); + bpt->enable_state = bp_enabled; + bpt->disposition = disposition; } - - value_free (bpt->val); - mark = value_mark (); - bpt->val = evaluate_expression (bpt->exp); - release_value (bpt->val); - if (VALUE_LAZY (bpt->val)) - value_fetch_lazy (bpt->val); - - if (bpt->type == bp_hardware_watchpoint || - bpt->type == bp_read_watchpoint || + } + else /* Not a pending breakpoint. */ + { + if (bpt->enable_state != bp_permanent) + bpt->enable_state = bp_enabled; + bpt->disposition = disposition; + check_duplicates (bpt); + breakpoints_changed (); + + if (bpt->type == bp_watchpoint || + bpt->type == bp_hardware_watchpoint || + bpt->type == bp_read_watchpoint || bpt->type == bp_access_watchpoint) { - int i = hw_watchpoint_used_count (bpt->type, &other_type_used); - int mem_cnt = can_use_hardware_watchpoint (bpt->val); - - /* Hack around 'unused var' error for some targets here */ - (void) mem_cnt, i; - target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT ( - bpt->type, i + mem_cnt, other_type_used); - /* we can consider of type is bp_hardware_watchpoint, convert to - bp_watchpoint in the following condition */ - if (target_resources_ok < 0) + if (bpt->exp_valid_block != NULL) + { + struct frame_info *fr = + fr = frame_find_by_id (bpt->watchpoint_frame); + if (fr == NULL) + { + printf_filtered ("\ +Cannot enable watchpoint %d because the block in which its expression\n\ +is valid is not currently in scope.\n", bpt->number); + bpt->enable_state = bp_disabled; + return; + } + + save_selected_frame = deprecated_selected_frame; + save_selected_frame_level = frame_relative_level (deprecated_selected_frame); + select_frame (fr); + } + + value_free (bpt->val); + mark = value_mark (); + bpt->val = evaluate_expression (bpt->exp); + release_value (bpt->val); + if (VALUE_LAZY (bpt->val)) + value_fetch_lazy (bpt->val); + + if (bpt->type == bp_hardware_watchpoint || + bpt->type == bp_read_watchpoint || + bpt->type == bp_access_watchpoint) { - printf_filtered ("\ + int i = hw_watchpoint_used_count (bpt->type, &other_type_used); + int mem_cnt = can_use_hardware_watchpoint (bpt->val); + + /* Hack around 'unused var' error for some targets here */ + (void) mem_cnt, i; + target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT ( + bpt->type, i + mem_cnt, other_type_used); + /* we can consider of type is bp_hardware_watchpoint, convert to + bp_watchpoint in the following condition */ + if (target_resources_ok < 0) + { + printf_filtered ("\ Cannot enable watchpoint %d because target watch resources\n\ have been allocated for other watchpoints.\n", bpt->number); - bpt->enable_state = bp_disabled; - value_free_to_mark (mark); - return; + bpt->enable_state = bp_disabled; + value_free_to_mark (mark); + return; + } } + + if (save_selected_frame_level >= 0) + select_frame (save_selected_frame); + value_free_to_mark (mark); } - - if (save_selected_frame_level >= 0) - select_frame (save_selected_frame); - value_free_to_mark (mark); } + if (modify_breakpoint_hook) modify_breakpoint_hook (bpt); breakpoint_modify_event (bpt->number); diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 1a4fada..41bcb0c 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -386,6 +386,17 @@ struct breakpoint /* Methods associated with this breakpoint. */ struct breakpoint_ops *ops; + + /* Was breakpoint issued from a tty? Saved for the use of pending breakpoints. */ + int from_tty; + + /* Flag value for pending breakpoint. + first bit : 0 non-temporary, 1 temporary. + second bit : 0 normal breakpoint, 1 hardware breakpoint. */ + int flag; + + /* Is breakpoint pending on shlib loads? */ + int pending; }; /* The following stuff is an abstract data type "bpstat" ("breakpoint |