aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/breakpoint.c29
-rw-r--r--gdb/breakpoint.h256
-rw-r--r--gdb/config/sparc/tm-sparc.h2
-rw-r--r--gdb/defs.h2
-rw-r--r--gdb/infcmd.c40
-rw-r--r--gdb/infrun.c24
7 files changed, 236 insertions, 129 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 615adae..2a174a5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,4 +1,14 @@
-Fri Sep 17 10:10:05 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+Sat Sep 18 10:13:18 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * defs.h (make_cleanup): Change PTR to void * when inside PARAMS.
+
+ Some of the following is in #ifdef CALL_DUMMY_BREAKPOINT_OFFSET.
+ * breakpoint.h (enum bptype): Add bp_call_dummy.
+ (struct bpstat_what): Add call_dummy field.
+ * infrun.c (wait_for_inferior): Deal with it.
+ * breakpoint.c (bpstat_what): Deal with call dummy breakpoint.
+ * infcmd.c (run_stack_dummy): Set the call dummy breakpoint.
+ * config/sparc/tm-sparc.h: Define CALL_DUMMY_BREAKPOINT_OFFSET.
* remote-sim.h: New file.
* remote-sim.c: Add remote debug feature. Rename stuff to distinguish
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 5e955c0..bec31eb 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1221,6 +1221,12 @@ bpstat_what (bs)
#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] =
{
@@ -1245,7 +1251,7 @@ bpstat_what (bs)
#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)
{
@@ -1297,7 +1303,7 @@ bpstat_what (bs)
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
@@ -1307,15 +1313,16 @@ bpstat_what (bs)
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
@@ -1347,7 +1354,7 @@ 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"};
static char *bpdisps[] = {"del", "dis", "keep"};
static char bpenables[] = "ny";
char wrap_indent[80];
@@ -1379,11 +1386,13 @@ breakpoint_1 (bnum, allflag)
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"));
@@ -1403,8 +1412,6 @@ breakpoint_1 (bnum, allflag)
}
else
print_address_symbolic (b->address, stdout, demangle, " ");
- /* intentional fall-through */
- case bp_step_resume: /* do nothing. */
break;
}
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 3949777..5c7e69d 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -29,7 +29,122 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define BREAKPOINT_MAX 16
-/* 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;
+};
+
+/* 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. */
@@ -49,9 +164,11 @@ extern bpstat bpstat_copy PARAMS ((bpstat));
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));
+
+/* 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). */
@@ -70,7 +187,9 @@ enum bpstat_what {
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,
@@ -90,9 +209,24 @@ enum bpstat_what {
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));
+
/* Find the bpstat associated with a breakpoint. NULL otherwise. */
bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
@@ -119,7 +253,9 @@ extern int bpstat_print PARAMS ((bpstat));
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. */
@@ -150,112 +286,6 @@ struct bpstat
int (*print_it) PARAMS((bpstat bs));
};
-/* 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;
-};
-
/* Prototypes for breakpoint-related functions. */
#ifdef __STDC__ /* Forward declarations for prototypes */
diff --git a/gdb/config/sparc/tm-sparc.h b/gdb/config/sparc/tm-sparc.h
index 70f1f20..09193f8 100644
--- a/gdb/config/sparc/tm-sparc.h
+++ b/gdb/config/sparc/tm-sparc.h
@@ -554,6 +554,8 @@ arguments. */
#define CALL_DUMMY_START_OFFSET 148
+#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + (8 * 4))
+
#define CALL_DUMMY_STACK_ADJUST 68
/* Insert the specified number of args and function address
diff --git a/gdb/defs.h b/gdb/defs.h
index f7b3d61..4791f3a 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -180,7 +180,7 @@ discard_cleanups PARAMS ((struct cleanup *));
Should be, once all calls and called-functions are cleaned up:
extern struct cleanup *
-make_cleanup PARAMS ((void (*function) (PTR), PTR));
+make_cleanup PARAMS ((void (*function) (void *), void *));
Until then, lint and/or various type-checking compiler options will
complain about make_cleanup calls. It'd be wrong to just cast things,
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index c0c5b7d..8cd9940 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -497,6 +497,15 @@ signal_command (signum_exp, from_tty)
proceed (stop_pc, signum, 0);
}
+/* Call breakpoint_auto_delete on the current contents of the bpstat
+ pointed to by arg (which is really a bpstat *). */
+void
+breakpoint_auto_delete_contents (arg)
+ PTR arg;
+{
+ breakpoint_auto_delete (*(bpstat *)arg);
+}
+
/* Execute a "stack dummy", a piece of code stored in the stack
by the debugger to be executed in the inferior.
@@ -522,6 +531,8 @@ run_stack_dummy (addr, buffer)
CORE_ADDR addr;
char buffer[REGISTER_BYTES];
{
+ struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+
/* Now proceed, having reached the desired place. */
clear_proceed_status ();
if (stack_dummy_testing & 4)
@@ -529,9 +540,38 @@ run_stack_dummy (addr, buffer)
POP_FRAME;
return(0);
}
+#ifdef CALL_DUMMY_BREAKPOINT_OFFSET
+ {
+ struct breakpoint *bpt;
+ struct symtab_and_line sal;
+
+ sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET;
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ /* If defined, CALL_DUMMY_BREAKPOINT_OFFSET is where we need to put
+ a breakpoint instruction. If not, the call dummy already has the
+ breakpoint instruction in it.
+
+ addr is the address of the call dummy plus the CALL_DUMMY_START_OFFSET,
+ so we need to subtract the CALL_DUMMY_START_OFFSET. */
+ bpt = set_momentary_breakpoint (sal,
+ NULL,
+ bp_call_dummy);
+ bpt->disposition = delete;
+
+ /* If all error()s out of proceed ended up calling normal_stop (and
+ perhaps they should; it already does in the special case of error
+ out of resume()), then we wouldn't need this. */
+ make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
+ }
+#endif /* CALL_DUMMY_BREAKPOINT_OFFSET. */
+
proceed_to_finish = 1; /* We want stop_registers, please... */
proceed (addr, 0, 0);
+ discard_cleanups (old_cleanups);
+
if (!stop_stack_dummy)
return 1;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a9d8a64..3656c98 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -721,7 +721,9 @@ wait_for_inferior ()
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
{
@@ -730,7 +732,9 @@ wait_for_inferior ()
/* 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;
@@ -793,6 +797,14 @@ wait_for_inferior ()
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:
@@ -887,6 +899,12 @@ wait_for_inferior ()
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. */
@@ -901,7 +919,8 @@ wait_for_inferior ()
#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
@@ -1081,8 +1100,7 @@ step_into_function:
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 ();