#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] =
{
#undef clrlrs
#undef err
enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
- int found_step_resume = 0;
+ struct bpstat_what retval;
for (; bs != NULL; bs = bs->next)
{
if (bs->stop)
{
#endif
- found_step_resume = 1;
+ retval.step_resume = 1;
/* We don't handle this via the main_action. */
bs_class = no_effect;
#if 0
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;
}
current_action = table[(int)bs_class][(int)current_action];
}
- {
- struct bpstat_what retval;
- retval.main_action = current_action;
- retval.step_resume = found_step_resume;
- return retval;
- }
+ retval.main_action = current_action;
+ return retval;
}
/* Nonzero if we should step constantly (e.g. watchpoints on machines
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"};
static char *bpdisps[] = {"del", "dis", "keep"};
static char bpenables[] = "ny";
char wrap_indent[80];
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:
if (addressprint)
printf_filtered ("%s ", local_hex_string_custom(b->address, "08"));
}
else
print_address_symbolic (b->address, stdout, demangle, " ");
- /* intentional fall-through */
- case bp_step_resume: /* do nothing. */
break;
}
#define BREAKPOINT_MAX 16
\f
-/* The follow stuff is an abstract data type "bpstat" ("breakpoint status").
+/* Type of breakpoint. */
+/* FIXME In the future, we should fold all other breakpoint-like things into
+ here. This includes:
+
+ * call-dummy (the breakpoint at the end of a subroutine stub that gdb
+ uses to call functions in the target) (definately).
+
+ * single-step (for machines where we have to simulate single stepping)
+ (probably, though perhaps it is better for it to look as much as
+ possible like a single-step to wait_for_inferior). */
+
+enum bptype {
+ bp_breakpoint, /* Normal breakpoint */
+ bp_until, /* used by until command */
+ bp_finish, /* used by finish command */
+ bp_watchpoint, /* Watchpoint */
+ bp_longjmp, /* secret breakpoint to find longjmp() */
+ bp_longjmp_resume, /* secret breakpoint to escape longjmp() */
+
+ /* Used by wait_for_inferior for stepping over subroutine calls, for
+ stepping over signal handlers, and for skipping prologues. */
+ bp_step_resume,
+
+ /* The breakpoint at the end of a call dummy. */
+ bp_call_dummy
+};
+
+/* States of enablement of breakpoint. */
+
+enum enable { disabled, enabled};
+
+/* Disposition of breakpoint. Ie: what to do after hitting it. */
+
+enum bpdisp {
+ delete, /* Delete it */
+ disable, /* Disable it */
+ donttouch /* Leave it alone */
+};
+
+/* Note that the ->silent field is not currently used by any commands
+ (though the code is in there if it was to be, and set_raw_breakpoint
+ does set it to 0). I implemented it because I thought it would be
+ useful for a hack I had to put in; I'm going to leave it in because
+ I can see how there might be times when it would indeed be useful */
+
+/* This is for a breakpoint or a watchpoint. */
+
+struct breakpoint
+{
+ struct breakpoint *next;
+ /* Type of breakpoint. */
+ enum bptype type;
+ /* Zero means disabled; remember the info but don't break here. */
+ enum enable enable;
+ /* What to do with this breakpoint after we hit it. */
+ enum bpdisp disposition;
+ /* Number assigned to distinguish breakpoints. */
+ int number;
+
+ /* Address to break at, or NULL if not a breakpoint. */
+ CORE_ADDR address;
+
+ /* Line number of this address. Only matters if address is
+ non-NULL. */
+
+ int line_number;
+
+ /* Source file name of this address. Only matters if address is
+ non-NULL. */
+
+ char *source_file;
+
+ /* Non-zero means a silent breakpoint (don't print frame info
+ if we stop here). */
+ unsigned char silent;
+ /* Number of stops at this breakpoint that should
+ be continued automatically before really stopping. */
+ int ignore_count;
+ /* "Real" contents of byte where breakpoint has been inserted.
+ Valid only when breakpoints are in the program. Under the complete
+ control of the target insert_breakpoint and remove_breakpoint routines.
+ No other code should assume anything about the value(s) here. */
+ char shadow_contents[BREAKPOINT_MAX];
+ /* Nonzero if this breakpoint is now inserted. Only matters if address
+ is non-NULL. */
+ char inserted;
+ /* Nonzero if this is not the first breakpoint in the list
+ for the given address. Only matters if address is non-NULL. */
+ char duplicate;
+ /* Chain of command lines to execute when this breakpoint is hit. */
+ struct command_line *commands;
+ /* Stack depth (address of frame). If nonzero, break only if fp
+ equals this. */
+ FRAME_ADDR frame;
+ /* Conditional. Break only if this expression's value is nonzero. */
+ struct expression *cond;
+
+ /* String we used to set the breakpoint (malloc'd). Only matters if
+ address is non-NULL. */
+ char *addr_string;
+ /* String form of the breakpoint condition (malloc'd), or NULL if there
+ is no condition. */
+ char *cond_string;
+ /* String form of exp (malloc'd), or NULL if none. */
+ char *exp_string;
+
+ /* The expression we are watching, or NULL if not a watchpoint. */
+ struct expression *exp;
+ /* The largest block within which it is valid, or NULL if it is
+ valid anywhere (e.g. consists just of global symbols). */
+ struct block *exp_valid_block;
+ /* Value of the watchpoint the last time we checked it. */
+ value val;
+};
+\f
+/* The following stuff is an abstract data type "bpstat" ("breakpoint status").
This provides the ability to determine whether we have stopped at a
breakpoint, and what we should do about it. */
breakpoint (if we hit a breakpoint). */
/* FIXME: prototypes uses equivalence between FRAME_ADDR and CORE_ADDR */
extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, CORE_ADDR));
+\f
+/* This bpstat_what stuff tells wait_for_inferior what to do with a
+ breakpoint (a challenging task). */
-/* Return values from bpstat_what. */
-enum bpstat_what {
+enum bpstat_what_main_action {
/* Perform various other tests; that is, this bpstat does not
say to perform any action (e.g. failed watchpoint and nothing
else). */
BPSTAT_WHAT_STOP_NOISY,
/* Remove breakpoints, single step once, then put them back in and
- go back to what we were doing. */
+ go back to what we were doing. It's possible that this should be
+ removed from the main_action and put into a separate field, to more
+ cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE. */
BPSTAT_WHAT_SINGLE,
/* Set longjmp_resume breakpoint, remove all other breakpoints,
BPSTAT_WHAT_LAST
};
-/* Tell what to do about this bpstat. */
-enum bpstat_what bpstat_what PARAMS ((bpstat));
+struct bpstat_what {
+ enum bpstat_what_main_action main_action : 4;
+
+ /* Did we hit the step resume breakpoint? This is separate from the
+ main_action to allow for it to be combined with any of the main
+ actions. */
+ unsigned int step_resume : 1;
+
+ /* Did we hit a call dummy breakpoint? This only goes with a main_action
+ of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of
+ continuing from a call dummy without popping the frame is not a
+ useful one). */
+ unsigned int call_dummy : 1;
+};
+/* Tell what to do about this bpstat. */
+struct bpstat_what bpstat_what PARAMS ((bpstat));
+\f
/* Find the bpstat associated with a breakpoint. NULL otherwise. */
bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
Return 0 if passed a bpstat which does not indicate any breakpoints. */
extern int bpstat_num PARAMS ((bpstat *));
-/* Perform actions associated with having stopped at *BSP. */
+/* Perform actions associated with having stopped at *BSP. Actually, we just
+ use this for breakpoint commands. Perhaps other actions will go here
+ later, but this is executed at a late time (from the command loop). */
extern void bpstat_do_actions PARAMS ((bpstat *));
/* Modify BS so that the actions will not be performed. */
int (*print_it) PARAMS((bpstat bs));
};
\f
-/* Type of breakpoint. */
-/* FIXME In the future, we should fold all other breakpoint-like things into
- here. This includes:
-
- 1) single-step (for machines where we have to simulate single stepping),
- 2) step-resume (for 'next'ing over subroutine calls),
- 3) call-dummy (the breakpoint at the end of a subroutine stub that gdb
- uses to call functions in the target).
-
- I definately agree with (2) and (3); I'm not as sure about (1)
- (it is a low-level thing, perhaps the best thing is that it looks
- as much as possible like a single-step to wait_for_inferior)
- -kingdon, 8 Apr 93.
-*/
-
-enum bptype {
- bp_breakpoint, /* Normal breakpoint */
- bp_until, /* used by until command */
- bp_finish, /* used by finish command */
- bp_watchpoint, /* Watchpoint */
- bp_longjmp, /* secret breakpoint to find longjmp() */
- bp_longjmp_resume /* secret breakpoint to escape longjmp() */
-};
-
-/* States of enablement of breakpoint. */
-
-enum enable { disabled, enabled};
-
-/* Disposition of breakpoint. Ie: what to do after hitting it. */
-
-enum bpdisp {
- delete, /* Delete it */
- disable, /* Disable it */
- donttouch /* Leave it alone */
-};
-
-/* Note that the ->silent field is not currently used by any commands
- (though the code is in there if it was to be, and set_raw_breakpoint
- does set it to 0). I implemented it because I thought it would be
- useful for a hack I had to put in; I'm going to leave it in because
- I can see how there might be times when it would indeed be useful */
-
-/* This is for a breakpoint or a watchpoint. */
-
-struct breakpoint
-{
- struct breakpoint *next;
- /* Type of breakpoint. */
- enum bptype type;
- /* Zero means disabled; remember the info but don't break here. */
- enum enable enable;
- /* What to do with this breakpoint after we hit it. */
- enum bpdisp disposition;
- /* Number assigned to distinguish breakpoints. */
- int number;
- /* Address to break at, or NULL if not a breakpoint. */
- CORE_ADDR address;
- /* Line number of this address. Redundant. Only matters if address
- is non-NULL. */
- int line_number;
- /* Symtab of file of this address. Redundant. Only matters if address
- is non-NULL. */
- struct symtab *symtab;
- /* Non-zero means a silent breakpoint (don't print frame info
- if we stop here). */
- unsigned char silent;
- /* Number of stops at this breakpoint that should
- be continued automatically before really stopping. */
- int ignore_count;
- /* "Real" contents of byte where breakpoint has been inserted.
- Valid only when breakpoints are in the program. Under the complete
- control of the target insert_breakpoint and remove_breakpoint routines.
- No other code should assume anything about the value(s) here. */
- char shadow_contents[BREAKPOINT_MAX];
- /* Nonzero if this breakpoint is now inserted. Only matters if address
- is non-NULL. */
- char inserted;
- /* Nonzero if this is not the first breakpoint in the list
- for the given address. Only matters if address is non-NULL. */
- char duplicate;
- /* Chain of command lines to execute when this breakpoint is hit. */
- struct command_line *commands;
- /* Stack depth (address of frame). If nonzero, break only if fp
- equals this. */
- FRAME_ADDR frame;
- /* Conditional. Break only if this expression's value is nonzero. */
- struct expression *cond;
-
- /* String we used to set the breakpoint (malloc'd). Only matters if
- address is non-NULL. */
- char *addr_string;
- /* String form of the breakpoint condition (malloc'd), or NULL if there
- is no condition. */
- char *cond_string;
- /* String form of exp (malloc'd), or NULL if none. */
- char *exp_string;
-
- /* The expression we are watching, or NULL if not a watchpoint. */
- struct expression *exp;
- /* The largest block within which it is valid, or NULL if it is
- valid anywhere (e.g. consists just of global symbols). */
- struct block *exp_valid_block;
- /* Value of the watchpoint the last time we checked it. */
- value val;
-};
-\f
/* Prototypes for breakpoint-related functions. */
#ifdef __STDC__ /* Forward declarations for prototypes */
random_signal
= !(bpstat_explains_signal (stop_bpstat)
|| trap_expected
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
|| PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
|| (step_range_end && step_resume_breakpoint == NULL));
else
{
/* End of a stack dummy. Some systems (e.g. Sony
news) give another signal besides SIGTRAP,
so check here as well as above. */
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
|| PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
);
if (!random_signal)
stop_signal = SIGTRAP;
what = bpstat_what (stop_bpstat);
+ if (what.call_dummy)
+ {
+ stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 1;
+#endif
+ }
+
switch (what.main_action)
{
case BPSTAT_WHAT_SET_LONGJMP_RESUME:
test for stepping. But, if not stepping,
do not stop. */
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ /* This is the old way of detecting the end of the stack dummy.
+ An architecture which defines CALL_DUMMY_BREAKPOINT_OFFSET gets
+ handled above. As soon as we can test it on all of them, all
+ architectures should define it. */
+
/* If this is the breakpoint at the end of a stack dummy,
just stop silently, unless the user was doing an si/ni, in which
case she'd better know what she's doing. */
#endif
break;
}
-
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+
if (step_resume_breakpoint)
/* Having a step-resume breakpoint overrides anything
else having to do with stepping commands until
since on some machines the prologue
is where the new fp value is established. */
step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, (CORE_ADDR)0,
- bp_step_resume);
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();