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

📄 breakpoint.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (b->enable != disabled && b->address == pc)      return 1;  return 0;}/* 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.  */voidbpstat_clear (bsp)     bpstat *bsp;{  bpstat p;  bpstat q;  if (bsp == 0)    return;  p = *bsp;  while (p != NULL)    {      q = p->next;      if (p->old_val != NULL)	value_free (p->old_val);      free ((PTR)p);      p = q;    }  *bsp = NULL;}/* Return a copy of a bpstat.  Like "bs1 = bs2" but all storage that   is part of the bpstat is copied as well.  */bpstatbpstat_copy (bs)     bpstat bs;{  bpstat p = NULL;  bpstat tmp;  bpstat retval;  if (bs == NULL)    return bs;  for (; bs != NULL; bs = bs->next)    {      tmp = (bpstat) xmalloc (sizeof (*tmp));      memcpy (tmp, bs, sizeof (*tmp));      if (p == NULL)	/* This is the first thing in the chain.  */	retval = tmp;      else	p->next = tmp;      p = tmp;    }  p->next = NULL;  return retval;}/* Find the bpstat associated with this breakpoint */bpstatbpstat_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.  */intbpstat_num (bsp)     bpstat *bsp;{  struct breakpoint *b;  if ((*bsp) == NULL)    return 0;			/* No more breakpoint values */  else    {      b = (*bsp)->breakpoint_at;      *bsp = (*bsp)->next;      if (b == NULL)	return -1;		/* breakpoint that's been deleted since */      else        return b->number;	/* We have its number */    }}/* Modify BS so that the actions will not be performed.  */voidbpstat_clear_actions (bs)     bpstat bs;{  for (; bs != NULL; bs = bs->next)    {      bs->commands = NULL;      if (bs->old_val != NULL)	{	  value_free (bs->old_val);	  bs->old_val = NULL;	}    }}/* Stub for cleaning up our state if we error-out of a breakpoint command *//* ARGSUSED */static voidcleanup_executing_breakpoints (ignore)     int ignore;{  executing_breakpoint_commands = 0;}/* Execute all the commands associated with all the breakpoints at this   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.  */voidbpstat_do_actions (bsp)     bpstat *bsp;{  bpstat bs;  struct cleanup *old_chain;  executing_breakpoint_commands = 1;  old_chain = make_cleanup (cleanup_executing_breakpoints, 0);top:  bs = *bsp;  breakpoint_proceeded = 0;  for (; bs != NULL; bs = bs->next)    {      while (bs->commands)	{	  char *line = bs->commands->line;	  bs->commands = bs->commands->next;	  execute_command (line, 0);	  /* If the inferior is proceeded by the command, bomb out now.	     The bpstat chain has been blown away by wait_for_inferior.	     But since execution has stopped again, there is a new bpstat	     to look at, so start over.  */	  if (breakpoint_proceeded)	    goto top;	}    }  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).  */intbpstat_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      || (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     circumstance is when we single-stepped for both a watchpoint and     for a "stepi" instruction.  The bpstat says that the watchpoint     explains the stop, but we shouldn't print because the watchpoint's     value didn't change -- and the real reason we are stopping here     rather than continuing to step (as the watchpoint would've had us do)     is because of the "stepi".  */  if (!bs->print)    return 0;  if (bs->breakpoint_at->type == bp_breakpoint)    {      /* I think the user probably only wants to see one breakpoint	 number, not all of them.  */      printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number);      return 0;    }        if (bs->old_val != NULL)    {      printf_filtered ("\nWatchpoint %d, ", bs->breakpoint_at->number);      print_expression (bs->breakpoint_at->exp, stdout);      printf_filtered ("\nOld value = ");      value_print (bs->old_val, stdout, 0, Val_pretty_default);      printf_filtered ("\nNew value = ");      value_print (bs->breakpoint_at->val, stdout, 0,		   Val_pretty_default);      printf_filtered ("\n");      value_free (bs->old_val);      bs->old_val = NULL;      return 1;    }  /* Maybe another breakpoint in the chain caused us to stop.     (Currently all watchpoints go on the bpstat whether hit or     not.  That probably could (should) be changed, provided care is taken     with respect to bpstat_explains_signal).  */  if (bs->next)    return bpstat_print (bs->next);  fprintf_filtered (stderr, "gdb internal error: in bpstat_print\n");  return 0;}/* Evaluate the expression EXP and return 1 if value is zero.   This is used inside a catch_errors to evaluate the breakpoint condition.    The argument is a "struct expression *" that has been cast to char * to    make it pass through catch_errors.  */static intbreakpoint_cond_eval (exp)     char *exp;{  return !value_true (evaluate_expression ((struct expression *)exp));}/* Allocate a new bpstat and chain it to the current one.  */static bpstatbpstat_alloc (b, cbs)     register struct breakpoint *b;     bpstat cbs;			/* Current "bs" value */{  bpstat bs;  bs = (bpstat) xmalloc (sizeof (*bs));  cbs->next = bs;  bs->breakpoint_at = b;  /* If the condition is false, etc., don't do the commands.  */  bs->commands = NULL;  bs->momentary = b->disposition == delete;  bs->old_val = NULL;  return bs;}/* Determine whether we stopped at a breakpoint, etc, or whether we   don't understand this stop.  Result is a chain of bpstat's such that:	if we don't understand the stop, the result is a null pointer.	if we understand why we stopped, the result is not null, and	the first element of the chain contains summary "stop" and	"print" flags for the whole chain.	Each element of the chain refers to a particular breakpoint or	watchpoint at which we have stopped.  (We may have stopped for	several reasons concurrently.)	Each element of the chain has valid next, breakpoint_at,	commands, FIXME??? fields. */	bpstatbpstat_stop_status (pc, frame_address)     CORE_ADDR *pc;     FRAME_ADDR frame_address;{  register struct breakpoint *b;  int stop = 0;  int print = 0;  CORE_ADDR bp_addr;#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)  /* True if we've hit a breakpoint (as opposed to a watchpoint).  */  int real_breakpoint = 0;#endif  /* Root of the chain of bpstat's */  struct bpstat root_bs[1];  /* Pointer to the last thing in the chain currently.  */  bpstat bs = root_bs;  /* Get the address where the breakpoint would have been.  */  bp_addr = *pc - DECR_PC_AFTER_BREAK;  ALL_BREAKPOINTS (b)    {      int this_bp_stop;      int this_bp_print;      if (b->enable == disabled)	continue;      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->type == bp_watchpoint)	{	  int within_current_scope;	  if (b->exp_valid_block != NULL)	    within_current_scope =	      contained_in (get_selected_block (), b->exp_valid_block);	  else	    within_current_scope = 1;	  if (within_current_scope)	    {	      /* We use value_{,free_to_}mark because it could be a		 *long* time before we return to the command level and		 call free_all_values.  */	      value mark = value_mark ();	      value new_val = evaluate_expression (b->exp);	      if (!value_equal (b->val, new_val))		{		  release_value (new_val);		  value_free_to_mark (mark);		  bs->old_val = b->val;		  b->val = new_val;		  /* We will stop here */		}	      else		{		  /* Nothing changed, don't do anything.  */		  value_free_to_mark (mark);		  continue;		  /* We won't stop here */		}	    }	  else	    {	      /* This seems like the only logical thing to do because		 if we temporarily ignored the watchpoint, then when		 we reenter the block in which it is valid it contains		 garbage (in the case of a function, it may have two		 garbage values, one before and one after the prologue).		 So we can't even detect the first assignment to it and		 watch after that (since the garbage may or may not equal		 the first value assigned).  */	      b->enable = disabled;	      printf_filtered ("\Watchpoint %d disabled because the program has left the block in\n\which its expression is valid.\n", b->number);	      /* We won't stop here */	      /* FIXME, maybe we should stop here!!! */	      continue;	    }	}#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)      else	real_breakpoint = 1;#endif      if (b->frame && b->frame != frame_address)	this_bp_stop = 0;      else	{	  int value_is_zero;	  if (b->cond)	    {	      /* Need to select the frame, with all that implies		 so that the conditions will have the right context.  */	      select_frame (get_current_frame (), 0);	      value_is_zero		= catch_errors (breakpoint_cond_eval, (char *)(b->cond),				"Error in testing breakpoint condition:\n");				/* FIXME-someday, should give breakpoint # */	      free_all_values ();	    }	  if (b->cond && value_is_zero)	    {	      this_bp_stop = 0;	    }	  else if (b->ignore_count > 0)	    {	      b->ignore_count--;	      this_bp_stop = 0;	    }	  else	    {	      /* We will stop here */	      if (b->disposition == disable)		b->enable = disabled;	      bs->commands = b->commands;	      if (b->silent)		this_bp_print = 0;	      if (bs->commands && !strcmp ("silent", bs->commands->line))		{		  bs->commands = bs->commands->next;		  this_bp_print = 0;		}	    }	}      if (this_bp_stop)	stop = 1;      if (this_bp_print)	print = 1;    }  bs->next = NULL;		/* Terminate the chain */  bs = root_bs->next;		/* Re-grab the head of the chain */  if (bs)    {      bs->stop = stop;      bs->print = print;#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)      if (real_breakpoint)	{	  *pc = bp_addr;#if defined (SHIFT_INST_REGS)	  {	    CORE_ADDR pc = read_register (PC_REGNUM);	    CORE_ADDR npc = read_register (NPC_REGNUM);	    if (pc != npc)	      {		write_register (NNPC_REGNUM, npc);		write_register (NPC_REGNUM, pc);	      }	  }#else /* No SHIFT_INST_REGS.  */	  write_pc (bp_addr);#endif /* No SHIFT_INST_REGS.  */	}#endif /* DECR_PC_AFTER_BREAK != 0.  */    }  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 == enabled && b->type == bp_watchpoint)      return 1;  return 0;}/* Print information on breakpoint number BNUM, or -1 if all.   If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS   is nonzero, process only watchpoints.  */static voidbreakpoint_1 (bnum, allflag)     int bnum;     int allflag;{  register struct breakpoint *b;  register struct command_line *l;  register struct symbol *sym;  CORE_ADDR last_addr = (CORE_ADDR)-1;  int found_a_breakpoint = 0;  static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint",			      "longjmp", "longjmp resume"};  static char *bpdisps[] = {"del", "dis", "keep"};  static char bpenables[] = "ny";  if (!breakpoint_chain)    {      printf_filtered ("No breakpoints or watchpoints.\n");      return;    }    ALL_BREAKPOINTS (b)    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",			   addressprint ? "Address    " : "");	printf_filtered ("%-3d %-14s %-4s %-3c ",			 b->number,			 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"));	    last_addr = b->address;	    if (b->symtab)	      {		sym = find_pc_function (b->address);		if (sym)		  {

⌨️ 快捷键说明

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