along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include <stdio.h>
-#include <ctype.h>
#include "defs.h"
+#include <ctype.h>
#include "symtab.h"
#include "frame.h"
#include "breakpoint.h"
#include "target.h"
#include "language.h"
#include <string.h>
+#include "demangle.h"
/* local function prototypes */
static void
describe_other_breakpoints PARAMS ((CORE_ADDR));
-static void
-watchpoints_info PARAMS ((char *, int));
-
static void
breakpoints_info PARAMS ((char *, int));
/* Are we executing breakpoint commands? */
static int executing_breakpoint_commands;
+/* Walk the following statement or block through all breakpoints.
+ ALL_BREAKPOINTS_SAFE does so even if the statment deletes the current
+ breakpoint. */
+
#define ALL_BREAKPOINTS(b) for (b = breakpoint_chain; b; b = b->next)
+#define ALL_BREAKPOINTS_SAFE(b,tmp) \
+ for (b = breakpoint_chain; \
+ b? (tmp=b->next, 1): 0; \
+ b = tmp)
+
/* Chain of all breakpoints defined. */
struct breakpoint *breakpoint_chain;
}
else
{
+ if (*p == '-')
+ ++p;
while (*p >= '0' && *p <= '9')
++p;
if (p == *pp)
{
if (b->cond)
{
- free (b->cond);
+ free ((PTR)b->cond);
b->cond = 0;
}
if (b->cond_string != NULL)
- free (b->cond_string);
+ free ((PTR)b->cond_string);
if (*p == 0)
{
b->cond = 0;
b->cond_string = NULL;
if (from_tty)
- printf ("Breakpoint %d now unconditional.\n", bnum);
+ printf_filtered ("Breakpoint %d now unconditional.\n", bnum);
}
else
{
if (b->number == bnum)
{
if (from_tty && input_from_terminal_p ())
- {
- printf ("Type commands for when breakpoint %d is hit, one per line.\n\
+ printf_filtered ("Type commands for when breakpoint %d is hit, one per line.\n\
End with a line saying just \"end\".\n", bnum);
- fflush (stdout);
- }
l = read_command_lines ();
free_command_lines (&b->commands);
b->commands = l;
bptlen -= (membpt + bptlen) - (memaddr + len);
}
- bcopy (b->shadow_contents + bptoffset,
- myaddr + membpt - memaddr, bptlen);
+ memcpy (myaddr + membpt - memaddr,
+ b->shadow_contents + bptoffset, bptlen);
if (membpt > memaddr)
{
q = p->next;
if (p->old_val != NULL)
value_free (p->old_val);
- free (p);
+ free ((PTR)p);
p = q;
}
*bsp = NULL;
for (; bs != NULL; bs = bs->next)
{
tmp = (bpstat) xmalloc (sizeof (*tmp));
- bcopy (bs, tmp, sizeof (*tmp));
+ memcpy (tmp, bs, sizeof (*tmp));
if (p == NULL)
/* This is the first thing in the chain. */
retval = tmp;
int real_breakpoint = 0;
#endif
/* Root of the chain of bpstat's */
- struct bpstat__struct root_bs[1];
+ struct bpstat root_bs[1];
/* Pointer to the last thing in the chain currently. */
bpstat bs = root_bs;
is nonzero, process only watchpoints. */
static void
-breakpoint_1 (bnum, type)
+breakpoint_1 (bnum, allflag)
int bnum;
- enum bptype type;
+ int allflag;
{
register struct breakpoint *b;
register struct command_line *l;
int found_a_breakpoint = 0;
static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint",
"longjmp", "longjmp resume"};
- static char *bpdisps[] = {"del", "dis", ""};
+ static char *bpdisps[] = {"del", "dis", "keep"};
static char bpenables[] = "ny";
if (!breakpoint_chain)
if (bnum == -1
|| bnum == b->number)
{
+/* We only print out user settable breakpoints unless the allflag is set. */
+ if (!allflag
+ && b->type != bp_breakpoint
+ && b->type != bp_watchpoint)
+ continue;
+
if (!found_a_breakpoint++)
- printf_filtered ("Num Type Disp Enb %sWhat\n",
+ printf_filtered ("Num Type Disp Enb %sWhat\n",
addressprint ? "Address " : "");
- printf_filtered ("%-3d %-10s %-4s %-3c ",
+ printf_filtered ("%-3d %-14s %-4s %-3c ",
b->number,
- bptypes[b->type],
- bpdisps[b->disposition],
- bpenables[b->enable]);
+ bptypes[(int)b->type],
+ bpdisps[(int)b->disposition],
+ bpenables[(int)b->enable]);
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:
if (addressprint)
printf_filtered ("%s ", local_hex_string_custom(b->address, "08"));
if (sym)
{
fputs_filtered ("in ", stdout);
- fputs_demangled (SYMBOL_NAME (sym), stdout, 1);
+ fputs_demangled (SYMBOL_NAME (sym), stdout,
+ DMGL_ANSI | DMGL_PARAMS);
fputs_filtered (" at ", stdout);
}
fputs_filtered (b->symtab->filename, stdout);
if (bnum_exp)
bnum = parse_and_eval_address (bnum_exp);
- breakpoint_1 (bnum, bp_breakpoint);
+ breakpoint_1 (bnum, 0);
}
+#if MAINTENANCE_CMDS
+
/* ARGSUSED */
static void
-watchpoints_info (bnum_exp, from_tty)
+maintenance_info_breakpoints (bnum_exp, from_tty)
char *bnum_exp;
int from_tty;
{
if (bnum_exp)
bnum = parse_and_eval_address (bnum_exp);
- breakpoint_1 (bnum, bp_watchpoint);
+ breakpoint_1 (bnum, 1);
}
+#endif
+
/* Print a message describing any breakpoints set at PC. */
static void
register struct breakpoint *b, *b1;
b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
- bzero (b, sizeof *b);
+ memset (b, 0, sizeof (*b));
b->address = sal.pc;
b->symtab = sal.symtab;
b->line_number = sal.line;
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)
+create_longjmp_breakpoint(func_name)
char *func_name;
- struct breakpoint **bpt;
{
- int i;
struct symtab_and_line sal;
struct breakpoint *b;
-
- if (*bpt != NULL)
- {
- delete_breakpoint(*bpt);
- *bpt = NULL;
- }
+ static int internal_breakpoint_number = -1;
if (func_name != NULL)
{
sal.symtab = NULL;
sal.line = 0;
- if (*bpt != NULL)
- b = *bpt;
- else
- b = set_raw_breakpoint(sal);
+ b = set_raw_breakpoint(sal);
if (!b) return;
- b->type = bp_longjmp;
+ b->type = func_name != NULL ? bp_longjmp : bp_longjmp_resume;
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;
- }
+ if (func_name)
+ b->addr_string = strsave(func_name);
+ b->number = internal_breakpoint_number--;
}
-#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
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;
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->type == bp_longjmp)
+ {
+ b->enable = enabled;
+ check_duplicates (b->address);
+ }
}
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;
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if ( b->type == bp_longjmp
+ || b->type == bp_longjmp_resume)
+ {
+ b->enable = disabled;
+ check_duplicates (b->address);
+ }
}
/* Call this after hitting the longjmp() breakpoint. Use this to set a new
breakpoint at the target of the jmp_buf.
+
+ FIXME - This ought to be done by setting a temporary breakpoint that gets
+ deleted automatically...
*/
void
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;
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->type == bp_longjmp_resume)
+ {
+ b->address = pc;
+ b->enable = enabled;
+ if (frame != NULL)
+ b->frame = FRAME_FP(frame);
+ else
+ b->frame = 0;
+ check_duplicates (b->address);
+ return;
+ }
}
/* Set a breakpoint that will evaporate an end of command
if (b->symtab)
printf_filtered (": file %s, line %d.",
b->symtab->filename, b->line_number);
+ break;
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ break;
}
printf_filtered ("\n");
}
printf ("Multiple breakpoints were set.\n");
printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
}
- free (sals.sals);
+ free ((PTR)sals.sals);
}
/* Helper function for break_command_1 and disassemble_command. */
error ("Couldn't get information on specified line.");
sal = sals.sals[0];
- free (sals.sals); /* malloc'd, so freed */
+ free ((PTR)sals.sals); /* malloc'd, so freed */
if (*arg)
error ("Junk at end of arguments.");
bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
blocks_searched = (char *) alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
- bzero (blocks_searched, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+ memset (blocks_searched, 0, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
while (block != 0)
{
printf ("Multiple breakpoints were set.\n");
printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
}
- free (sals.sals);
+ free ((PTR)sals.sals);
}
#if 0
}
if (from_tty) putchar ('\n');
}
- free (sals.sals);
+ free ((PTR)sals.sals);
}
\f
/* Delete breakpoint in BS if they are `delete' breakpoints.
free_command_lines (&bpt->commands);
if (bpt->cond)
- free (bpt->cond);
+ free ((PTR)bpt->cond);
if (bpt->cond_string != NULL)
- free (bpt->cond_string);
+ free ((PTR)bpt->cond_string);
if (bpt->addr_string != NULL)
- free (bpt->addr_string);
+ free ((PTR)bpt->addr_string);
if (xgdb_verbose && bpt->type == bp_breakpoint)
printf ("breakpoint #%d deleted\n", bpt->number);
for (bs = stop_bpstat; bs; bs = bs->next)
if (bs->breakpoint_at == bpt)
bs->breakpoint_at = NULL;
- free (bpt);
+ free ((PTR)bpt);
}
static void
char *s;
enum enable save_enable;
- if (b->type != bp_watchpoint && b->addr_string != NULL)
+ switch (b->type)
{
+ case bp_breakpoint:
+ if (b->addr_string == NULL)
+ {
+ /* Anything without a string can't be re-set. */
+ delete_breakpoint (b);
+ return 0;
+ }
/* In case we have a problem, disable this breakpoint. We'll restore
its status if we succeed. */
save_enable = b->enable;
for (i = 0; i < sals.nelts; i++)
{
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)
+ if (b->symtab != sals.sals[i].symtab
+ || b->line_number != sals.sals[i].line
+ || b->address != sals.sals[i].pc)
{
- s = b->cond_string;
- b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
- }
+ 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 (sals.sals[i].pc), 0);
+ }
- check_duplicates (b->address);
+ check_duplicates (b->address);
+ mention (b);
+ }
b->enable = save_enable; /* Restore it, this worked. */
- mention (b);
}
- free (sals.sals);
- }
- else
- {
- /* Anything without a string can't be re-set. */
+ free ((PTR)sals.sals);
+ break;
+ case bp_watchpoint:
+ /* FIXME! This is the wrong thing to do.... */
+ delete_breakpoint (b);
+ break;
+ default:
+ printf_filtered ("Deleting unknown breakpoint type %d\n", b->type);
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
delete_breakpoint (b);
+ break;
}
+
return 0;
}
void
breakpoint_re_set ()
{
- struct breakpoint *b;
+ struct breakpoint *b, *temp;
static char message1[] = "Error in re-setting breakpoint %d:\n";
char message[sizeof (message1) + 30 /* slop */];
- ALL_BREAKPOINTS (b)
+ if (current_source_symtab == NULL)
+ {
+ select_source_symtab (NULL);
+ }
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
{
- b->symtab = 0; /* Be sure we don't point to old dead symtab */
sprintf (message, message1, b->number); /* Format possible error msg */
- (void) catch_errors (breakpoint_re_set_one, (char *) b, message);
+ catch_errors (breakpoint_re_set_one, (char *) b, message);
}
+ create_longjmp_breakpoint("longjmp");
+ create_longjmp_breakpoint("_longjmp");
+ create_longjmp_breakpoint("siglongjmp");
+ create_longjmp_breakpoint(NULL);
+
+#if 0
+ /* Took this out (temporaliy at least), since it produces an extra
+ blank line at startup. This messes up the gdbtests. -PB */
/* Blank line to finish off all those mention() messages we just printed. */
printf_filtered ("\n");
+#endif
}
\f
/* Set ignore-count of breakpoint number BPTNUM to COUNT.
if (!from_tty)
return;
else if (count == 0)
- printf ("Will stop next time breakpoint %d is reached.", bptnum);
+ printf_filtered ("Will stop next time breakpoint %d is reached.",
+ bptnum);
else if (count == 1)
- printf ("Will ignore next crossing of breakpoint %d.", bptnum);
+ printf_filtered ("Will ignore next crossing of breakpoint %d.",
+ bptnum);
else
- printf ("Will ignore next %d crossings of breakpoint %d.",
+ printf_filtered ("Will ignore next %d crossings of breakpoint %d.",
count, bptnum);
return;
}
set_ignore_count (num,
longest_to_int (value_as_long (parse_and_eval (p))),
from_tty);
- printf ("\n");
+ printf_filtered ("\n");
}
\f
/* Call FUNCTION on each of the breakpoints
struct breakpoint *bpt;
if (args == 0)
ALL_BREAKPOINTS (bpt)
- enable_breakpoint (bpt);
+ switch (bpt->type)
+ {
+ case bp_breakpoint:
+ case bp_watchpoint:
+ enable_breakpoint (bpt);
+ default:
+ continue;
+ }
else
map_breakpoint_numbers (args, enable_breakpoint);
}
bpt->enable = disabled;
if (xgdb_verbose && bpt->type == bp_breakpoint)
- printf ("breakpoint #%d disabled\n", bpt->number);
+ printf_filtered ("breakpoint #%d disabled\n", bpt->number);
check_duplicates (bpt->address);
}
register struct breakpoint *bpt;
if (args == 0)
ALL_BREAKPOINTS (bpt)
- disable_breakpoint (bpt);
+ switch (bpt->type)
+ {
+ case bp_breakpoint:
+ case bp_watchpoint:
+ disable_breakpoint (bpt);
+ default:
+ continue;
+ }
else
map_breakpoint_numbers (args, disable_breakpoint);
}
return sals;
}
\f
-
-/* Chain containing all defined enable commands. */
-
-extern struct cmd_list_element
- *enablelist, *disablelist,
- *deletelist, *enablebreaklist;
-
-extern struct cmd_list_element *cmdlist;
-
void
_initialize_breakpoint ()
{
add_com_alias ("brea", "break", class_run, 1);
add_info ("breakpoints", breakpoints_info,
- "Status of all breakpoints, or breakpoint number NUMBER.\n\
-Second column is \"y\" for enabled breakpoint, \"n\" for disabled,\n\
-\"o\" for enabled once (disable when hit), \"d\" for enable but delete when hit.\n\
-Then come the address and the file/line number.\n\n\
+ "Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
+The \"Type\" column indicates one of:\n\
+\tbreakpoint - normal breakpoint\n\
+\twatchpoint - watchpoint\n\
+The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
+the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
+breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
+address and file/line number respectively.\n\n\
Convenience variable \"$_\" and default examine address for \"x\"\n\
are set to the address of the last breakpoint listed.\n\n\
Convenience variable \"$bpnum\" contains the number of the last\n\
breakpoint set.");
+#if MAINTENANCE_CMDS
+
+ add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints,
+ "Status of all breakpoints, or breakpoint number NUMBER.\n\
+The \"Type\" column indicates one of:\n\
+\tbreakpoint - normal breakpoint\n\
+\twatchpoint - watchpoint\n\
+\tlongjmp - internal breakpoint used to step through longjmp()\n\
+\tlongjmp resume - internal breakpoint at the target of longjmp()\n\
+\tuntil - internal breakpoint used by the \"until\" command\n\
+\tfinish - internal breakpoint used by the \"finish\" command\n\
+The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
+the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
+breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
+address and file/line number respectively.\n\n\
+Convenience variable \"$_\" and default examine address for \"x\"\n\
+are set to the address of the last breakpoint listed.\n\n\
+Convenience variable \"$bpnum\" contains the number of the last\n\
+breakpoint set.",
+ &maintenanceinfolist);
+
+#endif /* MAINTENANCE_CMDS */
+
add_com ("catch", class_breakpoint, catch_command,
"Set breakpoints to catch exceptions that are raised.\n\
Argument may be a single exception to catch, multiple exceptions\n\
A watchpoint stops execution of your program whenever the value of\n\
an expression changes.");
- add_info ("watchpoints", watchpoints_info,
- "Status of all watchpoints, or watchpoint number NUMBER.\n\
-Second column is \"y\" for enabled watchpoints, \"n\" for disabled.");
+ add_info ("watchpoints", breakpoints_info,
+ "Synonym for ``info breakpoints''.");
}
+
+#ifdef IBM6000_TARGET
+/* Where should this function go? It is used by AIX only. FIXME. */
+
+/* Breakpoint address relocation used to be done in breakpoint_re_set(). That
+ approach the following problem:
+
+ before running the program, if a file is list, then a breakpoint is
+ set (just the line number), then if we switch into another file and run
+ the program, just a line number as a breakpoint address was not
+ descriptive enough and breakpoint was ending up in a different file's
+ similar line.
+
+ I don't think any other platform has this breakpoint relocation problem, so this
+ is not an issue for other platforms. */
+
+void
+fixup_breakpoints (low, high, delta)
+ CORE_ADDR low;
+ CORE_ADDR high;
+ CORE_ADDR delta;
+{
+ struct breakpoint *b;
+ extern struct breakpoint *breakpoint_chain;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->address >= low && b->address <= high)
+ b->address += delta;
+ }
+}
+#endif