diff options
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 669 |
1 files changed, 432 insertions, 237 deletions
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index f6b136f..61a7a9f 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -1,5 +1,5 @@ /* Everything about breakpoints, for GDB. - Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GDB. @@ -20,10 +20,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <ctype.h> #include "defs.h" -#include "param.h" #include "symtab.h" #include "frame.h" #include "breakpoint.h" +#include "gdbtypes.h" #include "expression.h" #include "gdbcore.h" #include "gdbcmd.h" @@ -35,85 +35,114 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "language.h" #include <string.h> +/* local function prototypes */ + +static void +catch_command_1 PARAMS ((char *, int, int)); + +static void +enable_delete_command PARAMS ((char *, int)); + +static void +enable_delete_breakpoint PARAMS ((struct breakpoint *)); + +static void +enable_once_command PARAMS ((char *, int)); + +static void +enable_once_breakpoint PARAMS ((struct breakpoint *)); + +static void +disable_command PARAMS ((char *, int)); + +static void +disable_breakpoint PARAMS ((struct breakpoint *)); + +static void +enable_command PARAMS ((char *, int)); + +static void +enable_breakpoint PARAMS ((struct breakpoint *)); + +static void +map_breakpoint_numbers PARAMS ((char *, void (*)(struct breakpoint *))); + +static void +ignore_command PARAMS ((char *, int)); + +static int +breakpoint_re_set_one PARAMS ((char *)); + +static void +delete_command PARAMS ((char *, int)); + +static void +clear_command PARAMS ((char *, int)); + +static void +catch_command PARAMS ((char *, int)); + +static struct symtabs_and_lines +get_catch_sals PARAMS ((int)); + +static void +watch_command PARAMS ((char *, int)); + +static void +tbreak_command PARAMS ((char *, int)); + +static void +break_command_1 PARAMS ((char *, int, int)); + +static void +mention PARAMS ((struct breakpoint *)); + +static struct breakpoint * +set_raw_breakpoint PARAMS ((struct symtab_and_line)); + +static void +check_duplicates PARAMS ((CORE_ADDR)); + +static void +describe_other_breakpoints PARAMS ((CORE_ADDR)); + +static void +watchpoints_info PARAMS ((char *, int)); + +static void +breakpoints_info PARAMS ((char *, int)); + +static void +breakpoint_1 PARAMS ((int, int)); + +static bpstat +bpstat_alloc PARAMS ((struct breakpoint *, bpstat)); + +static int +breakpoint_cond_eval PARAMS ((char *)); + +static void +cleanup_executing_breakpoints PARAMS ((int)); + +static void +commands_command PARAMS ((char *, int)); + +static void +condition_command PARAMS ((char *, int)); + +static int +get_number PARAMS ((char **)); + +static void +set_breakpoint_count PARAMS ((int)); + + extern int addressprint; /* Print machine addresses? */ extern int demangle; /* Print de-mangled symbol names? */ -extern int catch_errors (); -extern void set_next_address (); /* ...for x/ command */ - /* Are we executing breakpoint commands? */ static int executing_breakpoint_commands; -/* States of enablement of breakpoint. - `temporary' means disable when hit. - `delete' means delete when hit. */ - -enum enable { disabled, enabled, temporary, delete}; - -/* Not 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; - /* 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; - /* Zero means disabled; remember the info but don't break here. */ - enum enable enable; - /* 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; - - /* 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; -}; - #define ALL_BREAKPOINTS(b) for (b = breakpoint_chain; b; b = b->next) /* Chain of all breakpoints defined. */ @@ -146,9 +175,6 @@ CORE_ADDR default_breakpoint_address; struct symtab *default_breakpoint_symtab; int default_breakpoint_line; -static void delete_breakpoint (); -void breakpoint_auto_delete (); - /* Flag indicating extra verbosity for xgdb. */ extern int xgdb_verbose; @@ -299,7 +325,13 @@ End with a line saying just \"end\".\n", bnum); extern int memory_breakpoint_size; /* from mem-break.c */ /* Like target_read_memory() but if breakpoints are inserted, return - the shadow contents instead of the breakpoints themselves. */ + the shadow contents instead of the breakpoints themselves. + + Read "memory data" from whatever target or inferior we have. + Returns zero if successful, errno value if not. EIO is used + for address out of bounds. If breakpoints are inserted, returns + shadow contents, not the breakpoints themselves. From breakpoint.c. */ + int read_memory_nobpt (memaddr, myaddr, len) CORE_ADDR memaddr; @@ -315,7 +347,7 @@ read_memory_nobpt (memaddr, myaddr, len) ALL_BREAKPOINTS (b) { - if (b->address == NULL || !b->inserted) + if (b->type == bp_watchpoint || !b->inserted) continue; else if (b->address + memory_breakpoint_size <= memaddr) /* The breakpoint is entirely before the chunk of memory @@ -392,7 +424,7 @@ insert_breakpoints () int disabled_breaks = 0; ALL_BREAKPOINTS (b) - if (b->address != NULL + if (b->type != bp_watchpoint && b->enable != disabled && ! b->inserted && ! b->duplicate) @@ -445,7 +477,7 @@ remove_breakpoints () #endif /* BREAKPOINT_DEBUG */ ALL_BREAKPOINTS (b) - if (b->address != NULL && b->inserted) + if (b->type != bp_watchpoint && b->inserted) { val = target_remove_breakpoint(b->address, b->shadow_contents); if (val) @@ -495,6 +527,10 @@ breakpoint_here_p (pc) /* bpstat stuff. External routines' interfaces are documented in breakpoint.h. */ + +/* Clear a bpstat so that it says we are not at any breakpoint. + Also free any storage that is part of a bpstat. */ + void bpstat_clear (bsp) bpstat *bsp; @@ -516,6 +552,9 @@ bpstat_clear (bsp) *bsp = NULL; } +/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that + is part of the bpstat is copied as well. */ + bpstat bpstat_copy (bs) bpstat bs; @@ -542,6 +581,27 @@ bpstat_copy (bs) return retval; } +/* Find the bpstat associated with this breakpoint */ + +bpstat +bpstat_find_breakpoint(bsp, breakpoint) + bpstat bsp; + struct breakpoint *breakpoint; +{ + if (bsp == NULL) return NULL; + + for (;bsp != NULL; bsp = bsp->next) { + if (bsp->breakpoint_at == breakpoint) return bsp; + } + return NULL; +} + +/* Return the breakpoint number of the first breakpoint we are stopped + at. *BSP upon return is a bpstat which points to the remaining + breakpoints stopped at (but which is not guaranteed to be good for + anything but further calls to bpstat_num). + Return 0 if passed a bpstat which does not indicate any breakpoints. */ + int bpstat_num (bsp) bpstat *bsp; @@ -561,6 +621,8 @@ bpstat_num (bsp) } } +/* Modify BS so that the actions will not be performed. */ + void bpstat_clear_actions (bs) bpstat bs; @@ -589,6 +651,7 @@ cleanup_executing_breakpoints (ignore) location. Any of these commands could cause the process to proceed beyond this point, etc. We look out for such changes by checking the global "breakpoint_proceeded" after each command. */ + void bpstat_do_actions (bsp) bpstat *bsp; @@ -618,19 +681,25 @@ top: goto top; } } - clear_momentary_breakpoints (); executing_breakpoint_commands = 0; discard_cleanups (old_chain); } +/* Print a message indicating what happened. Returns nonzero to + say that only the source line should be printed after this (zero + return means print the frame as well as the source line). */ + int bpstat_print (bs) bpstat bs; { /* bs->breakpoint_at can be NULL if it was a momentary breakpoint which has since been deleted. */ - if (bs == NULL || bs->breakpoint_at == NULL) + if (bs == NULL + || bs->breakpoint_at == NULL + || (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 @@ -643,7 +712,7 @@ bpstat_print (bs) if (!bs->print) return 0; - if (bs->breakpoint_at->address != NULL) + if (bs->breakpoint_at->type == bp_breakpoint) { /* I think the user probably only wants to see one breakpoint number, not all of them. */ @@ -703,7 +772,7 @@ bpstat_alloc (b, cbs) bs->breakpoint_at = b; /* If the condition is false, etc., don't do the commands. */ bs->commands = NULL; - bs->momentary = b->number == -3; + bs->momentary = b->disposition == delete; bs->old_val = NULL; return bs; } @@ -755,15 +824,18 @@ bpstat_stop_status (pc, frame_address) if (b->enable == disabled) continue; - if (b->address != NULL && b->address != bp_addr) + + if (b->type != bp_watchpoint && b->address != bp_addr) 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; - if (b->exp != NULL) /* Watchpoint */ + if (b->type == bp_watchpoint) { int within_current_scope; if (b->exp_valid_block != NULL) @@ -849,7 +921,7 @@ which its expression is valid.\n", b->number); else { /* We will stop here */ - if (b->enable == temporary) + if (b->disposition == disable) b->enable = disabled; bs->commands = b->commands; if (b->silent) @@ -896,12 +968,16 @@ which its expression is valid.\n", b->number); return bs; } +/* Nonzero if we should step constantly (e.g. watchpoints on machines + without hardware support). This isn't related to a specific bpstat, + just to things like whether watchpoints are set. */ + int bpstat_should_step () { struct breakpoint *b; ALL_BREAKPOINTS (b) - if (b->enable != disabled && b->exp != NULL) + if (b->enable == enabled && b->type == bp_watchpoint) return 1; return 0; } @@ -911,50 +987,47 @@ bpstat_should_step () is nonzero, process only watchpoints. */ static void -breakpoint_1 (bnum, watchpoints) +breakpoint_1 (bnum, type) int bnum; - int watchpoints; + enum bptype type; { register struct breakpoint *b; register struct command_line *l; register struct symbol *sym; CORE_ADDR last_addr = (CORE_ADDR)-1; - int header_printed = 0; + int found_a_breakpoint = 0; + static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint", + "longjmp", "longjmp resume"}; + static char *bpdisps[] = {"del", "dis", ""}; + static char bpenables[] = "ny"; + + if (!breakpoint_chain) + { + printf_filtered ("No breakpoints or watchpoints.\n"); + return; + } ALL_BREAKPOINTS (b) - if (bnum == -1 || bnum == b->number) + if (bnum == -1 + || bnum == b->number) { - if (b->address == NULL && !watchpoints) + if (!found_a_breakpoint++) + printf_filtered ("Num Type Disp Enb %sWhat\n", + addressprint ? "Address " : ""); + + printf_filtered ("%-3d %-10s %-4s %-3c ", + b->number, + bptypes[b->type], + bpdisps[b->disposition], + bpenables[b->enable]); + switch (b->type) { - if (bnum == -1) - continue; - error ("That is a watchpoint, not a breakpoint."); - } - if (b->address != NULL && watchpoints) - { - if (bnum == -1) - continue; - error ("That is a breakpoint, not a watchpoint."); - } - - if (!header_printed) - { - if (watchpoints) - printf_filtered (" Enb Expression\n"); - else if (addressprint) - printf_filtered (" Enb Address Where\n"); - else - printf_filtered (" Enb Where\n"); - header_printed = 1; - } - - printf_filtered ("#%-3d %c ", b->number, "nyod"[(int) b->enable]); - if (b->address == NULL) { - printf_filtered (" "); - print_expression (b->exp, stdout); - } else { + case bp_watchpoint: + print_expression (b->exp, stdout); + break; + case bp_breakpoint: if (addressprint) - printf_filtered (" %s ", local_hex_string_custom(b->address, "08")); + printf_filtered ("%s ", local_hex_string_custom(b->address, "08")); last_addr = b->address; if (b->symtab) @@ -962,7 +1035,7 @@ breakpoint_1 (bnum, watchpoints) sym = find_pc_function (b->address); if (sym) { - fputs_filtered (" in ", stdout); + fputs_filtered ("in ", stdout); fputs_demangled (SYMBOL_NAME (sym), stdout, 1); fputs_filtered (" at ", stdout); } @@ -996,19 +1069,14 @@ breakpoint_1 (bnum, watchpoints) } } - if (!header_printed) - { - char *which = watchpoints ? "watch" : "break"; - if (bnum == -1) - printf_filtered ("No %spoints.\n", which); - else - printf_filtered ("No %spoint numbered %d.\n", which, bnum); - } - - /* Compare against (CORE_ADDR)-1 in case some compiler decides - that a comparison of an unsigned with -1 is always false. */ - if (last_addr != (CORE_ADDR)-1) - set_next_address (last_addr); + if (!found_a_breakpoint + && bnum != -1) + 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. */ + if (last_addr != (CORE_ADDR)-1) + set_next_address (last_addr); } /* ARGSUSED */ @@ -1022,7 +1090,7 @@ breakpoints_info (bnum_exp, from_tty) if (bnum_exp) bnum = parse_and_eval_address (bnum_exp); - breakpoint_1 (bnum, 0); + breakpoint_1 (bnum, bp_breakpoint); } /* ARGSUSED */ @@ -1036,7 +1104,7 @@ watchpoints_info (bnum_exp, from_tty) if (bnum_exp) bnum = parse_and_eval_address (bnum_exp); - breakpoint_1 (bnum, 1); + breakpoint_1 (bnum, bp_watchpoint); } /* Print a message describing any breakpoints set at PC. */ @@ -1094,7 +1162,7 @@ check_duplicates (address) register struct breakpoint *b; register int count = 0; - if (address == NULL) /* Watchpoints are uninteresting */ + if (address == 0) /* Watchpoints are uninteresting */ return; ALL_BREAKPOINTS (b) @@ -1131,7 +1199,7 @@ set_raw_breakpoint (sal) b->silent = 0; b->ignore_count = 0; b->commands = NULL; - b->frame = NULL; + b->frame = 0; /* Add this breakpoint to the end of the chain so that a list of breakpoints will come out in order @@ -1152,46 +1220,171 @@ set_raw_breakpoint (sal) return b; } +struct breakpoint *longjmp_breakpoint = NULL; +struct breakpoint *_longjmp_breakpoint = NULL; +struct breakpoint *siglongjmp_breakpoint = NULL; +struct breakpoint *longjmp_resume_breakpoint = NULL; + +static void +create_longjmp_breakpoint_1(func_name, bpt) + char *func_name; + struct breakpoint **bpt; +{ + int i; + struct symtab_and_line sal; + struct breakpoint *b; + + if (*bpt != NULL) + { + delete_breakpoint(*bpt); + *bpt = NULL; + } + + if (func_name != NULL) + { + struct minimal_symbol *m; + + m = lookup_minimal_symbol(func_name, (struct objfile *)NULL); + if (m) + sal.pc = m->address; + else + return; + } + else + sal.pc = 0; + + sal.symtab = NULL; + sal.line = 0; + if (*bpt != NULL) + b = *bpt; + else + b = set_raw_breakpoint(sal); + + if (!b) return; + + b->type = bp_longjmp; + b->disposition = donttouch; + b->enable = disabled; + b->silent = 1; + *bpt = b; +} + +/* Call this routine each time we read a new executable or symbol table + file. */ + +#ifdef GET_LONGJMP_TARGET +void +create_longjmp_breakpoint() +{ + create_longjmp_breakpoint_1("longjmp", &longjmp_breakpoint); + create_longjmp_breakpoint_1("_longjmp", &_longjmp_breakpoint); + create_longjmp_breakpoint_1("siglongjmp", &siglongjmp_breakpoint); + + if ((longjmp_breakpoint || _longjmp_breakpoint || siglongjmp_breakpoint) + && !longjmp_resume_breakpoint) + { + create_longjmp_breakpoint_1(NULL, &longjmp_resume_breakpoint); + if (longjmp_resume_breakpoint) + longjmp_resume_breakpoint->type = bp_longjmp_resume; + } +} +#else +void +create_longjmp_breakpoint() +{ +} +#endif + +/* Call this routine when stepping and nexting to enable a breakpoint if we do + a longjmp(). When we hit that breakpoint, call + set_longjmp_resume_breakpoint() to figure out where we are going. */ + +void +enable_longjmp_breakpoint() +{ + if (longjmp_breakpoint) + longjmp_breakpoint->enable = enabled; + if (_longjmp_breakpoint) + _longjmp_breakpoint->enable = enabled; + if (siglongjmp_breakpoint) + siglongjmp_breakpoint->enable = enabled; +} + +void +disable_longjmp_breakpoint() +{ + if (longjmp_breakpoint) + longjmp_breakpoint->enable = disabled; + if (_longjmp_breakpoint) + _longjmp_breakpoint->enable = disabled; + if (siglongjmp_breakpoint) + siglongjmp_breakpoint->enable = disabled; + if (longjmp_resume_breakpoint) + longjmp_resume_breakpoint->enable = disabled; +} + +/* Call this after hitting the longjmp() breakpoint. Use this to set a new + breakpoint at the target of the jmp_buf. +*/ + +void +set_longjmp_resume_breakpoint(pc, frame) + CORE_ADDR pc; + FRAME frame; +{ + longjmp_resume_breakpoint->address = pc; + longjmp_resume_breakpoint->enable = enabled; + if (frame != NULL) + longjmp_resume_breakpoint->frame = FRAME_FP(frame); + else + longjmp_resume_breakpoint->frame = 0; +} + /* Set a breakpoint that will evaporate an end of command at address specified by SAL. Restrict it to frame FRAME if FRAME is nonzero. */ -void -set_momentary_breakpoint (sal, frame) +struct breakpoint * +set_momentary_breakpoint (sal, frame, type) struct symtab_and_line sal; FRAME frame; + enum bptype type; { register struct breakpoint *b; b = set_raw_breakpoint (sal); - b->number = -3; - b->enable = delete; + b->type = type; + b->enable = enabled; + b->disposition = donttouch; b->frame = (frame ? FRAME_FP (frame) : 0); + return b; } +#if 0 void clear_momentary_breakpoints () { register struct breakpoint *b; ALL_BREAKPOINTS (b) - if (b->number == -3) + if (b->disposition == delete) { delete_breakpoint (b); break; } } +#endif /* Tell the user we have just set a breakpoint B. */ static void mention (b) struct breakpoint *b; { - if (b->exp) + switch (b->type) { + case bp_watchpoint: printf_filtered ("Watchpoint %d: ", b->number); print_expression (b->exp, stdout); - } - else - { + break; + case bp_breakpoint: printf_filtered ("Breakpoint %d at %s", b->number, local_hex_string(b->address)); if (b->symtab) @@ -1222,25 +1415,22 @@ set_breakpoint (s, line, tempflag, addr_string) sal.symtab = s; sal.line = line; - sal.pc = find_line_pc (sal.symtab, sal.line); - if (sal.pc == 0) - error ("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename); - else - { - describe_other_breakpoints (sal.pc); + sal.pc = 0; + resolve_sal_pc (&sal); /* Might error out */ + describe_other_breakpoints (sal.pc); - b = set_raw_breakpoint (sal); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; - b->cond = 0; - b->addr_string = addr_string; - if (tempflag) - b->enable = temporary; + b = set_raw_breakpoint (sal); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->type = bp_breakpoint; + b->cond = 0; + b->addr_string = addr_string; + b->enable = enabled; + b->disposition = tempflag ? delete : donttouch; - mention (b); - } + mention (b); } -#endif +#endif /* 0 */ /* Set a breakpoint according to ARG (function, linenum or *address) and make it temporary if TEMPFLAG is nonzero. */ @@ -1264,7 +1454,6 @@ break_command_1 (arg, tempflag, from_tty) char *addr_end; int i; - CORE_ADDR pc; sals.sals = NULL; sals.nelts = 0; @@ -1312,18 +1501,11 @@ break_command_1 (arg, tempflag, from_tty) if (! sals.nelts) return; + /* 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++) { - sal = sals.sals[i]; - if (sal.pc == 0 && sal.symtab != 0) - { - pc = find_line_pc (sal.symtab, sal.line); - if (pc == 0) - error ("No line %d in file \"%s\".", - sal.line, sal.symtab->filename); - } - else - pc = sal.pc; + resolve_sal_pc (&sals.sals[i]); while (arg && *arg) { @@ -1332,15 +1514,15 @@ break_command_1 (arg, tempflag, from_tty) { arg += 2; cond_start = arg; - cond = parse_exp_1 (&arg, block_for_pc (pc), 0); + cond = parse_exp_1 (&arg, block_for_pc (sals.sals[i].pc), 0); cond_end = arg; } else error ("Junk at end of arguments."); } - sals.sals[i].pc = pc; } + /* Now set all the breakpoints. */ for (i = 0; i < sals.nelts; i++) { sal = sals.sals[i]; @@ -1351,6 +1533,7 @@ break_command_1 (arg, tempflag, from_tty) b = set_raw_breakpoint (sal); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; + b->type = bp_breakpoint; b->cond = cond; if (addr_start) @@ -1358,8 +1541,8 @@ break_command_1 (arg, tempflag, from_tty) if (cond_start) b->cond_string = savestring (cond_start, cond_end - cond_start); - if (tempflag) - b->enable = temporary; + b->enable = enabled; + b->disposition = tempflag ? delete : donttouch; mention (b); } @@ -1372,6 +1555,24 @@ break_command_1 (arg, tempflag, from_tty) free (sals.sals); } +/* Helper function for break_command_1 and disassemble_command. */ + +void +resolve_sal_pc (sal) + struct symtab_and_line *sal; +{ + CORE_ADDR pc; + + if (sal->pc == 0 && sal->symtab != 0) + { + pc = find_line_pc (sal->symtab, sal->line); + if (pc == 0) + error ("No line %d in file \"%s\".", + sal->line, sal->symtab->filename); + sal->pc = pc; + } +} + void break_command (arg, from_tty) char *arg; @@ -1400,7 +1601,7 @@ watch_command (arg, from_tty) struct block *exp_valid_block; struct value *val; - sal.pc = NULL; + sal.pc = 0; sal.symtab = NULL; sal.line = 0; @@ -1415,6 +1616,8 @@ watch_command (arg, from_tty) b = set_raw_breakpoint (sal); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; + b->type = bp_watchpoint; + b->disposition = donttouch; b->exp = exp; b->exp_valid_block = exp_valid_block; b->val = val; @@ -1436,6 +1639,8 @@ until_break_command (arg, from_tty) struct symtabs_and_lines sals; struct symtab_and_line sal; FRAME prev_frame = get_prev_frame (selected_frame); + struct breakpoint *breakpoint; + struct cleanup *old_chain; clear_proceed_status (); @@ -1457,14 +1662,12 @@ until_break_command (arg, from_tty) if (*arg) error ("Junk at end of arguments."); - if (sal.pc == 0 && sal.symtab != 0) - sal.pc = find_line_pc (sal.symtab, sal.line); + resolve_sal_pc (&sal); - if (sal.pc == 0) - error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename); - - set_momentary_breakpoint (sal, selected_frame); + breakpoint = set_momentary_breakpoint (sal, selected_frame, bp_until); + old_chain = make_cleanup(delete_breakpoint, breakpoint); + /* Keep within the current frame */ if (prev_frame) @@ -1474,10 +1677,12 @@ until_break_command (arg, from_tty) fi = get_frame_info (prev_frame); sal = find_pc_line (fi->pc, 0); sal.pc = fi->pc; - set_momentary_breakpoint (sal, prev_frame); + breakpoint = set_momentary_breakpoint (sal, prev_frame, bp_until); + make_cleanup(delete_breakpoint, breakpoint); } proceed (-1, -1, 0); + do_cleanups(old_chain); } #if 0 @@ -1579,7 +1784,6 @@ static struct symtabs_and_lines get_catch_sals (this_level_only) int this_level_only; { - extern struct blockvector *blockvector_for_pc (); register struct blockvector *bl; register struct block *block; int index, have_default = 0; @@ -1692,7 +1896,7 @@ get_catch_sals (this_level_only) /* Commands to deal with catching exceptions. */ -void +static void catch_command_1 (arg, tempflag, from_tty) char *arg; int tempflag; @@ -1707,7 +1911,6 @@ catch_command_1 (arg, tempflag, from_tty) register struct breakpoint *b; char *save_arg; int i; - CORE_ADDR pc; sal.line = sal.pc = sal.end = 0; sal.symtab = 0; @@ -1737,28 +1940,18 @@ catch_command_1 (arg, tempflag, from_tty) save_arg = arg; for (i = 0; i < sals.nelts; i++) { - sal = sals.sals[i]; - if (sal.pc == 0 && sal.symtab != 0) - { - pc = find_line_pc (sal.symtab, sal.line); - if (pc == 0) - error ("No line %d in file \"%s\".", - sal.line, sal.symtab->filename); - } - else - pc = sal.pc; + resolve_sal_pc (&sals.sals[i]); while (arg && *arg) { if (arg[0] == 'i' && arg[1] == 'f' && (arg[2] == ' ' || arg[2] == '\t')) - cond = (struct expression *) parse_exp_1 ((arg += 2, &arg), - block_for_pc (pc), 0); + cond = parse_exp_1 ((arg += 2, &arg), + block_for_pc (sals.sals[i].pc), 0); else error ("Junk at end of arguments."); } arg = save_arg; - sals.sals[i].pc = pc; } for (i = 0; i < sals.nelts; i++) @@ -1769,10 +1962,12 @@ catch_command_1 (arg, tempflag, from_tty) describe_other_breakpoints (sal.pc); b = set_raw_breakpoint (sal); - b->number = ++breakpoint_count; + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->type = bp_breakpoint; b->cond = cond; - if (tempflag) - b->enable = temporary; + b->enable = enabled; + b->disposition = tempflag ? delete : donttouch; printf ("Breakpoint %d at %s", b->number, local_hex_string(b->address)); if (b->symtab) @@ -1870,7 +2065,7 @@ clear_command (arg, from_tty) ALL_BREAKPOINTS (b) while (b->next - && b->next->address != NULL + && b->next->type != bp_watchpoint && (sal.pc ? b->next->address == sal.pc : (b->next->symtab == sal.symtab && b->next->line_number == sal.line))) @@ -1911,13 +2106,13 @@ breakpoint_auto_delete (bs) bpstat bs; { for (; bs; bs = bs->next) - if (bs->breakpoint_at && bs->breakpoint_at->enable == delete) + if (bs->breakpoint_at && bs->breakpoint_at->disposition == delete) delete_breakpoint (bs->breakpoint_at); } /* Delete a breakpoint and clean up all traces of it in the data structures. */ -static void +void delete_breakpoint (bpt) struct breakpoint *bpt; { @@ -1947,7 +2142,7 @@ delete_breakpoint (bpt) if (bpt->addr_string != NULL) free (bpt->addr_string); - if (xgdb_verbose && bpt->number >=0) + if (xgdb_verbose && bpt->type == bp_breakpoint) printf ("breakpoint #%d deleted\n", bpt->number); /* Be sure no bpstat's are pointing at it after it's been freed. */ @@ -1958,8 +2153,6 @@ delete_breakpoint (bpt) free (bpt); } -static void map_breakpoint_numbers (); - static void delete_command (arg, from_tty) char *arg; @@ -1992,36 +2185,34 @@ breakpoint_re_set_one (bint) struct breakpoint *b = (struct breakpoint *)bint; /* get past catch_errs */ int i; struct symtabs_and_lines sals; - struct symtab_and_line sal; char *s; + enum enable save_enable; - if (b->address != NULL && b->addr_string != NULL) + if (b->type != bp_watchpoint && b->addr_string != NULL) { + /* In case we have a problem, disable this breakpoint. We'll restore + its status if we succeed. */ + save_enable = b->enable; + b->enable = disabled; + s = b->addr_string; sals = decode_line_1 (&s, 1, (struct symtab *)NULL, 0); for (i = 0; i < sals.nelts; i++) { - sal = sals.sals[i]; - - b->symtab = sal.symtab; - b->line_number = sal.line; - if (sal.pc == 0 && sal.symtab != 0) - { - sal.pc = find_line_pc (sal.symtab, sal.line); - if (sal.pc == 0) - error ("No line %d in file \"%s\".", - sal.line, sal.symtab->filename); - } - b->address = sal.pc; + resolve_sal_pc (&sals.sals[i]); + b->symtab = sals.sals[i].symtab; + b->line_number = sals.sals[i].line; + b->address = sals.sals[i].pc; if (b->cond_string != NULL) { s = b->cond_string; - b->cond = parse_exp_1 (&s, block_for_pc (sal.pc), 0); + b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0); } check_duplicates (b->address); + b->enable = save_enable; /* Restore it, this worked. */ mention (b); } free (sals.sals); @@ -2039,12 +2230,14 @@ void breakpoint_re_set () { struct breakpoint *b; + static char message1[] = "Error in re-setting breakpoint %d:\n"; + char message[sizeof (message1) + 30 /* slop */]; ALL_BREAKPOINTS (b) { b->symtab = 0; /* Be sure we don't point to old dead symtab */ - (void) catch_errors (breakpoint_re_set_one, (char *) b, - "Error in re-setting breakpoint:\n"); + sprintf (message, message1, b->number); /* Format possible error msg */ + (void) catch_errors (breakpoint_re_set_one, (char *) b, message); } /* Blank line to finish off all those mention() messages we just printed. */ @@ -2123,7 +2316,7 @@ ignore_command (args, from_tty) static void map_breakpoint_numbers (args, function) char *args; - void (*function) (); + void (*function) PARAMS ((struct breakpoint *)); { register char *p = args; char *p1; @@ -2157,11 +2350,11 @@ enable_breakpoint (bpt) { bpt->enable = enabled; - if (xgdb_verbose && bpt->number >= 0) + if (xgdb_verbose && bpt->type == bp_breakpoint) printf ("breakpoint #%d enabled\n", bpt->number); check_duplicates (bpt->address); - if (bpt->val != NULL) + if (bpt->type == bp_watchpoint) { if (bpt->exp_valid_block != NULL && !contained_in (get_selected_block (), bpt->exp_valid_block)) @@ -2199,7 +2392,7 @@ disable_breakpoint (bpt) { bpt->enable = disabled; - if (xgdb_verbose && bpt->number >= 0) + if (xgdb_verbose && bpt->type == bp_breakpoint) printf ("breakpoint #%d disabled\n", bpt->number); check_duplicates (bpt->address); @@ -2223,7 +2416,8 @@ static void enable_once_breakpoint (bpt) struct breakpoint *bpt; { - bpt->enable = temporary; + bpt->enable = enabled; + bpt->disposition = disable; check_duplicates (bpt->address); } @@ -2241,7 +2435,8 @@ static void enable_delete_breakpoint (bpt) struct breakpoint *bpt; { - bpt->enable = delete; + bpt->enable = enabled; + bpt->disposition = delete; check_duplicates (bpt->address); } |