Index: breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.145 diff -u -p -r1.145 breakpoint.c --- breakpoint.c 17 Nov 2003 00:55:49 -0000 1.145 +++ breakpoint.c 3 Dec 2003 01:21:49 -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 @@ -563,9 +565,12 @@ condition_command (char *arg, int from_t /* 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); @@ -757,7 +762,7 @@ insert_bp_location (struct bp_location * /* Permanent breakpoints cannot be inserted or removed. Disabled breakpoints should not be inserted. */ - if (bpt->owner->enable_state != bp_enabled) + if (bpt->owner->enable_state != bp_enabled || bpt->owner->pending) return 0; if (bpt->inserted || bpt->duplicate) @@ -1107,7 +1112,7 @@ insert_breakpoints (void) { /* Permanent breakpoints cannot be inserted or removed. Disabled breakpoints should not be inserted. */ - if (b->owner->enable_state != bp_enabled) + if (b->owner->enable_state != bp_enabled || b->owner->pending) continue; /* FIXME drow/2003-10-07: This code should be pushed elsewhere when @@ -1458,6 +1463,7 @@ remove_breakpoint (struct bp_location *b } else if (b->loc_type == bp_loc_hardware_watchpoint && b->owner->enable_state == bp_enabled + && !b->owner->pending && !b->duplicate) { struct value *v; @@ -1514,6 +1520,7 @@ remove_breakpoint (struct bp_location *b b->owner->type == bp_catch_vfork || b->owner->type == bp_catch_exec) && b->owner->enable_state == bp_enabled + && !b->owner->pending && !b->duplicate) { val = -1; @@ -1539,6 +1546,7 @@ remove_breakpoint (struct bp_location *b else if ((b->owner->type == bp_catch_catch || b->owner->type == bp_catch_throw) && b->owner->enable_state == bp_enabled + && !b->owner->pending && !b->duplicate) { @@ -1550,6 +1558,7 @@ remove_breakpoint (struct bp_location *b else if (ep_is_exception_catchpoint (b->owner) && b->inserted /* sometimes previous insert doesn't happen */ && b->owner->enable_state == bp_enabled + && !b->owner->pending && !b->duplicate) { @@ -1675,7 +1684,8 @@ breakpoint_here_p (CORE_ADDR pc) && bpt->loc_type != bp_loc_hardware_breakpoint) continue; - if ((bpt->owner->enable_state == bp_enabled + if (((bpt->owner->enable_state == bp_enabled + && !bpt->owner->pending) || bpt->owner->enable_state == bp_permanent) && bpt->address == pc) /* bp is enabled and matches pc */ { @@ -1772,7 +1782,8 @@ breakpoint_thread_match (CORE_ADDR pc, p && bpt->loc_type != bp_loc_hardware_breakpoint) continue; - if ((bpt->owner->enable_state == bp_enabled + if (((bpt->owner->enable_state == bp_enabled + && !bpt->owner->pending) || bpt->owner->enable_state == bp_permanent) && bpt->address == pc && (bpt->owner->thread == -1 || bpt->owner->thread == thread)) @@ -2576,7 +2587,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->pending) continue; if (b->type != bp_watchpoint @@ -3179,7 +3191,7 @@ bpstat_should_step (void) { struct breakpoint *b; ALL_BREAKPOINTS (b) - if (b->enable_state == bp_enabled && b->type == bp_watchpoint) + if (b->enable_state == bp_enabled && !b->pending && b->type == bp_watchpoint) return 1; return 0; } @@ -3190,7 +3202,7 @@ bpstat_have_active_hw_watchpoints (void) { struct bp_location *bpt; ALL_BP_LOCATIONS (bpt) - if ((bpt->owner->enable_state == bp_enabled) + if ((bpt->owner->enable_state == bp_enabled && !bpt->owner->pending) && bpt->inserted && bpt->loc_type == bp_loc_hardware_watchpoint) return 1; @@ -3458,7 +3470,15 @@ print_one_breakpoint (struct breakpoint if (addressprint) { annotate_field (4); - ui_out_field_core_addr (uiout, "addr", b->loc->address); + if (b->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; @@ -3477,6 +3497,10 @@ print_one_breakpoint (struct breakpoint 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, ""); @@ -3513,7 +3537,15 @@ print_one_breakpoint (struct breakpoint 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, "\tpending stop 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 */ @@ -3744,14 +3776,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->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 ", @@ -3840,6 +3872,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) @@ -3874,6 +3907,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) @@ -4050,6 +4084,7 @@ set_raw_breakpoint (struct symtab_and_li 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 @@ -4269,6 +4304,7 @@ disable_breakpoints_in_shlibs (int silen if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint)) && b->enable_state == bp_enabled && + !b->pending && !b->loc->duplicate && PC_SOLIB (b->loc->address)) { @@ -4288,23 +4324,123 @@ disable_breakpoints_in_shlibs (int silen } } +struct captured_parse_breakpoint_args + { + char **arg_p; + struct symtabs_and_lines *sals_p; + char ***addr_string_p; + int silent_flag; + }; + +/* Try and resolve a pending breakpoint. */ +static struct breakpoint * +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; + /* 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; + struct ui_file *old_gdb_stderr; + + 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; + parse_args.silent_flag = 1; + + old_gdb_stderr = gdb_stderr; + gdb_stderr = ui_file_new (); + + rc = catch_errors (do_captured_parse_breakpoint, &parse_args, + NULL, RETURN_MASK_ALL); + + ui_file_delete (gdb_stderr); + gdb_stderr = old_gdb_stderr; + + if (rc == GDB_RC_OK) + { + enum language old_language = current_language->la_language; + int old_input_radix = input_radix; + char *arg; + struct breakpoint *b1; + + 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); + b1 = breakpoint_chain; + while (b1->next) + b1 = b1->next; + /* If there is condition specified, it should be copied over. */ + if (b->cond_string) + { + arg = b->cond_string; + b1->cond_string = savestring (arg, strlen (arg)); + b1->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); + if (*arg) + error ("Junk at end of expression"); + } + /* If there are commands associated with the breakpoint, they should be copied too. */ + if (b->commands) + { + b1->commands = copy_command_lines (b->commands); + } + + set_language (old_language); + input_radix = old_input_radix; + return b1; /* Pending breakpoint resolved. */ + } + + /* Otherwise, we didn't successfully resolve pending breakpoint. */ + return NULL; +} + /* 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->enable_state == bp_shlib_disabled) - { - char buf[1], *lib; + { + 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) != NULL) + del_b = b; /* Mark pending breakpoint for deletion. */ + } + } - /* 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; - } + if (del_b) + delete_breakpoint (del_b); } #endif @@ -4323,7 +4459,7 @@ solib_load_unload_1 (char *hookname, int int thread = -1; /* All threads. */ /* Set a breakpoint on the specified hook. */ - sals = decode_line_1 (&hookname, 1, (struct symtab *) NULL, 0, &canonical); + sals = decode_line_1 (&hookname, 1, (struct symtab *) NULL, 0, &canonical, 0); addr_end = hookname; if (sals.nelts == 0) @@ -4491,7 +4627,7 @@ hw_watchpoint_used_count (enum bptype ty *other_type_used = 0; ALL_BREAKPOINTS (b) { - if (b->enable_state == bp_enabled) + if (b->enable_state == bp_enabled && !b->pending) { if (b->type == type) i++; @@ -4717,14 +4853,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)) @@ -4800,7 +4943,8 @@ create_breakpoints (struct symtabs_and_l static void parse_breakpoint_sals (char **address, struct symtabs_and_lines *sals, - char ***addr_string) + char ***addr_string, + int silent_flag) { char *addr_start = *address; *addr_string = NULL; @@ -4841,9 +4985,9 @@ 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); + default_breakpoint_line, addr_string, silent_flag); else - *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, addr_string); + *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, addr_string, silent_flag); } /* For any SAL that didn't have a canonical string, fill one in. */ if (sals->nelts > 0 && *addr_string == NULL) @@ -4897,6 +5041,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, args->silent_flag); + + 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. */ @@ -4907,14 +5061,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; @@ -4924,19 +5082,51 @@ 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; + parse_args.silent_flag = 0; + + rc = catch_errors (do_captured_parse_breakpoint, &parse_args, + NULL, RETURN_MASK_ALL); + + if (rc != GDB_RC_OK) + { + char *msg = error_last_message (); + /* Check for "Function xxx not defined" and "No source file xxx ..." messages. If + these are matched, allow breakpoint to be set pending on shared library loads. */ + if (!strncmp (msg, "Function ", sizeof ("Function ") - 1) || + !strncmp (msg, "No source file", sizeof ("No source file") - 1)) + { + if (!query ("Make breakpoint pending on future shared library load? ")) + 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 + return; + } + 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 *)); @@ -4963,62 +5153,87 @@ 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 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); } + else + { + struct symtab_and_line sal; + struct breakpoint *b; - create_breakpoints (sals, addr_string, cond, cond_string, - hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, - tempflag ? disp_del : disp_donttouch, - thread, ignore_count, from_tty); + 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->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."); @@ -5065,7 +5280,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; @@ -5289,7 +5504,7 @@ break_at_finish_command_1 (char *arg, in beg_addr_string = addr_string; sals = decode_line_1 (&addr_string, 1, (struct symtab *) NULL, 0, - (char ***) NULL); + (char ***) NULL, 0); xfree (beg_addr_string); old_chain = make_cleanup (xfree, sals.sals); @@ -5806,10 +6021,10 @@ until_break_command (char *arg, int from if (default_breakpoint_valid) sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, (char ***) NULL); + default_breakpoint_line, (char ***) NULL, 0); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, - 0, (char ***) NULL); + 0, (char ***) NULL, 0); if (sals.nelts != 1) error ("Couldn't get information on specified line."); @@ -6269,7 +6484,7 @@ handle_gnu_v3_exceptions (int tempflag, trigger_func_name = xstrdup ("__cxa_throw"); nameptr = trigger_func_name; - sals = decode_line_1 (&nameptr, 1, NULL, 0, NULL); + sals = decode_line_1 (&nameptr, 1, NULL, 0, NULL, 0); if (sals.nelts == 0) { xfree (trigger_func_name); @@ -6764,6 +6979,7 @@ delete_breakpoint (struct breakpoint *bp && !b->loc->duplicate && b->enable_state != bp_disabled && b->enable_state != bp_shlib_disabled + && !b->pending && b->enable_state != bp_call_disabled) { int val; @@ -6969,6 +7185,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; @@ -6976,7 +7196,7 @@ breakpoint_re_set_one (void *bint) set_language (b->language); input_radix = b->input_radix; s = b->addr_string; - sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL); + sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, 0); for (i = 0; i < sals.nelts; i++) { resolve_sal_pc (&sals.sals[i]); @@ -7063,7 +7283,7 @@ breakpoint_re_set_one (void *bint) value_free (b->val); b->val = evaluate_expression (b->exp); release_value (b->val); - if (VALUE_LAZY (b->val) && b->enable_state == bp_enabled) + if (VALUE_LAZY (b->val) && b->enable_state == bp_enabled && !b->pending) value_fetch_lazy (b->val); if (b->cond_string != NULL) @@ -7073,7 +7293,7 @@ breakpoint_re_set_one (void *bint) xfree (b->cond); b->cond = parse_exp_1 (&s, (struct block *) 0, 0); } - if (b->enable_state == bp_enabled) + if (b->enable_state == bp_enabled && !b->pending) mention (b); value_free_to_mark (mark); break; @@ -7364,70 +7584,92 @@ do_enable_breakpoint (struct breakpoint 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->exp_valid_block != NULL) - { - struct frame_info *fr = - fr = frame_find_by_id (bpt->watchpoint_frame); - if (fr == NULL) + if (bpt->pending) + { + if (bpt->enable_state != bp_enabled) + { + /* 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. */ + struct breakpoint *new_bp; + breakpoints_changed (); + if ((new_bp = resolve_pending_breakpoint (bpt)) != 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; + 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); @@ -7512,10 +7754,10 @@ decode_line_spec_1 (char *string, int fu sals = decode_line_1 (&string, funfirstline, default_breakpoint_symtab, default_breakpoint_line, - (char ***) NULL); + (char ***) NULL, 0); else sals = decode_line_1 (&string, funfirstline, - (struct symtab *) NULL, 0, (char ***) NULL); + (struct symtab *) NULL, 0, (char ***) NULL, 0); if (*string) error ("Junk at end of line specification: %s", string); return sals; 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 3 Dec 2003 01:21:50 -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,15 @@ struct breakpoint /* Methods associated with this breakpoint. */ struct breakpoint_ops *ops; + + /* Initial from_tty value. */ + int from_tty; + + /* Initial flag value. */ + int flag; + + /* Is breakpoint pending on shlib loads? */ + int pending; }; /* The following stuff is an abstract data type "bpstat" ("breakpoint Index: linespec.c =================================================================== RCS file: /cvs/src/src/gdb/linespec.c,v retrieving revision 1.52 diff -u -p -r1.52 linespec.c --- linespec.c 20 Oct 2003 14:38:42 -0000 1.52 +++ linespec.c 3 Dec 2003 01:21:52 -0000 @@ -100,7 +100,8 @@ static struct symtabs_and_lines decode_l int, int, char ***); static struct symtab *symtab_from_filename (char **argptr, - char *p, int is_quote_enclosed); + char *p, int is_quote_enclosed, + int silent_if_not_found); static struct symtabs_and_lines decode_all_digits (char **argptr, @@ -119,7 +120,8 @@ static struct symtabs_and_lines decode_d static struct symtabs_and_lines decode_variable (char *copy, int funfirstline, char ***canonical, - struct symtab *file_symtab); + struct symtab *file_symtab, + int silent_if_not_found); static struct symtabs_and_lines symbol_found (int funfirstline, @@ -637,7 +639,11 @@ decode_line_2 (struct symbol *sym_arr[], Note that it is possible to return zero for the symtab if no file is validly specified. Callers must check that. - Also, the line number returned may be invalid. */ + Also, the line number returned may be invalid. + + If the silent_if_not_found flag is set, then no error message is issued for + an unknown function or file. This is used when searching for locations in + shared libraries that may not be loaded yet. */ /* We allow single quotes in various places. This is a hideous kludge, which exists because the completer can't yet deal with the @@ -646,7 +652,7 @@ decode_line_2 (struct symbol *sym_arr[], struct symtabs_and_lines decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab, - int default_line, char ***canonical) + int default_line, char ***canonical, int silent_if_not_found) { char *p; char *q; @@ -722,7 +728,8 @@ decode_line_1 (char **argptr, int funfir /* No, the first part is a filename; set s to be that file's symtab. Also, move argptr past the filename. */ - file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed); + file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed, + silent_if_not_found); } #if 0 /* No one really seems to know why this was added. It certainly @@ -827,7 +834,8 @@ decode_line_1 (char **argptr, int funfir /* Look up that token as a variable. If file specified, use that file's per-file block to start with. */ - return decode_variable (copy, funfirstline, canonical, file_symtab); + return decode_variable (copy, funfirstline, canonical, + file_symtab, silent_if_not_found); } @@ -1422,10 +1430,13 @@ collect_methods (char *copy, struct type /* Return the symtab associated to the filename given by the substring - of *ARGPTR ending at P, and advance ARGPTR past that filename. */ + of *ARGPTR ending at P, and advance ARGPTR past that filename. The + silent_if_not_found flag is used to specify that if the filename is + not found, do not issue an error message. */ static struct symtab * -symtab_from_filename (char **argptr, char *p, int is_quote_enclosed) +symtab_from_filename (char **argptr, char *p, + int is_quote_enclosed, int silent_if_not_found) { char *p1; char *copy; @@ -1450,6 +1461,8 @@ symtab_from_filename (char **argptr, cha { if (!have_full_symbols () && !have_partial_symbols ()) error ("No symbol table is loaded. Use the \"file\" command."); + if (silent_if_not_found) + throw_exception (RETURN_ERROR); error ("No source file named %s.", copy); } @@ -1626,11 +1639,13 @@ decode_dollar (char *copy, int funfirstl /* Decode a linespec that's a variable. If FILE_SYMTAB is non-NULL, - look in that symtab's static variables first. */ + look in that symtab's static variables first. The silent_if_not_found + flag is used to specify that no error message should be issued if the + function is not found. */ static struct symtabs_and_lines decode_variable (char *copy, int funfirstline, char ***canonical, - struct symtab *file_symtab) + struct symtab *file_symtab, int silent_if_not_found) { struct symbol *sym; /* The symtab that SYM was found in. */ @@ -1658,6 +1673,9 @@ decode_variable (char *copy, int funfirs !have_partial_symbols () && !have_minimal_symbols ()) error ("No symbol table is loaded. Use the \"file\" command."); + if (silent_if_not_found) + throw_exception (RETURN_ERROR); + error ("Function \"%s\" not defined.", copy); } Index: linespec.h =================================================================== RCS file: /cvs/src/src/gdb/linespec.h,v retrieving revision 1.3 diff -u -p -r1.3 linespec.h --- linespec.h 12 Apr 2003 17:41:25 -0000 1.3 +++ linespec.h 3 Dec 2003 01:21:52 -0000 @@ -24,6 +24,7 @@ struct symtab; extern struct symtabs_and_lines decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab, int default_line, - char ***canonical); + char ***canonical, + int silent_if_not_found); #endif /* defined (LINESPEC_H) */ Index: symtab.c =================================================================== RCS file: /cvs/src/src/gdb/symtab.c,v retrieving revision 1.123 diff -u -p -r1.123 symtab.c --- symtab.c 22 Nov 2003 16:01:03 -0000 1.123 +++ symtab.c 3 Dec 2003 01:21:53 -0000 @@ -3868,7 +3868,7 @@ decode_line_spec (char *string, int funf sals = decode_line_1 (&string, funfirstline, cursal.symtab, cursal.line, - (char ***) NULL); + (char ***) NULL, 0); if (*string) error ("Junk at end of line specification: %s", string); Index: tracepoint.c =================================================================== RCS file: /cvs/src/src/gdb/tracepoint.c,v retrieving revision 1.54 diff -u -p -r1.54 tracepoint.c --- tracepoint.c 2 Oct 2003 20:28:30 -0000 1.54 +++ tracepoint.c 3 Dec 2003 01:21:53 -0000 @@ -392,7 +392,7 @@ trace_command (char *arg, int from_tty) printf_filtered ("TRACE %s\n", arg); addr_start = arg; - sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, &canonical); + sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, &canonical, 0); addr_end = arg; if (!sals.nelts) return; /* ??? Presumably decode_line_1 has already warned? */ @@ -2341,7 +2341,7 @@ scope_info (char *args, int from_tty) if (args == 0 || *args == 0) error ("requires an argument (function, line or *addr) to define a scope"); - sals = decode_line_1 (&args, 1, NULL, 0, &canonical); + sals = decode_line_1 (&args, 1, NULL, 0, &canonical, 0); if (sals.nelts == 0) return; /* presumably decode_line_1 has already warned */ Index: cli/cli-cmds.c =================================================================== RCS file: /cvs/src/src/gdb/cli/cli-cmds.c,v retrieving revision 1.36 diff -u -p -r1.36 cli-cmds.c --- cli/cli-cmds.c 8 Nov 2003 00:13:03 -0000 1.36 +++ cli/cli-cmds.c 3 Dec 2003 01:21:54 -0000 @@ -557,7 +557,7 @@ edit_command (char *arg, int from_tty) /* Now should only be one argument -- decode it in SAL */ arg1 = arg; - sals = decode_line_1 (&arg1, 0, 0, 0, 0); + sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0); if (! sals.nelts) return; /* C++ */ if (sals.nelts > 1) { @@ -681,7 +681,7 @@ list_command (char *arg, int from_tty) dummy_beg = 1; else { - sals = decode_line_1 (&arg1, 0, 0, 0, 0); + sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0); if (!sals.nelts) return; /* C++ */ @@ -714,9 +714,9 @@ list_command (char *arg, int from_tty) else { if (dummy_beg) - sals_end = decode_line_1 (&arg1, 0, 0, 0, 0); + sals_end = decode_line_1 (&arg1, 0, 0, 0, 0, 0); else - sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0); + sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0, 0); if (sals_end.nelts == 0) return; if (sals_end.nelts > 1)