⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 breakpoint.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Everything about breakpoints, for GDB.   Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "defs.h"#include <ctype.h>#include "symtab.h"#include "frame.h"#include "breakpoint.h"#include "gdbtypes.h"#include "expression.h"#include "gdbcore.h"#include "gdbcmd.h"#include "value.h"#include "ctype.h"#include "command.h"#include "inferior.h"#include "target.h"#include "language.h"#include <string.h>#include "demangle.h"/* local function prototypes */static voidcatch_command_1 PARAMS ((char *, int, int));static voidenable_delete_command PARAMS ((char *, int));static voidenable_delete_breakpoint PARAMS ((struct breakpoint *));static voidenable_once_command PARAMS ((char *, int));static voidenable_once_breakpoint PARAMS ((struct breakpoint *));static voiddisable_command PARAMS ((char *, int));static voiddisable_breakpoint PARAMS ((struct breakpoint *));static voidenable_command PARAMS ((char *, int));static voidenable_breakpoint PARAMS ((struct breakpoint *));static voidmap_breakpoint_numbers PARAMS ((char *,	void (*)(struct breakpoint *)));static voidignore_command PARAMS ((char *, int));static intbreakpoint_re_set_one PARAMS ((char *));static voiddelete_command PARAMS ((char *, int));static voidclear_command PARAMS ((char *, int));static voidcatch_command PARAMS ((char *, int));static struct symtabs_and_linesget_catch_sals PARAMS ((int));static voidwatch_command PARAMS ((char *, int));static voidtbreak_command PARAMS ((char *, int));static voidbreak_command_1 PARAMS ((char *, int, int));static voidmention PARAMS ((struct breakpoint *));static struct breakpoint *set_raw_breakpoint PARAMS ((struct symtab_and_line));static voidcheck_duplicates PARAMS ((CORE_ADDR));static voiddescribe_other_breakpoints PARAMS ((CORE_ADDR));static voidbreakpoints_info PARAMS ((char *, int));static voidbreakpoint_1 PARAMS ((int, int));static bpstatbpstat_alloc PARAMS ((struct breakpoint *, bpstat));static intbreakpoint_cond_eval PARAMS ((char *));static voidcleanup_executing_breakpoints PARAMS ((int));static voidcommands_command PARAMS ((char *, int));static voidcondition_command PARAMS ((char *, int));static intget_number PARAMS ((char **));static voidset_breakpoint_count PARAMS ((int));extern int addressprint;		/* Print machine addresses? */extern int demangle;			/* Print de-mangled symbol names? *//* 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;/* Number of last breakpoint made.  */static int breakpoint_count;/* Set breakpoint count to NUM.  */static voidset_breakpoint_count (num)     int num;{  breakpoint_count = num;  set_internalvar (lookup_internalvar ("bpnum"),		   value_from_longest (builtin_type_int, (LONGEST) num));}/* Default address, symtab and line to put a breakpoint at   for "break" command with no arg.   if default_breakpoint_valid is zero, the other three are   not valid, and "break" with no arg is an error.   This set by print_stack_frame, which calls set_default_breakpoint.  */int default_breakpoint_valid;CORE_ADDR default_breakpoint_address;struct symtab *default_breakpoint_symtab;int default_breakpoint_line;/* Flag indicating extra verbosity for xgdb.  */extern int xgdb_verbose;/* *PP is a string denoting a breakpoint.  Get the number of the breakpoint.   Advance *PP after the string and any trailing whitespace.   Currently the string can either be a number or "$" followed by the name   of a convenience variable.  Making it an expression wouldn't work well   for map_breakpoint_numbers (e.g. "4 + 5 + 6").  */static intget_number (pp)     char **pp;{  int retval;  char *p = *pp;  if (p == NULL)    /* Empty line means refer to the last breakpoint.  */    return breakpoint_count;  else if (*p == '$')    {      /* Make a copy of the name, so we can null-terminate it	 to pass to lookup_internalvar().  */      char *varname;      char *start = ++p;      value val;      while (isalnum (*p) || *p == '_')	p++;      varname = (char *) alloca (p - start + 1);      strncpy (varname, start, p - start);      varname[p - start] = '\0';      val = value_of_internalvar (lookup_internalvar (varname));      if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_INT)	error ("Convenience variables used to specify breakpoints must have integer values."	       );      retval = (int) value_as_long (val);    }  else    {      if (*p == '-')	++p;      while (*p >= '0' && *p <= '9')	++p;      if (p == *pp)	/* There is no number here.  (e.g. "cond a == b").  */	error_no_arg ("breakpoint number");      retval = atoi (*pp);    }  if (!(isspace (*p) || *p == '\0'))    error ("breakpoint number expected");  while (isspace (*p))    p++;  *pp = p;  return retval;}/* condition N EXP -- set break condition of breakpoint N to EXP.  */static voidcondition_command (arg, from_tty)     char *arg;     int from_tty;{  register struct breakpoint *b;  char *p;  register int bnum;  if (arg == 0)    error_no_arg ("breakpoint number");  p = arg;  bnum = get_number (&p);  ALL_BREAKPOINTS (b)    if (b->number == bnum)      {	if (b->cond)	  {	    free ((PTR)b->cond);	    b->cond = 0;	  }	if (b->cond_string != NULL)	  free ((PTR)b->cond_string);	if (*p == 0)	  {	    b->cond = 0;	    b->cond_string = NULL;	    if (from_tty)	      printf_filtered ("Breakpoint %d now unconditional.\n", bnum);	  }	else	  {	    arg = p;	    /* I don't know if it matters whether this is the string the user	       typed in or the decompiled expression.  */	    b->cond_string = savestring (arg, strlen (arg));	    b->cond = parse_exp_1 (&arg, block_for_pc (b->address), 0);	    if (*arg)	      error ("Junk at end of expression");	  }	return;      }  error ("No breakpoint number %d.", bnum);}/* ARGSUSED */static voidcommands_command (arg, from_tty)     char *arg;     int from_tty;{  register struct breakpoint *b;  char *p;  register int bnum;  struct command_line *l;  /* If we allowed this, we would have problems with when to     free the storage, if we change the commands currently     being read from.  */  if (executing_breakpoint_commands)    error ("Can't use the \"commands\" command among a breakpoint's commands.");  p = arg;  bnum = get_number (&p);  if (p && *p)    error ("Unexpected extra arguments following breakpoint number.");        ALL_BREAKPOINTS (b)    if (b->number == bnum)      {	if (from_tty && input_from_terminal_p ())	  printf_filtered ("Type commands for when breakpoint %d is hit, one per line.\n\End with a line saying just \"end\".\n", bnum);	l = read_command_lines (from_tty);	free_command_lines (b->commands);	b->commands = l;	return;      }  error ("No breakpoint number %d.", 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.   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.  */intread_memory_nobpt (memaddr, myaddr, len)     CORE_ADDR memaddr;     char *myaddr;     unsigned len;{  int status;  struct breakpoint *b;  if (memory_breakpoint_size < 0)    /* No breakpoints on this machine.  */    return target_read_memory (memaddr, myaddr, len);    ALL_BREAKPOINTS (b)    {      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	   we are reading.  */	continue;      else if (b->address >= memaddr + len)	/* The breakpoint is entirely after the chunk of memory we	   are reading.  */	continue;      else	{	  /* Copy the breakpoint from the shadow contents, and recurse	     for the things before and after.  */	  	  /* Addresses and length of the part of the breakpoint that	     we need to copy.  */	  CORE_ADDR membpt = b->address;	  unsigned int bptlen = memory_breakpoint_size;	  /* Offset within shadow_contents.  */	  int bptoffset = 0;	  	  if (membpt < memaddr)	    {	      /* Only copy the second part of the breakpoint.  */	      bptlen -= memaddr - membpt;	      bptoffset = memaddr - membpt;	      membpt = memaddr;	    }	  if (membpt + bptlen > memaddr + len)	    {	      /* Only copy the first part of the breakpoint.  */	      bptlen -= (membpt + bptlen) - (memaddr + len);	    }	  memcpy (myaddr + membpt - memaddr, 		  b->shadow_contents + bptoffset, bptlen);	  if (membpt > memaddr)	    {	      /* Copy the section of memory before the breakpoint.  */	      status = read_memory_nobpt (memaddr, myaddr, membpt - memaddr);	      if (status != 0)		return status;	    }	  if (membpt + bptlen < memaddr + len)	    {	      /* Copy the section of memory after the breakpoint.  */	      status = read_memory_nobpt		(membpt + bptlen,		 myaddr + membpt + bptlen - memaddr,		 memaddr + len - (membpt + bptlen));	      if (status != 0)		return status;	    }	  return 0;	}    }  /* Nothing overlaps.  Just call read_memory_noerr.  */  return target_read_memory (memaddr, myaddr, len);}/* insert_breakpoints is used when starting or continuing the program.   remove_breakpoints is used when the program stops.   Both return zero if successful,   or an `errno' value if could not write the inferior.  */intinsert_breakpoints (){  register struct breakpoint *b;  int val = 0;  int disabled_breaks = 0;  ALL_BREAKPOINTS (b)    if (b->type != bp_watchpoint	&& b->enable != disabled	&& ! b->inserted	&& ! b->duplicate)      {	val = target_insert_breakpoint(b->address, b->shadow_contents);	if (val)	  {	    /* Can't set the breakpoint.  */#if defined (DISABLE_UNSETTABLE_BREAK)	    if (DISABLE_UNSETTABLE_BREAK (b->address))	      {		val = 0;		b->enable = disabled;		if (!disabled_breaks)		  {		    fprintf (stderr,			 "Cannot insert breakpoint %d:\n", b->number);		    printf_filtered ("Disabling shared library breakpoints:\n");		  }		disabled_breaks = 1;		printf_filtered ("%d ", b->number);	      }	    else#endif	      {		fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number);#ifdef ONE_PROCESS_WRITETEXT		fprintf (stderr,		  "The same program may be running in another process.\n");#endif		memory_error (val, b->address);	/* which bombs us out */	      }	  }	else	  b->inserted = 1;      }  if (disabled_breaks)    printf_filtered ("\n");  return val;}intremove_breakpoints (){  register struct breakpoint *b;  int val;#ifdef BREAKPOINT_DEBUG  printf ("Removing breakpoints.\n");#endif /* BREAKPOINT_DEBUG */  ALL_BREAKPOINTS (b)    if (b->type != bp_watchpoint && b->inserted)      {	val = target_remove_breakpoint(b->address, b->shadow_contents);	if (val)	  return val;	b->inserted = 0;#ifdef BREAKPOINT_DEBUG	printf ("Removed breakpoint at %s",		local_hex_string(b->address));	printf (", shadow %s",		local_hex_string(b->shadow_contents[0]));	printf (", %s.\n",		local_hex_string(b->shadow_contents[1]));#endif /* BREAKPOINT_DEBUG */      }  return 0;}/* Clear the "inserted" flag in all breakpoints.   This is done when the inferior is loaded.  */voidmark_breakpoints_out (){  register struct breakpoint *b;  ALL_BREAKPOINTS (b)    b->inserted = 0;}/* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at PC.   When continuing from a location with a breakpoint,   we actually single step once before calling insert_breakpoints.  */intbreakpoint_here_p (pc)     CORE_ADDR pc;{  register struct breakpoint *b;  ALL_BREAKPOINTS (b)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -