X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fbreakpoint.c;h=018f464653177adc762117c1d3e9c63e0b0df2b6;hb=9cbc6ef04e5d04231f2ac1c4b7fd9848d9a2b3b0;hp=4ea0f676ff3cd801d5e03c844ab9f9719cd7f503;hpb=fad0733a64e6fe0c4931c183e5ca13631f9272d7;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 4ea0f676ff..018f464653 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 *); @@ -99,7 +99,8 @@ static void check_duplicates (struct breakpoint *); static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int); -static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr); +static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr, + enum bptype bptype); static void describe_other_breakpoints (CORE_ADDR, asection *); @@ -119,6 +120,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 @@ -210,6 +213,12 @@ static void ep_skip_leading_whitespace (char **s); if such is available. */ static int can_use_hw_watchpoints; +/* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints. + If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints + for unrecognized breakpoint locations. + If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */ +static enum auto_boolean pending_break_support; + void _initialize_breakpoint (void); extern int addressprint; /* Print machine addresses? */ @@ -257,13 +266,13 @@ int breakpoint_count; /* Pointer to current exception event record */ static struct exception_event_record *current_exception_event; -/* Indicator of whether exception catchpoints should be nuked - between runs of a program */ -int exception_catchpoints_are_fragile = 0; +/* Indicator of whether exception catchpoints should be nuked between + runs of a program. */ +int deprecated_exception_catchpoints_are_fragile = 0; /* Indicator of when exception catchpoints set-up should be - reinitialized -- e.g. when program is re-run */ -int exception_support_initialized = 0; + reinitialized -- e.g. when program is re-run. */ +int deprecated_exception_support_initialized = 0; /* This function returns a pointer to the string representation of the pathname of the dynamically-linked library that has just been @@ -322,7 +331,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 +565,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); @@ -734,6 +746,23 @@ insert_catchpoint (struct ui_out *uo, void *args) return 0; } +/* Helper routine: free the value chain for a breakpoint (watchpoint). */ + +static void free_valchain (struct bp_location *b) +{ + struct value *v; + struct value *n; + + /* Free the saved value chain. We will construct a new one + the next time the watchpoint is inserted. */ + for (v = b->owner->val_chain; v; v = n) + { + n = v->next; + value_free (v); + } + b->owner->val_chain = NULL; +} + /* Insert a low-level "breakpoint" of some type. BPT is the breakpoint. Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS, PROCESS_WARNING, and HW_BREAKPOINT_ERROR are used to report problems. @@ -881,18 +910,17 @@ insert_bp_location (struct bp_location *bpt, must watch. As soon as a many-to-one mapping is available I'll convert this. */ - struct frame_info *saved_frame; - int saved_level, within_current_scope; + int within_current_scope; struct value *mark = value_mark (); struct value *v; + struct frame_id saved_frame_id; - /* Save the current frame and level so we can restore it after + /* Save the current frame's ID so we can restore it after evaluating the watchpoint expression on its own frame. */ /* FIXME drow/2003-09-09: It would be nice if evaluate_expression took a frame parameter, so that we didn't have to change the selected frame. */ - saved_frame = deprecated_selected_frame; - saved_level = frame_relative_level (deprecated_selected_frame); + saved_frame_id = get_frame_id (deprecated_selected_frame); /* Determine if the watchpoint is within scope. */ if (bpt->owner->exp_valid_block == NULL) @@ -908,6 +936,8 @@ insert_bp_location (struct bp_location *bpt, if (within_current_scope) { + free_valchain (bpt); + /* Evaluate the expression and cut the chain of values produced off from the value chain. @@ -987,10 +1017,8 @@ insert_bp_location (struct bp_location *bpt, bpt->owner->disposition = disp_del_at_next_stop; } - /* Restore the frame and level. */ - if (saved_frame != deprecated_selected_frame - || saved_level != frame_relative_level (deprecated_selected_frame)) - select_frame (saved_frame); + /* Restore the selected frame. */ + select_frame (frame_find_by_id (saved_frame_id)); return val; } @@ -1493,15 +1521,6 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is) if ((is == mark_uninserted) && (b->inserted)) warning ("Could not remove hardware watchpoint %d.", b->owner->number); - - /* Free the saved value chain. We will construct a new one - the next time the watchpoint is inserted. */ - for (v = b->owner->val_chain; v; v = n) - { - n = v->next; - value_free (v); - } - b->owner->val_chain = NULL; } else if ((b->owner->type == bp_catch_fork || b->owner->type == bp_catch_vfork || @@ -1624,8 +1643,8 @@ breakpoint_init_inferior (enum inf_context context) default: /* Likewise for exception catchpoints in dynamic-linked executables where required */ - if (ep_is_exception_catchpoint (b) && - exception_catchpoints_are_fragile) + if (ep_is_exception_catchpoint (b) + && deprecated_exception_catchpoints_are_fragile) { warning_needed = 1; delete_breakpoint (b); @@ -1634,8 +1653,8 @@ breakpoint_init_inferior (enum inf_context context) } } - if (exception_catchpoints_are_fragile) - exception_support_initialized = 0; + if (deprecated_exception_catchpoints_are_fragile) + deprecated_exception_support_initialized = 0; /* Don't issue the warning unless it's really needed... */ if (warning_needed && (context != inf_exited)) @@ -1717,34 +1736,34 @@ breakpoint_inserted_here_p (CORE_ADDR pc) return 0; } -/* Return nonzero if FRAME is a dummy frame. We can't use - DEPRECATED_PC_IN_CALL_DUMMY because figuring out the saved SP would - take too much time, at least using frame_register() on the 68k. - This means that for this function to work right a port must use the - bp_call_dummy breakpoint. */ +/* This function returns non-zero iff there is a software breakpoint + inserted at PC. */ int -deprecated_frame_in_dummy (struct frame_info *frame) +software_breakpoint_inserted_here_p (CORE_ADDR pc) { - struct breakpoint *b; + struct bp_location *bpt; + int any_breakpoint_here = 0; - /* This function is used by two files: get_frame_type(), after first - checking that !DEPRECATED_USE_GENERIC_DUMMY_FRAMES; and - sparc-tdep.c, which doesn't yet use generic dummy frames anyway. */ - gdb_assert (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES); + ALL_BP_LOCATIONS (bpt) + { + if (bpt->loc_type != bp_loc_software_breakpoint) + continue; + + if ((breakpoint_enabled (bpt->owner) + || bpt->owner->enable_state == bp_permanent) + && bpt->inserted + && bpt->address == pc) /* bp is enabled and matches pc */ + { + if (overlay_debugging + && section_is_overlay (bpt->section) + && !section_is_mapped (bpt->section)) + continue; /* unmapped overlay -- can't be a match */ + else + return 1; + } + } - ALL_BREAKPOINTS (b) - { - if (b->type == bp_call_dummy - && frame_id_eq (b->frame_id, get_frame_id (frame)) - /* We need to check the PC as well as the frame on the sparc, - for signals.exp in the testsuite. */ - && (get_frame_pc (frame) - >= (b->loc->address - - DEPRECATED_SIZEOF_CALL_DUMMY_WORDS / sizeof (LONGEST) * DEPRECATED_REGISTER_SIZE)) - && get_frame_pc (frame) <= b->loc->address) - return 1; - } return 0; } @@ -2539,11 +2558,10 @@ which its expression is valid.\n"); } } -/* Get a bpstat associated with having just stopped at address *PC - and frame address CORE_ADDRESS. Update *PC to point at the - breakpoint (if we hit a breakpoint). NOT_A_SW_BREAKPOINT is nonzero - if this is known to not be a real breakpoint (it could still be a - watchpoint, though). */ +/* Get a bpstat associated with having just stopped at address + BP_ADDR in thread PTID. STOPPED_BY_WATCHPOINT is 1 if the + target thinks we stopped due to a hardware watchpoint, 0 if we + know we did not trigger a hardware watchpoint, and -1 if we do not know. */ /* Determine whether we stopped at a breakpoint, etc, or whether we don't understand this stop. Result is a chain of bpstat's such that: @@ -2560,24 +2578,16 @@ which its expression is valid.\n"); commands, FIXME??? fields. */ bpstat -bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint) +bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid, int stopped_by_watchpoint) { struct breakpoint *b, *temp; - CORE_ADDR bp_addr; /* True if we've hit a breakpoint (as opposed to a watchpoint). */ int real_breakpoint = 0; /* Root of the chain of bpstat's */ struct bpstats root_bs[1]; /* Pointer to the last thing in the chain currently. */ bpstat bs = root_bs; - - /* Get the address where the breakpoint would have been. The - "not_a_sw_breakpoint" argument is meant to distinguish between a - breakpoint trap event and a trace/singlestep trap event. For a - trace/singlestep trap event, we would not want to subtract - DECR_PC_AFTER_BREAK from the PC. */ - - bp_addr = *pc - (not_a_sw_breakpoint ? 0 : DECR_PC_AFTER_BREAK); + int thread_id = pid_to_thread_id (ptid); ALL_BREAKPOINTS_SAFE (b, temp) { @@ -2603,9 +2613,21 @@ bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint) continue; } + /* Continuable hardware watchpoints are treated as non-existent if the + reason we stopped wasn't a hardware watchpoint (we didn't stop on + some data address). Otherwise gdb won't stop on a break instruction + in the code (not from a breakpoint) when a hardware watchpoint has + been defined. */ + + if ((b->type == bp_hardware_watchpoint + || b->type == bp_read_watchpoint + || b->type == bp_access_watchpoint) + && !stopped_by_watchpoint) + continue; + if (b->type == bp_hardware_breakpoint) { - if (b->loc->address != *pc) + if (b->loc->address != bp_addr) continue; if (overlay_debugging /* unmapped overlay section */ && section_is_overlay (b->loc->section) @@ -2831,6 +2853,12 @@ bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint) /* Don't consider this a hit. */ --(b->hit_count); } + else if (b->thread != -1 && b->thread != thread_id) + { + bs->stop = 0; + /* Don't consider this a hit. */ + --(b->hit_count); + } else if (b->ignore_count > 0) { b->ignore_count--; @@ -2863,18 +2891,6 @@ bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint) bs->next = NULL; /* Terminate the chain */ bs = root_bs->next; /* Re-grab the head of the chain */ - if (real_breakpoint && bs) - { - if (bs->breakpoint_at->type != bp_hardware_breakpoint) - { - if (DECR_PC_AFTER_BREAK != 0) - { - *pc = bp_addr; - write_pc (bp_addr); - } - } - } - /* The value of a hardware watchpoint hasn't changed, but the intermediate memory locations we are watching may have. */ if (bs && !bs->stop && @@ -2991,7 +3007,7 @@ bpstat_what (bpstat bs) /* step_resume entries: a step resume breakpoint overrides another breakpoint of signal handling (see comment in wait_for_inferior - at first PC_IN_SIGTRAMP where we set the step_resume breakpoint). */ + at where we set the step_resume breakpoint). */ /* We handle the through_sigtramp_breakpoint the same way; having both one of those and a step_resume_breakpoint is probably very rare (?). */ @@ -3451,7 +3467,10 @@ 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", ""); + else + ui_out_field_core_addr (uiout, "addr", b->loc->address); } annotate_field (5); *last_addr = b->loc->address; @@ -3470,6 +3489,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, ""); @@ -3506,7 +3529,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 */ @@ -3737,14 +3768,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 ", @@ -3833,6 +3864,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) @@ -3867,6 +3899,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) @@ -3905,13 +3938,25 @@ breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr, this function is simply the identity function. */ static CORE_ADDR -adjust_breakpoint_address (CORE_ADDR bpaddr) +adjust_breakpoint_address (CORE_ADDR bpaddr, enum bptype bptype) { if (!gdbarch_adjust_breakpoint_address_p (current_gdbarch)) { /* Very few targets need any kind of breakpoint adjustment. */ return bpaddr; } + else if (bptype == bp_watchpoint + || bptype == bp_hardware_watchpoint + || bptype == bp_read_watchpoint + || bptype == bp_access_watchpoint + || bptype == bp_catch_fork + || bptype == bp_catch_vfork + || bptype == bp_catch_exec) + { + /* Watchpoints and the various bp_catch_* eventpoints should not + have their addresses modified. */ + return bpaddr; + } else { CORE_ADDR adjusted_bpaddr; @@ -4020,7 +4065,8 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype) memset (b, 0, sizeof (*b)); b->loc = allocate_bp_location (b, bptype); b->loc->requested_address = sal.pc; - b->loc->address = adjust_breakpoint_address (b->loc->requested_address); + b->loc->address = adjust_breakpoint_address (b->loc->requested_address, + bptype); if (sal.symtab == NULL) b->source_file = NULL; else @@ -4043,6 +4089,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 @@ -4211,7 +4258,7 @@ create_thread_event_breakpoint (CORE_ADDR address) b->enable_state = bp_enabled; /* addr_string has to be used or breakpoint_re_set will delete me. */ - xasprintf (&b->addr_string, "*0x%s", paddr (b->loc->address)); + b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address)); return b; } @@ -4226,6 +4273,66 @@ remove_thread_event_breakpoints (void) delete_breakpoint (b); } +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; +} + #ifdef SOLIB_ADD void remove_solib_event_breakpoints (void) @@ -4285,19 +4392,26 @@ disable_breakpoints_in_shlibs (int silent) 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 @@ -4512,7 +4626,8 @@ set_longjmp_resume_breakpoint (CORE_ADDR pc, struct frame_id frame_id) if (b->type == bp_longjmp_resume) { b->loc->requested_address = pc; - b->loc->address = adjust_breakpoint_address (b->loc->requested_address); + b->loc->address = adjust_breakpoint_address (b->loc->requested_address, + b->type); b->enable_state = bp_enabled; b->frame_id = frame_id; check_duplicates (b); @@ -4597,13 +4712,13 @@ mention (struct breakpoint *b) stb = ui_out_stream_new (uiout); old_chain = make_cleanup_ui_out_stream_delete (stb); - /* FIXME: This is misplaced; mention() is called by things (like hitting a - watchpoint) other than breakpoint creation. It should be possible to - clean this up and at the same time replace the random calls to - breakpoint_changed with this hook, as has already been done for - delete_breakpoint_hook and so on. */ - if (create_breakpoint_hook) - create_breakpoint_hook (b); + /* FIXME: This is misplaced; mention() is called by things (like + hitting a watchpoint) other than breakpoint creation. It should + be possible to clean this up and at the same time replace the + random calls to breakpoint_changed with this hook, as has already + been done for deprecated_delete_breakpoint_hook and so on. */ + if (deprecated_create_breakpoint_hook) + deprecated_create_breakpoint_hook (b); breakpoint_create_event (b->number); if (b->ops != NULL && b->ops->print_mention != NULL) @@ -4709,14 +4824,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)) @@ -4729,6 +4851,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 @@ -4739,7 +4866,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) { @@ -4774,11 +4902,35 @@ create_breakpoints (struct symtabs_and_lines sals, char **addr_string, else /* addr_string has to be used or breakpoint_re_set will delete me. */ - xasprintf (&b->addr_string, "*0x%s", paddr (b->loc->address)); + b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address)); b->cond_string = cond_string[i]; 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); + + /* We have to copy over the ignore_count and thread as well. */ + b->ignore_count = pending_bp->ignore_count; + b->thread = pending_bp->thread; + } mention (b); } } @@ -4792,7 +4944,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; @@ -4833,9 +4986,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) @@ -4878,7 +5033,8 @@ breakpoint_sals_to_pc (struct symtabs_and_lines *sals, Give the target a chance to bless sals.sals[i].pc before we try to make a breakpoint for it. */ - if (PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc)) +#ifdef DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE + if (DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc)) { if (address == NULL) error ("Cannot break without a running program."); @@ -4886,29 +5042,48 @@ breakpoint_sals_to_pc (struct symtabs_and_lines *sals, error ("Cannot break on %s without a running program.", address); } +#endif } } +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; @@ -4916,19 +5091,69 @@ 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 pending breakpoint support is turned off, throw error. */ + + if (pending_break_support == AUTO_BOOLEAN_FALSE) + throw_exception (RETURN_ERROR); + + /* If pending breakpoint support is auto query and the user selects + no, then simply return the error code. */ + if (pending_break_support == AUTO_BOOLEAN_AUTO && + !nquery ("Make breakpoint pending on future shared library load? ")) + return rc; + + /* At this point, either the user was queried about setting a + pending breakpoint and selected yes, or pending breakpoint + behavior is on and thus a pending breakpoint is defaulted + on behalf of the user. */ + 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 *)); @@ -4955,62 +5180,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."); @@ -5021,6 +5278,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, @@ -5057,7 +5316,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; @@ -5121,7 +5380,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. */ @@ -5213,7 +5473,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 @@ -5296,7 +5556,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 @@ -5363,7 +5623,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 @@ -5381,7 +5641,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 @@ -5393,13 +5653,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 @@ -5440,7 +5700,7 @@ stopin_command (char *arg, int from_tty) if (badInput) printf_filtered ("Usage: stop in \n"); else - break_command_1 (arg, 0, from_tty); + break_command_1 (arg, 0, from_tty, NULL); } static void @@ -5472,7 +5732,7 @@ stopat_command (char *arg, int from_tty) if (badInput) printf_filtered ("Usage: stop at \n"); else - break_command_1 (arg, 0, from_tty); + break_command_1 (arg, 0, from_tty, NULL); } /* accessflag: hw_write: watch write, @@ -5630,7 +5890,8 @@ watch_command_1 (char *arg, int accessflag, int from_tty) scope_breakpoint->loc->requested_address = get_frame_pc (prev_frame); scope_breakpoint->loc->address - = adjust_breakpoint_address (scope_breakpoint->loc->requested_address); + = adjust_breakpoint_address (scope_breakpoint->loc->requested_address, + scope_breakpoint->type); /* The scope breakpoint is related to the watchpoint. We will need to act on them together. */ @@ -5645,11 +5906,6 @@ watch_command_1 (char *arg, int accessflag, int from_tty) in hardware. If the watchpoint can not be handled in hardware return zero. */ -#if !defined(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT) -#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(BYTE_SIZE) \ - ((BYTE_SIZE) <= (DEPRECATED_REGISTER_SIZE)) -#endif - #if !defined(TARGET_REGION_OK_FOR_HW_WATCHPOINT) #define TARGET_REGION_OK_FOR_HW_WATCHPOINT(ADDR,LEN) \ (TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(LEN)) @@ -6613,13 +6869,15 @@ delete_breakpoint (struct breakpoint *bpt) if (bpt->type == bp_none) return; - if (delete_breakpoint_hook) - delete_breakpoint_hook (bpt); + if (deprecated_delete_breakpoint_hook) + deprecated_delete_breakpoint_hook (bpt); breakpoint_delete_event (bpt->number); if (bpt->loc->inserted) remove_breakpoint (bpt->loc, mark_inserted); + free_valchain (bpt->loc); + if (breakpoint_chain == bpt) breakpoint_chain = bpt->next; @@ -6679,6 +6937,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; @@ -6884,6 +7143,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; @@ -6936,7 +7199,8 @@ breakpoint_re_set_one (void *bint) b->line_number = sals.sals[i].line; b->loc->requested_address = sals.sals[i].pc; b->loc->address - = adjust_breakpoint_address (b->loc->requested_address); + = adjust_breakpoint_address (b->loc->requested_address, + b->type); /* Used to check for duplicates here, but that can cause trouble, as it doesn't check for disabled @@ -7240,8 +7504,8 @@ disable_breakpoint (struct breakpoint *bpt) check_duplicates (bpt); - if (modify_breakpoint_hook) - modify_breakpoint_hook (bpt); + if (deprecated_modify_breakpoint_hook) + deprecated_modify_breakpoint_hook (bpt); breakpoint_modify_event (bpt->number); } @@ -7281,8 +7545,6 @@ disable_command (char *args, int from_tty) static void do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition) { - struct frame_info *save_selected_frame = NULL; - int save_selected_frame_level = -1; int target_resources_ok, other_type_used; struct value *mark; @@ -7299,72 +7561,92 @@ 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) + struct frame_id saved_frame_id; + + saved_frame_id = get_frame_id (get_selected_frame ()); + if (bpt->exp_valid_block != NULL) { - printf_filtered ("\ + 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; + } + 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) + { + 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; + } } + + select_frame (frame_find_by_id (saved_frame_id)); + 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); + + if (deprecated_modify_breakpoint_hook) + deprecated_modify_breakpoint_hook (bpt); breakpoint_modify_event (bpt->number); } @@ -7435,6 +7717,16 @@ enable_delete_command (char *args, int from_tty) map_breakpoint_numbers (args, enable_delete_breakpoint); } +static void +set_breakpoint_cmd (char *args, int from_tty) +{ +} + +static void +show_breakpoint_cmd (char *args, int from_tty) +{ +} + /* Use default_breakpoint_'s, or nothing if they aren't valid. */ struct symtabs_and_lines @@ -7459,6 +7751,8 @@ decode_line_spec_1 (char *string, int funfirstline) void _initialize_breakpoint (void) { + static struct cmd_list_element *breakpoint_set_cmdlist; + static struct cmd_list_element *breakpoint_show_cmdlist; struct cmd_list_element *c; breakpoint_chain = 0; @@ -7777,4 +8071,34 @@ hardware.)", add_show_from_set (c, &showlist); can_use_hw_watchpoints = 1; + + add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, "\ +Breakpoint specific settings\n\ +Configure various breakpoint-specific variables such as\n\ +pending breakpoint behavior", + &breakpoint_set_cmdlist, "set breakpoint ", + 0/*allow-unknown*/, &setlist); + add_prefix_cmd ("breakpoint", class_maintenance, show_breakpoint_cmd, "\ +Breakpoint specific settings\n\ +Configure various breakpoint-specific variables such as\n\ +pending breakpoint behavior", + &breakpoint_show_cmdlist, "show breakpoint ", + 0/*allow-unknown*/, &showlist); + + add_setshow_auto_boolean_cmd ("pending", no_class, &pending_break_support, "\ +Set debugger's behavior regarding pending breakpoints.\n\ +If on, an unrecognized breakpoint location will cause gdb to create a\n\ +pending breakpoint. If off, an unrecognized breakpoint location results in\n\ +an error. If auto, an unrecognized breakpoint location results in a\n\ +user-query to see if a pending breakpoint should be created.","\ +Show debugger's behavior regarding pending breakpoints.\n\ +If on, an unrecognized breakpoint location will cause gdb to create a\n\ +pending breakpoint. If off, an unrecognized breakpoint location results in\n\ +an error. If auto, an unrecognized breakpoint location results in a\n\ +user-query to see if a pending breakpoint should be created.", + NULL, NULL, + &breakpoint_set_cmdlist, + &breakpoint_show_cmdlist); + + pending_break_support = AUTO_BOOLEAN_AUTO; }