diff options
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/breakpoint.c | 29 | ||||
-rw-r--r-- | gdb/breakpoint.h | 256 | ||||
-rw-r--r-- | gdb/config/sparc/tm-sparc.h | 2 | ||||
-rw-r--r-- | gdb/defs.h | 2 | ||||
-rw-r--r-- | gdb/infcmd.c | 40 | ||||
-rw-r--r-- | gdb/infrun.c | 24 |
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 @@ -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 (); |