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)
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 ()
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. */
{
bpstat p = NULL;
bpstat tmp;
- bpstat retval;
+ bpstat retval = NULL;
if (bs == NULL)
return bs;
|| (bs->breakpoint_at->type != bp_breakpoint
&& bs->breakpoint_at->type != bp_watchpoint))
return 0;
-
- /* If bpstat_stop_status says don't print, OK, we won't. An example
- circumstance is when we single-stepped for both a watchpoint and
- for a "stepi" instruction. The bpstat says that the watchpoint
- explains the stop, but we shouldn't print because the watchpoint's
- value didn't change -- and the real reason we are stopping here
- rather than continuing to step (as the watchpoint would've had us do)
- is because of the "stepi". */
- if (!bs->print)
- return 0;
if (bs->breakpoint_at->type == bp_breakpoint)
{
if (bs->next)
return bpstat_print (bs->next);
- fprintf_filtered (stderr, "gdb internal error: in bpstat_print\n");
+ /* We reached the end of the chain without printing anything. */
return 0;
}
bs->breakpoint_at = b;
/* If the condition is false, etc., don't do the commands. */
bs->commands = NULL;
- bs->momentary = b->disposition == delete;
bs->old_val = NULL;
bs->print_it = print_it_normal;
return bs;
}
+\f
+/* 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). */
/* 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);
/* This is used when everything which needs to be printed has
already been printed. But we still want to print the frame. */
static int
-print_it_noop (bs)
+print_it_done (bs)
bpstat bs;
{
return 0;
}
+/* This is used when nothing should be printed for this bpstat entry. */
+
+static int
+print_it_noop (bs)
+ bpstat 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
*/
-
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;
- int stop = 0;
- int print = 0;
CORE_ADDR bp_addr;
#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
/* True if we've hit a breakpoint (as opposed to a watchpoint). */
ALL_BREAKPOINTS (b)
{
- int this_bp_stop;
- int this_bp_print;
-
if (b->enable == disabled)
continue;
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 */
- this_bp_stop = 1;
- this_bp_print = 1;
+ bs->stop = 1;
+ bs->print = 1;
if (b->type == bp_watchpoint)
{
"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. */
- bs->print_it = print_it_noop;
+ bs->print_it = print_it_done;
/* Stop. */
break;
case WP_VALUE_CHANGED:
break;
case WP_VALUE_NOT_CHANGED:
/* Don't stop. */
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
continue;
default:
/* Can't happen. */
b->enable = disabled;
printf_filtered ("Watchpoint %d disabled.\n", b->number);
/* We've already printed what needs to be printed. */
- bs->print_it = print_it_noop;
+ bs->print_it = print_it_done;
/* Stop. */
break;
}
#endif
if (b->frame && b->frame != frame_address)
- this_bp_stop = 0;
+ bs->stop = 0;
else
{
- int value_is_zero;
+ int value_is_zero = 0;
if (b->cond)
{
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 ();
}
if (b->cond && value_is_zero)
{
- this_bp_stop = 0;
+ bs->stop = 0;
}
else if (b->ignore_count > 0)
{
b->ignore_count--;
- this_bp_stop = 0;
+ bs->stop = 0;
}
else
{
b->enable = disabled;
bs->commands = b->commands;
if (b->silent)
- this_bp_print = 0;
+ bs->print = 0;
if (bs->commands && STREQ ("silent", bs->commands->line))
{
bs->commands = bs->commands->next;
- this_bp_print = 0;
+ bs->print = 0;
}
}
}
- if (this_bp_stop)
- stop = 1;
- if (this_bp_print)
- print = 1;
+ /* Print nothing for this entry if we dont stop or if we dont print. */
+ if (bs->stop == 0 || bs->print == 0)
+ bs->print_it = print_it_noop;
}
bs->next = NULL; /* Terminate the chain */
bs = root_bs->next; /* Re-grab the head of the chain */
+#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
if (bs)
{
- bs->stop = stop;
- bs->print = print;
-#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
if (real_breakpoint)
{
*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. */
}
-#endif /* DECR_PC_AFTER_BREAK != 0. */
}
+#endif /* DECR_PC_AFTER_BREAK != 0. */
return bs;
}
+\f
+/* Tell what to do about this bpstat. */
+struct bpstat_what
+bpstat_what (bs)
+ bpstat bs;
+{
+ /* Classify each bpstat as one of the following. */
+ enum class {
+ /* This bpstat element has no effect on the main_action. */
+ no_effect = 0,
+
+ /* There was a watchpoint, stop but don't print. */
+ wp_silent,
+
+ /* There was a watchpoint, stop and print. */
+ wp_noisy,
+
+ /* There was a breakpoint but we're not stopping. */
+ bp_nostop,
+
+ /* There was a breakpoint, stop but don't print. */
+ bp_silent,
+
+ /* There was a breakpoint, stop and print. */
+ bp_noisy,
+
+ /* We hit the longjmp breakpoint. */
+ long_jump,
+
+ /* We hit the longjmp_resume breakpoint. */
+ long_resume,
+
+ /* This is just used to count how many enums there are. */
+ class_last
+ };
+
+ /* Here is the table which drives this routine. So that we can
+ format it pretty, we define some abbreviations for the
+ enum bpstat_what codes. */
+#define keep_c BPSTAT_WHAT_KEEP_CHECKING
+#define stop_s BPSTAT_WHAT_STOP_SILENT
+#define stop_n BPSTAT_WHAT_STOP_NOISY
+#define single BPSTAT_WHAT_SINGLE
+#define setlr BPSTAT_WHAT_SET_LONGJMP_RESUME
+#define clrlr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
+#define clrlrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
+/* "Can't happen." Might want to print an error message.
+ abort() is not out of the question, but chances are GDB is just
+ a bit confused, not unusable. */
+#define err BPSTAT_WHAT_STOP_NOISY
+
+ /* Given an old action and a class, come up with a new action. */
+ /* 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 */
+
+/*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},
+/*bp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s},
+/*bp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n},
+/*long_jump*/ {setlr , stop_s, stop_n, setlr , err , err , err },
+/*long_resume*/ {clrlr , stop_s, stop_n, clrlrs, err , err , err }
+ };
+#undef keep_c
+#undef stop_s
+#undef stop_n
+#undef single
+#undef setlr
+#undef clrlr
+#undef clrlrs
+#undef err
+ 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 = no_effect;
+ if (bs->breakpoint_at == NULL)
+ /* I suspect this can happen if it was a momentary breakpoint
+ which has since been deleted. */
+ continue;
+ switch (bs->breakpoint_at->type)
+ {
+ case bp_breakpoint:
+ case bp_until:
+ case bp_finish:
+ if (bs->stop)
+ {
+ if (bs->print)
+ bs_class = bp_noisy;
+ else
+ bs_class = bp_silent;
+ }
+ else
+ bs_class = bp_nostop;
+ break;
+ case bp_watchpoint:
+ if (bs->stop)
+ {
+ if (bs->print)
+ bs_class = wp_noisy;
+ else
+ bs_class = wp_silent;
+ }
+ else
+ /* 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;
+ break;
+ 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];
+ }
+ retval.main_action = current_action;
+ return retval;
+}
/* Nonzero if we should step constantly (e.g. watchpoints on machines
without hardware support). This isn't related to a specific bpstat,
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)
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 ");
}
}
- 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. */
(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));
}
}
\f
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;
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");
/* 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;
&& (!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;
}
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++)
}
}
+ /* 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++)
{
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);
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. */
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.");
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);
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)
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;
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;
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);
}
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;
}
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);
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)
{
- b->symtab = sals.sals[i].symtab;
+ 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))
+ )
+ {
+ 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);
s = b->cond_string;
b->cond = parse_exp_1 (&s, (struct block *)0, 0);
}
- mention (b);
+ if (b->enable == enabled)
+ mention (b);
break;
default:
case bp_finish:
case bp_longjmp:
case bp_longjmp_resume:
+ case bp_call_dummy:
delete_breakpoint (b);
break;
}
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");
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)
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);
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);
}
}
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;