X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fbreakpoint.c;h=2db375340eb137dba18c07a92fc53ee9d945bace;hb=cf3e377e61e7861677252feb4d06ba8fcea1e5c1;hp=05e787e6167446ccbd5fa88ed5ef247cb52e179e;hpb=cabd4da684520537eb21d0d0af95cf5ba3efff30;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 05e787e616..2db375340e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -347,7 +347,11 @@ read_memory_nobpt (memaddr, myaddr, len) struct breakpoint *b; if (memory_breakpoint_size < 0) - /* No breakpoints on this machine. */ + /* No breakpoints on this machine. FIXME: This should be + dependent on the debugging target. Probably want + target_insert_breakpoint to return a size, saying how many + bytes of the shadow contents are used, or perhaps have + something like target_xfer_shadow. */ return target_read_memory (memaddr, myaddr, len); ALL_BREAKPOINTS (b) @@ -490,19 +494,18 @@ remove_breakpoints () b->inserted = 0; #ifdef BREAKPOINT_DEBUG printf ("Removed breakpoint at %s", - local_hex_string(b->address)); + local_hex_string((unsigned long) b->address)); printf (", shadow %s", - local_hex_string(b->shadow_contents[0])); + local_hex_string((unsigned long) b->shadow_contents[0])); printf (", %s.\n", - local_hex_string(b->shadow_contents[1])); + local_hex_string((unsigned long) b->shadow_contents[1])); #endif /* BREAKPOINT_DEBUG */ } return 0; } -/* Clear the "inserted" flag in all breakpoints. - This is done when the inferior is loaded. */ +/* Clear the "inserted" flag in all breakpoints. */ void mark_breakpoints_out () @@ -513,6 +516,26 @@ mark_breakpoints_out () b->inserted = 0; } +/* Clear the "inserted" flag in all breakpoints and delete any breakpoints + which should go away between runs of the program. */ + +void +breakpoint_init_inferior () +{ + register struct breakpoint *b, *temp; + + ALL_BREAKPOINTS_SAFE (b, temp) + { + b->inserted = 0; + + /* If the call dummy breakpoint is at the entry point it will + cause problems when the inferior is rerun, so we better + get rid of it. */ + if (b->type == bp_call_dummy) + delete_breakpoint (b); + } +} + /* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at PC. When continuing from a location with a breakpoint, we actually single step once before calling insert_breakpoints. */ @@ -566,7 +589,7 @@ bpstat_copy (bs) { bpstat p = NULL; bpstat tmp; - bpstat retval; + bpstat retval = NULL; if (bs == NULL) return bs; @@ -790,6 +813,121 @@ bpstat_alloc (b, cbs) bs->print_it = print_it_normal; return bs; } + +/* Return the frame which we can use to evaluate the expression + whose valid block is valid_block, or NULL if not in scope. + + This whole concept is probably not the way to do things (it is incredibly + slow being the main reason, not to mention fragile (e.g. the sparc + frame pointer being fetched as 0 bug causes it to stop)). Instead, + introduce a version of "struct frame" which survives over calls to the + inferior, but which is better than FRAME_ADDR in the sense that it lets + us evaluate expressions relative to that frame (on some machines, it + can just be a FRAME_ADDR). Save one of those instead of (or in addition + to) the exp_valid_block, and then use it to evaluate the watchpoint + expression, with no need to do all this backtracing every time. + + Or better yet, what if it just copied the struct frame and its next + frame? Off the top of my head, I would think that would work + because things like (a29k) rsize and msize, or (sparc) bottom just + depend on the frame, and aren't going to be different just because + the inferior has done something. Trying to recalculate them + strikes me as a lot of work, possibly even impossible. Saving the + next frame is needed at least on a29k, where get_saved_register + uses fi->next->saved_msp. For figuring out whether that frame is + still on the stack, I guess this needs to be machine-specific (e.g. + a29k) but I think + + read_fp () INNER_THAN watchpoint_frame->frame + + would generally work. + + Of course the scope of the expression could be less than a whole + function; perhaps if the innermost frame is the one which the + watchpoint is relative to (another machine-specific thing, usually + + FRAMELESS_FUNCTION_INVOCATION (get_current_frame(), fromleaf) + read_fp () == wp_frame->frame + && !fromleaf + + ), *then* it could do a + + contained_in (get_current_block (), wp->exp_valid_block). + + */ + +FRAME +within_scope (valid_block) + struct block *valid_block; +{ + FRAME fr = get_current_frame (); + struct frame_info *fi = get_frame_info (fr); + CORE_ADDR func_start; + + /* If caller_pc_valid is true, we are stepping through + a function prologue, which is bounded by callee_func_start + (inclusive) and callee_prologue_end (exclusive). + caller_pc is the pc of the caller. + + Yes, this is hairy. */ + static int caller_pc_valid = 0; + static CORE_ADDR caller_pc; + static CORE_ADDR callee_func_start; + static CORE_ADDR callee_prologue_end; + + find_pc_partial_function (fi->pc, (PTR)NULL, &func_start, (CORE_ADDR *)NULL); + func_start += FUNCTION_START_OFFSET; + if (fi->pc == func_start) + { + /* We just called a function. The only other case I + can think of where the pc would equal the pc of the + start of a function is a frameless function (i.e. + no prologue) where we branch back to the start + of the function. In that case, SKIP_PROLOGUE won't + find one, and we'll clear caller_pc_valid a few lines + down. */ + caller_pc_valid = 1; + caller_pc = SAVED_PC_AFTER_CALL (fr); + callee_func_start = func_start; + SKIP_PROLOGUE (func_start); + callee_prologue_end = func_start; + } + if (caller_pc_valid) + { + if (fi->pc < callee_func_start + || fi->pc >= callee_prologue_end) + caller_pc_valid = 0; + } + + if (contained_in (block_for_pc (caller_pc_valid + ? caller_pc + : fi->pc), + valid_block)) + { + return fr; + } + fr = get_prev_frame (fr); + + /* If any active frame is in the exp_valid_block, then it's + OK. Note that this might not be the same invocation of + the exp_valid_block that we were watching a little while + ago, or the same one as when the watchpoint was set (e.g. + we are watching a local variable in a recursive function. + When we return from a recursive invocation, then we are + suddenly watching a different instance of the variable). + + At least for now I am going to consider this a feature. */ + for (; fr != NULL; fr = get_prev_frame (fr)) + { + fi = get_frame_info (fr); + if (contained_in (block_for_pc (fi->pc), + valid_block)) + { + return fr; + } + } + return NULL; +} /* Possible return values for watchpoint_check (this can't be an enum because of check_errors). */ @@ -803,23 +941,31 @@ bpstat_alloc (b, cbs) /* Check watchpoint condition. */ static int watchpoint_check (p) - PTR p; + char *p; { bpstat bs = (bpstat) p; + FRAME fr; int within_current_scope; - if (bs->breakpoint_at->exp_valid_block != NULL) - within_current_scope = - contained_in (get_selected_block (), bs->breakpoint_at->exp_valid_block); - else + if (bs->breakpoint_at->exp_valid_block == NULL) within_current_scope = 1; - + else + { + fr = within_scope (bs->breakpoint_at->exp_valid_block); + within_current_scope = fr != NULL; + if (within_current_scope) + /* If we end up stopping, the current frame will get selected + in normal_stop. So this call to select_frame won't affect + the user. */ + select_frame (fr, -1); + } + if (within_current_scope) { /* We use value_{,free_to_}mark because it could be a *long* time before we return to the command level and - call free_all_values. */ - /* But couldn't we just call free_all_values instead? */ + call free_all_values. We can't call free_all_values because + we might be in the middle of evaluating a function call. */ value mark = value_mark (); value new_val = evaluate_expression (bs->breakpoint_at->exp); @@ -876,14 +1022,18 @@ print_it_noop (bs) return -1; } +/* Get a bpstat associated with having just stopped at address *PC + and frame address FRAME_ADDRESS. Update *PC to point at the + breakpoint (if we hit a breakpoint). NOT_A_BREAKPOINT is nonzero + if this is known to not be a real breakpoint (it could still be a + watchpoint, though). */ + /* 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: if we don't understand the stop, the result is a null pointer. - if we understand why we stopped, the result is not null, and - the first element of the chain contains summary "stop" and - "print" flags for the whole chain. + if we understand why we stopped, the result is not null. Each element of the chain refers to a particular breakpoint or watchpoint at which we have stopped. (We may have stopped for @@ -894,11 +1044,11 @@ print_it_noop (bs) */ - bpstat -bpstat_stop_status (pc, frame_address) +bpstat_stop_status (pc, frame_address, not_a_breakpoint) CORE_ADDR *pc; FRAME_ADDR frame_address; + int not_a_breakpoint; { register struct breakpoint *b; CORE_ADDR bp_addr; @@ -922,6 +1072,9 @@ bpstat_stop_status (pc, frame_address) if (b->type != bp_watchpoint && b->address != bp_addr) continue; + if (b->type != bp_watchpoint && not_a_breakpoint) + continue; + /* Come here if it's a watchpoint, or if the break address matches */ bs = bpstat_alloc (b, bs); /* Alloc a bpstat to explain stop */ @@ -935,7 +1088,8 @@ bpstat_stop_status (pc, frame_address) "Error evaluating expression for watchpoint %d\n"; char message[sizeof (message1) + 30 /* slop */]; sprintf (message, message1, b->number); - switch (catch_errors (watchpoint_check, (char *) bs, message)) + switch (catch_errors (watchpoint_check, (char *) bs, message, + RETURN_MASK_ALL)) { case WP_DISABLED: /* We've already printed what needs to be printed. */ @@ -972,7 +1126,7 @@ bpstat_stop_status (pc, frame_address) bs->stop = 0; else { - int value_is_zero; + int value_is_zero = 0; if (b->cond) { @@ -981,7 +1135,8 @@ bpstat_stop_status (pc, frame_address) select_frame (get_current_frame (), 0); value_is_zero = catch_errors (breakpoint_cond_eval, (char *)(b->cond), - "Error in testing breakpoint condition:\n"); + "Error in testing breakpoint condition:\n", + RETURN_MASK_ALL); /* FIXME-someday, should give breakpoint # */ free_all_values (); } @@ -1023,15 +1178,7 @@ bpstat_stop_status (pc, frame_address) { *pc = bp_addr; #if defined (SHIFT_INST_REGS) - { - CORE_ADDR pc = read_register (PC_REGNUM); - CORE_ADDR npc = read_register (NPC_REGNUM); - if (pc != npc) - { - write_register (NNPC_REGNUM, npc); - write_register (NPC_REGNUM, pc); - } - } + SHIFT_INST_REGS(); #else /* No SHIFT_INST_REGS. */ write_pc (bp_addr); #endif /* No SHIFT_INST_REGS. */ @@ -1042,14 +1189,14 @@ bpstat_stop_status (pc, frame_address) } /* Tell what to do about this bpstat. */ -enum bpstat_what +struct bpstat_what bpstat_what (bs) bpstat bs; { /* Classify each bpstat as one of the following. */ enum class { - /* There was a watchpoint, but we're not stopping. */ - wp_nostop = 0, + /* This bpstat element has no effect on the main_action. */ + no_effect = 0, /* There was a watchpoint, stop but don't print. */ wp_silent, @@ -1092,13 +1239,19 @@ bpstat_what (bs) #define err BPSTAT_WHAT_STOP_NOISY /* Given an old action and a class, come up with a new action. */ - static const enum bpstat_what + /* One interesting property of this table is that wp_silent is the same + as bp_silent and wp_noisy is the same as bp_noisy. That is because + after stopping, the check for whether to step over a breakpoint + (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without + reference to how we stopped. We retain separate wp_silent and bp_silent + codes in case we want to change that someday. */ + static const enum bpstat_what_main_action table[(int)class_last][(int)BPSTAT_WHAT_LAST] = { /* old action */ /* keep_c stop_s stop_n single setlr clrlr clrlrs */ -/*wp_nostop*/ {keep_c, stop_s, stop_n, single, setlr , clrlr , clrlrs}, +/*no_effect*/ {keep_c, stop_s, stop_n, single, setlr , clrlr , clrlrs}, /*wp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s}, /*wp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n}, /*bp_nostop*/ {single, stop_s, stop_n, single, setlr , clrlrs, clrlrs}, @@ -1115,11 +1268,14 @@ bpstat_what (bs) #undef clrlr #undef clrlrs #undef err - enum bpstat_what current_action = BPSTAT_WHAT_KEEP_CHECKING; + enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING; + struct bpstat_what retval; + retval.call_dummy = 0; + retval.step_resume = 0; for (; bs != NULL; bs = bs->next) { - enum class bs_class; + enum class bs_class = no_effect; if (bs->breakpoint_at == NULL) /* I suspect this can happen if it was a momentary breakpoint which has since been deleted. */ @@ -1148,7 +1304,9 @@ bpstat_what (bs) bs_class = wp_silent; } else - bs_class = wp_nostop; + /* There was a watchpoint, but we're not stopping. This requires + no further action. */ + bs_class = no_effect; break; case bp_longjmp: bs_class = long_jump; @@ -1156,10 +1314,36 @@ bpstat_what (bs) case bp_longjmp_resume: bs_class = long_resume; break; + case bp_step_resume: +#if 0 + /* Need to temporarily disable this until we can fix the bug + with nexting over a breakpoint with ->stop clear causing + an infinite loop. For now, treat the breakpoint as having + been hit even if the frame is wrong. */ + if (bs->stop) + { +#endif + retval.step_resume = 1; + /* We don't handle this via the main_action. */ + bs_class = no_effect; +#if 0 + } + else + /* It is for the wrong frame. */ + bs_class = bp_nostop; +#endif + break; + case bp_call_dummy: + /* Make sure the action is stop (silent or noisy), so infrun.c + pops the dummy frame. */ + bs_class = bp_silent; + retval.call_dummy = 1; + break; } current_action = table[(int)bs_class][(int)current_action]; } - return current_action; + retval.main_action = current_action; + return retval; } /* Nonzero if we should step constantly (e.g. watchpoints on machines @@ -1191,16 +1375,12 @@ breakpoint_1 (bnum, allflag) CORE_ADDR last_addr = (CORE_ADDR)-1; int found_a_breakpoint = 0; static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint", - "longjmp", "longjmp resume"}; + "longjmp", "longjmp resume", "step resume", + "call dummy" }; static char *bpdisps[] = {"del", "dis", "keep"}; static char bpenables[] = "ny"; + char wrap_indent[80]; - if (!breakpoint_chain) - { - printf_filtered ("No breakpoints or watchpoints.\n"); - return; - } - ALL_BREAKPOINTS (b) if (bnum == -1 || bnum == b->number) @@ -1220,41 +1400,49 @@ breakpoint_1 (bnum, allflag) bptypes[(int)b->type], bpdisps[(int)b->disposition], bpenables[(int)b->enable]); + strcpy (wrap_indent, " "); + if (addressprint) + strcat (wrap_indent, " "); switch (b->type) { case bp_watchpoint: print_expression (b->exp, stdout); break; + case bp_breakpoint: case bp_until: case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_step_resume: + case bp_call_dummy: if (addressprint) - printf_filtered ("%s ", local_hex_string_custom(b->address, "08")); + printf_filtered ("%s ", local_hex_string_custom ((unsigned long) b->address, "08l")); last_addr = b->address; - if (b->symtab) + if (b->source_file) { sym = find_pc_function (b->address); if (sym) { fputs_filtered ("in ", stdout); fputs_filtered (SYMBOL_SOURCE_NAME (sym), stdout); + wrap_here (wrap_indent); fputs_filtered (" at ", stdout); } - fputs_filtered (b->symtab->filename, stdout); + fputs_filtered (b->source_file, stdout); printf_filtered (":%d", b->line_number); } else print_address_symbolic (b->address, stdout, demangle, " "); + break; } printf_filtered ("\n"); if (b->frame) printf_filtered ("\tstop only in stack frame at %s\n", - local_hex_string(b->frame)); + local_hex_string((unsigned long) b->frame)); if (b->cond) { printf_filtered ("\tstop only if "); @@ -1273,9 +1461,13 @@ breakpoint_1 (bnum, allflag) } } - if (!found_a_breakpoint - && bnum != -1) - printf_filtered ("No breakpoint or watchpoint number %d.\n", bnum); + if (!found_a_breakpoint) + { + if (bnum == -1) + printf_filtered ("No breakpoints or watchpoints.\n"); + else + printf_filtered ("No breakpoint or watchpoint number %d.\n", bnum); + } else /* Compare against (CORE_ADDR)-1 in case some compiler decides that a comparison of an unsigned with -1 is always false. */ @@ -1339,7 +1531,7 @@ describe_other_breakpoints (pc) (b->enable == disabled) ? " (disabled)" : "", (others > 1) ? "," : ((others == 1) ? " and" : "")); } - printf ("also set at pc %s.\n", local_hex_string(pc)); + printf ("also set at pc %s.\n", local_hex_string((unsigned long) pc)); } } @@ -1400,7 +1592,11 @@ set_raw_breakpoint (sal) b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint)); memset (b, 0, sizeof (*b)); b->address = sal.pc; - b->symtab = sal.symtab; + if (sal.symtab == NULL) + b->source_file = NULL; + else + b->source_file = savestring (sal.symtab->filename, + strlen (sal.symtab->filename)); b->line_number = sal.line; b->enable = enabled; b->next = 0; @@ -1569,15 +1765,16 @@ mention (b) break; case bp_breakpoint: printf_filtered ("Breakpoint %d at %s", b->number, - local_hex_string(b->address)); - if (b->symtab) + local_hex_string((unsigned long) b->address)); + if (b->source_file) printf_filtered (": file %s, line %d.", - b->symtab->filename, b->line_number); + b->source_file, b->line_number); break; case bp_until: case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_step_resume: break; } printf_filtered ("\n"); @@ -1636,11 +1833,14 @@ break_command_1 (arg, tempflag, from_tty) /* Pointers in arg to the start, and one past the end, of the condition. */ char *cond_start = NULL; - char *cond_end; + char *cond_end = NULL; /* Pointers in arg to the start, and one past the end, of the address part. */ char *addr_start = NULL; - char *addr_end; + char *addr_end = NULL; + struct cleanup *old_chain; + struct cleanup *canonical_strings_chain = NULL; + char **canonical = (char **)NULL; int i; @@ -1680,9 +1880,9 @@ break_command_1 (arg, tempflag, from_tty) && (!current_source_symtab || (arg && (*arg == '+' || *arg == '-')))) sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line); + default_breakpoint_line, &canonical); else - sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0); + sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical); addr_end = arg; } @@ -1690,6 +1890,20 @@ break_command_1 (arg, tempflag, from_tty) if (! sals.nelts) return; + /* Make sure that all storage allocated in decode_line_1 gets freed in case + the following `for' loop errors out. */ + old_chain = make_cleanup (free, sals.sals); + if (canonical != (char **)NULL) + { + make_cleanup (free, canonical); + canonical_strings_chain = make_cleanup (null_cleanup, 0); + for (i = 0; i < sals.nelts; i++) + { + if (canonical[i] != NULL) + make_cleanup (free, canonical[i]); + } + } + /* Resolve all line numbers to PC's, and verify that conditions can be parsed, before setting any breakpoints. */ for (i = 0; i < sals.nelts; i++) @@ -1711,6 +1925,10 @@ break_command_1 (arg, tempflag, from_tty) } } + /* Remove the canonical strings from the cleanup, they are needed below. */ + if (canonical != (char **)NULL) + discard_cleanups (canonical_strings_chain); + /* Now set all the breakpoints. */ for (i = 0; i < sals.nelts; i++) { @@ -1725,11 +1943,11 @@ break_command_1 (arg, tempflag, from_tty) b->type = bp_breakpoint; b->cond = cond; - /* FIXME: We should add the filename if this is a static function - and probably if it is a line number (the line numbers could - have changed when we re-read symbols; possibly better to disable - the breakpoint in that case). */ - if (addr_start) + /* If a canonical line spec is needed use that instead of the + command string. */ + if (canonical != (char **)NULL && canonical[i] != NULL) + b->addr_string = canonical[i]; + else if (addr_start) b->addr_string = savestring (addr_start, addr_end - addr_start); if (cond_start) b->cond_string = savestring (cond_start, cond_end - cond_start); @@ -1745,7 +1963,7 @@ break_command_1 (arg, tempflag, from_tty) printf ("Multiple breakpoints were set.\n"); printf ("Use the \"delete\" command to delete unwanted breakpoints.\n"); } - free ((PTR)sals.sals); + do_cleanups (old_chain); } /* Helper function for break_command_1 and disassemble_command. */ @@ -1845,9 +2063,9 @@ until_break_command (arg, from_tty) if (default_breakpoint_valid) sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line); + default_breakpoint_line, (char ***)NULL); else - sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0); + sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, (char ***)NULL); if (sals.nelts != 1) error ("Couldn't get information on specified line."); @@ -2123,7 +2341,7 @@ catch_command_1 (arg, tempflag, from_tty) else { /* Grab selected catch clauses. */ - error ("catch NAME not implemeneted"); + error ("catch NAME not implemented"); #if 0 /* This isn't used; I don't know what it was for. */ sals = map_catch_names (arg, catch_breakpoint); @@ -2165,10 +2383,7 @@ catch_command_1 (arg, tempflag, from_tty) b->enable = enabled; b->disposition = tempflag ? delete : donttouch; - printf ("Breakpoint %d at %s", b->number, local_hex_string(b->address)); - if (b->symtab) - printf (": file %s, line %d.", b->symtab->filename, b->line_number); - printf ("\n"); + mention (b); } if (sals.nelts > 1) @@ -2249,8 +2464,12 @@ clear_command (arg, from_tty) sal = sals.sals[i]; found = (struct breakpoint *) 0; while (breakpoint_chain - && (sal.pc ? breakpoint_chain->address == sal.pc - : (breakpoint_chain->symtab == sal.symtab + && (sal.pc + ? breakpoint_chain->address == sal.pc + : (breakpoint_chain->source_file != NULL + && sal.symtab != NULL + && STREQ (breakpoint_chain->source_file, + sal.symtab->filename) && breakpoint_chain->line_number == sal.line))) { b1 = breakpoint_chain; @@ -2262,8 +2481,11 @@ clear_command (arg, from_tty) ALL_BREAKPOINTS (b) while (b->next && b->next->type != bp_watchpoint - && (sal.pc ? b->next->address == sal.pc - : (b->next->symtab == sal.symtab + && (sal.pc + ? b->next->address == sal.pc + : (b->next->source_file != NULL + && sal.symtab != NULL + && STREQ (b->next->source_file, sal.symtab->filename) && b->next->line_number == sal.line))) { b1 = b->next; @@ -2302,7 +2524,8 @@ breakpoint_auto_delete (bs) bpstat bs; { for (; bs; bs = bs->next) - if (bs->breakpoint_at && bs->breakpoint_at->disposition == delete) + if (bs->breakpoint_at && bs->breakpoint_at->disposition == delete + && bs->stop) delete_breakpoint (bs->breakpoint_at); } @@ -2316,7 +2539,7 @@ delete_breakpoint (bpt) register bpstat bs; if (bpt->inserted) - target_remove_breakpoint(bpt->address, bpt->shadow_contents); + target_remove_breakpoint(bpt->address, bpt->shadow_contents); if (breakpoint_chain == bpt) breakpoint_chain = bpt->next; @@ -2329,16 +2552,38 @@ delete_breakpoint (bpt) } check_duplicates (bpt->address); + /* If this breakpoint was inserted, and there is another breakpoint + at the same address, we need to insert the other breakpoint. */ + if (bpt->inserted) + { + ALL_BREAKPOINTS (b) + if (b->address == bpt->address + && !b->duplicate + && b->enable != disabled) + { + int val; + val = target_insert_breakpoint (b->address, b->shadow_contents); + if (val != 0) + { + fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number); + memory_error (val, b->address); /* which bombs us out */ + } + else + b->inserted = 1; + } + } free_command_lines (&bpt->commands); if (bpt->cond) - free ((PTR)bpt->cond); + free (bpt->cond); if (bpt->cond_string != NULL) - free ((PTR)bpt->cond_string); + free (bpt->cond_string); if (bpt->addr_string != NULL) - free ((PTR)bpt->addr_string); + free (bpt->addr_string); if (bpt->exp_string != NULL) - free ((PTR)bpt->exp_string); + free (bpt->exp_string); + if (bpt->source_file != NULL) + free (bpt->source_file); if (xgdb_verbose && bpt->type == bp_breakpoint) printf ("breakpoint #%d deleted\n", bpt->number); @@ -2401,25 +2646,45 @@ breakpoint_re_set_one (bint) b->enable = disabled; s = b->addr_string; - sals = decode_line_1 (&s, 1, (struct symtab *)NULL, 0); + sals = decode_line_1 (&s, 1, (struct symtab *)NULL, 0, (char ***)NULL); for (i = 0; i < sals.nelts; i++) { resolve_sal_pc (&sals.sals[i]); - if (b->symtab != sals.sals[i].symtab - || b->line_number != sals.sals[i].line - || b->address != sals.sals[i].pc) + + /* Reparse conditions, they might contain references to the + old symtab. */ + if (b->cond_string != NULL) + { + s = b->cond_string; + if (b->cond) + free ((PTR)b->cond); + b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0); + } + + /* We need to re-set the breakpoint if the address changes...*/ + if (b->address != sals.sals[i].pc + /* ...or new and old breakpoints both have source files, and + the source file name or the line number changes... */ + || (b->source_file != NULL + && sals.sals[i].symtab != NULL + && (!STREQ (b->source_file, sals.sals[i].symtab->filename) + || b->line_number != sals.sals[i].line) + ) + /* ...or we switch between having a source file and not having + one. */ + || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL)) + ) { - b->symtab = sals.sals[i].symtab; + if (b->source_file != NULL) + free (b->source_file); + if (sals.sals[i].symtab == NULL) + b->source_file = NULL; + else + b->source_file = + savestring (sals.sals[i].symtab->filename, + strlen (sals.sals[i].symtab->filename)); b->line_number = sals.sals[i].line; b->address = sals.sals[i].pc; - - if (b->cond_string != NULL) - { - s = b->cond_string; - if (b->cond) - free ((PTR)b->cond); - b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0); - } check_duplicates (b->address); @@ -2463,6 +2728,7 @@ breakpoint_re_set_one (bint) case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_call_dummy: delete_breakpoint (b); break; } @@ -2478,17 +2744,11 @@ breakpoint_re_set () static char message1[] = "Error in re-setting breakpoint %d:\n"; char message[sizeof (message1) + 30 /* slop */]; - /* If we have no current source symtab, and we have any breakpoints, - go through the work of making a source context. */ - if (current_source_symtab == NULL && breakpoint_chain != 0) - { - select_source_symtab (NULL); - } - ALL_BREAKPOINTS_SAFE (b, temp) { sprintf (message, message1, b->number); /* Format possible error msg */ - catch_errors (breakpoint_re_set_one, (char *) b, message); + catch_errors (breakpoint_re_set_one, (char *) b, message, + RETURN_MASK_ALL); } create_longjmp_breakpoint("longjmp"); @@ -2610,6 +2870,9 @@ static void enable_breakpoint (bpt) struct breakpoint *bpt; { + FRAME save_selected_frame = NULL; + int save_selected_frame_level = -1; + bpt->enable = enabled; if (xgdb_verbose && bpt->type == bp_breakpoint) @@ -2618,14 +2881,20 @@ enable_breakpoint (bpt) check_duplicates (bpt->address); if (bpt->type == bp_watchpoint) { - if (bpt->exp_valid_block != NULL - && !contained_in (get_selected_block (), bpt->exp_valid_block)) + if (bpt->exp_valid_block != NULL) { - printf_filtered ("\ + FRAME fr = within_scope (bpt->exp_valid_block); + 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 = disabled; - return; + bpt->enable = disabled; + return; + } + save_selected_frame = selected_frame; + save_selected_frame_level = selected_frame_level; + select_frame (fr, -1); } value_free (bpt->val); @@ -2634,6 +2903,9 @@ is valid is not currently in scope.\n", bpt->number); release_value (bpt->val); if (VALUE_LAZY (bpt->val)) value_fetch_lazy (bpt->val); + + if (save_selected_frame_level >= 0) + select_frame (save_selected_frame, save_selected_frame_level); } } @@ -2742,9 +3014,11 @@ decode_line_spec_1 (string, funfirstline) error ("Empty line specification."); if (default_breakpoint_valid) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, default_breakpoint_line); + default_breakpoint_symtab, default_breakpoint_line, + (char ***)NULL); else - sals = decode_line_1 (&string, funfirstline, (struct symtab *)NULL, 0); + sals = decode_line_1 (&string, funfirstline, + (struct symtab *)NULL, 0, (char ***)NULL); if (*string) error ("Junk at end of line specification: %s", string); return sals;