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

📄 infrun.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
  normal_stop ();}/* Record the pc and sp of the program the last time it stopped.   These are just used internally by wait_for_inferior, but need   to be preserved over calls to it and cleared when the inferior   is started.  */static CORE_ADDR prev_pc;static CORE_ADDR prev_sp;static CORE_ADDR prev_func_start;static char *prev_func_name;voidinit_wait_for_inferior_keep_brkpts(){  /* These are meaningless until the first time through wait_for_inferior.  */  prev_pc = 0;  prev_sp = 0;  prev_func_start = 0;  prev_func_name = NULL;  trap_expected_after_continue = 0;  stop_signal = 0;            /* Don't confuse first call to proceed(). */}/* Initialize static vars when a new inferior begins.  */voidinit_wait_for_inferior (){  init_wait_for_inferior_keep_brkpts();  breakpoints_inserted = 0;  mark_breakpoints_out ();}voidremote_go(){  clear_proceed_status();  stop_soon_quietly = 1;  trap_expected = 0;  wait_for_inferior();  normal_stop();}/* Wait for control to return from inferior to debugger.   If inferior gets a signal, we may decide to start it up again   instead of returning.  That is why there is a loop in this function.   When this function actually returns it means the inferior   should be left stopped and GDB should read more commands.  */voidwait_for_inferior (){  WAITTYPE w;  int another_trap;  int random_signal;  CORE_ADDR stop_sp;  CORE_ADDR stop_func_start;  char *stop_func_name;  CORE_ADDR prologue_pc, tmp;  int stop_step_resume_break;  struct symtab_and_line sal;  int remove_breakpoints_on_following_step = 0;  int current_line;  int handling_longjmp = 0;	/* FIXME */  sal = find_pc_line(prev_pc, 0);  current_line = sal.line;  while (1)    {      /* Clean up saved state that will become invalid.  */      pc_changed = 0;      flush_cached_frames ();      registers_changed ();      target_wait (&w);#ifdef SIGTRAP_STOP_AFTER_LOAD      /* Somebody called load(2), and it gave us a "trap signal after load".         Ignore it gracefully. */      SIGTRAP_STOP_AFTER_LOAD (w);#endif      /* See if the process still exists; clean up if it doesn't.  */      if (WIFEXITED (w))	{	  target_terminal_ours ();	/* Must do this before mourn anyway */	  if (WEXITSTATUS (w))	    printf_filtered ("\nProgram exited with code 0%o.\n", 		     (unsigned int)WEXITSTATUS (w));	  else	    if (!batch_mode())	      printf_filtered ("\nProgram exited normally.\n");	  fflush (stdout);	  target_mourn_inferior ();#ifdef NO_SINGLE_STEP	  one_stepped = 0;#endif	  stop_print_frame = 0;	  break;	}      else if (!WIFSTOPPED (w))	{	  stop_print_frame = 0;	  stop_signal = WTERMSIG (w);	  target_terminal_ours ();	/* Must do this before mourn anyway */	  target_kill ();		/* kill mourns as well */#ifdef PRINT_RANDOM_SIGNAL	  printf_filtered ("\nProgram terminated: ");	  PRINT_RANDOM_SIGNAL (stop_signal);#else	  printf_filtered ("\nProgram terminated with signal %d, %s\n",			   stop_signal, safe_strsignal (stop_signal));#endif	  printf_filtered ("The inferior process no longer exists.\n");	  fflush (stdout);#ifdef NO_SINGLE_STEP	  one_stepped = 0;#endif	  break;	}      #ifdef NO_SINGLE_STEP      if (one_stepped)	single_step (0);	/* This actually cleans up the ss */#endif /* NO_SINGLE_STEP */            stop_pc = read_pc ();      set_current_frame ( create_new_frame (read_register (FP_REGNUM),					    read_pc ()));            stop_frame_address = FRAME_FP (get_current_frame ());      stop_sp = read_register (SP_REGNUM);      stop_func_start = 0;      stop_func_name = 0;      /* Don't care about return value; stop_func_start and stop_func_name	 will both be 0 if it doesn't work.  */      find_pc_partial_function (stop_pc, &stop_func_name, &stop_func_start);      stop_func_start += FUNCTION_START_OFFSET;      another_trap = 0;      bpstat_clear (&stop_bpstat);      stop_step = 0;      stop_stack_dummy = 0;      stop_print_frame = 1;      stop_step_resume_break = 0;      random_signal = 0;      stopped_by_random_signal = 0;      breakpoints_failed = 0;            /* Look at the cause of the stop, and decide what to do.	 The alternatives are:	 1) break; to really stop and return to the debugger,	 2) drop through to start up again	 (set another_trap to 1 to single step once)	 3) set random_signal to 1, and the decision between 1 and 2	 will be made according to the signal handling tables.  */            stop_signal = WSTOPSIG (w);            /* First, distinguish signals caused by the debugger from signals	 that have to do with the program's own actions.	 Note that breakpoint insns may cause SIGTRAP or SIGILL	 or SIGEMT, depending on the operating system version.	 Here we detect when a SIGILL or SIGEMT is really a breakpoint	 and change it to SIGTRAP.  */            if (stop_signal == SIGTRAP	  || (breakpoints_inserted &&	      (stop_signal == SIGILL#ifdef SIGEMT	       || stop_signal == SIGEMT#endif            ))	  || stop_soon_quietly)	{	  if (stop_signal == SIGTRAP && stop_after_trap)	    {	      stop_print_frame = 0;	      break;	    }	  if (stop_soon_quietly)	    break;	  /* Don't even think about breakpoints	     if just proceeded over a breakpoint.	     However, if we are trying to proceed over a breakpoint	     and end up in sigtramp, then step_resume_break_address	     will be set and we should check whether we've hit the	     step breakpoint.  */	  if (stop_signal == SIGTRAP && trap_expected	      && step_resume_break_address == 0)	    bpstat_clear (&stop_bpstat);	  else	    {	      /* See if there is a breakpoint at the current PC.  */#if DECR_PC_AFTER_BREAK	      /* Notice the case of stepping through a jump		 that lands just after a breakpoint.		 Don't confuse that with hitting the breakpoint.		 What we check for is that 1) stepping is going on		 and 2) the pc before the last insn does not match		 the address of the breakpoint before the current pc.  */	      if (prev_pc == stop_pc - DECR_PC_AFTER_BREAK		  || !step_range_end		  || step_resume_break_address		  || handling_longjmp /* FIXME */)#endif /* DECR_PC_AFTER_BREAK not zero */		{		  /* See if we stopped at the special breakpoint for		     stepping over a subroutine call.  If both are zero,		     this wasn't the reason for the stop.  */		  if (step_resume_break_address		      && stop_pc - DECR_PC_AFTER_BREAK		         == step_resume_break_address)		    {		      stop_step_resume_break = 1;		      if (DECR_PC_AFTER_BREAK)			{			  stop_pc -= DECR_PC_AFTER_BREAK;			  write_register (PC_REGNUM, stop_pc);			  pc_changed = 0;			}		    }		  else		    {		      stop_bpstat =			bpstat_stop_status (&stop_pc, stop_frame_address);		      /* Following in case break condition called a			 function.  */		      stop_print_frame = 1;		    }		}	    }	  	  if (stop_signal == SIGTRAP)	    random_signal	      = !(bpstat_explains_signal (stop_bpstat)		  || trap_expected		  || stop_step_resume_break		  || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)		  || (step_range_end && !step_resume_break_address));	  else	    {	      random_signal		= !(bpstat_explains_signal (stop_bpstat)		    || stop_step_resume_break		    /* End of a stack dummy.  Some systems (e.g. Sony		       news) give another signal besides SIGTRAP,		       so check here as well as above.  */		    || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)		    );	      if (!random_signal)		stop_signal = SIGTRAP;	    }	}      else	random_signal = 1;            /* For the program's own signals, act according to	 the signal handling tables.  */            if (random_signal)	{	  /* Signal not for debugging purposes.  */	  int printed = 0;	  	  stopped_by_random_signal = 1;	  	  if (stop_signal >= NSIG	      || signal_print[stop_signal])	    {	      printed = 1;	      target_terminal_ours_for_output ();#ifdef PRINT_RANDOM_SIGNAL	      PRINT_RANDOM_SIGNAL (stop_signal);#else	      printf_filtered ("\nProgram received signal %d, %s\n",			       stop_signal, safe_strsignal (stop_signal));#endif /* PRINT_RANDOM_SIGNAL */	      fflush (stdout);	    }	  if (stop_signal >= NSIG	      || signal_stop[stop_signal])	    break;	  /* If not going to stop, give terminal back	     if we took it away.  */	  else if (printed)	    target_terminal_inferior ();	  /* Note that virtually all the code below does `if !random_signal'.	     Perhaps this code should end with a goto or continue.  At least	     one (now fixed) bug was caused by this -- a !random_signal was	     missing in one of the tests below.  */	}      /* Handle cases caused by hitting a breakpoint.  */      if (!random_signal)	if (bpstat_explains_signal (stop_bpstat))	  {	    CORE_ADDR jmp_buf_pc;	    switch (stop_bpstat->breakpoint_at->type) /* FIXME */	      {		/* If we hit the breakpoint at longjmp, disable it for the		   duration of this command.  Then, install a temporary		   breakpoint at the target of the jmp_buf. */	      case bp_longjmp:		disable_longjmp_breakpoint();		remove_breakpoints ();		breakpoints_inserted = 0;		if (!GET_LONGJMP_TARGET(&jmp_buf_pc)) goto keep_going;		/* Need to blow away step-resume breakpoint, as it		   interferes with us */		remove_step_breakpoint ();		step_resume_break_address = 0;		stop_step_resume_break = 0;#if 0				/* FIXME - Need to implement nested temporary breakpoints */		if (step_over_calls > 0)		  set_longjmp_resume_breakpoint(jmp_buf_pc,						get_current_frame());		else#endif				/* 0 */		  set_longjmp_resume_breakpoint(jmp_buf_pc, NULL);		handling_longjmp = 1; /* FIXME */		goto keep_going;	      case bp_longjmp_resume:		remove_breakpoints ();		breakpoints_inserted = 0;#if 0				/* FIXME - Need to implement nested temporary breakpoints */		if (step_over_calls		    && (stop_frame_address			INNER_THAN step_frame_address))		  {		    another_trap = 1;		    goto keep_going;		  }#endif				/* 0 */		disable_longjmp_breakpoint();		handling_longjmp = 0; /* FIXME */		break;	      default:		fprintf(stderr, "Unknown breakpoint type %d\n",			stop_bpstat->breakpoint_at->type);	      case bp_watchpoint:	      case bp_breakpoint:	      case bp_until:	      case bp_finish:		/* Does a breakpoint want us to stop?  */		if (bpstat_stop (stop_bpstat))		  {		    stop_print_frame = bpstat_should_print (stop_bpstat);		    goto stop_stepping;		  }		/* Otherwise, must remove breakpoints and single-step		   to get us past the one we hit.  */		else		  {		    remove_breakpoints ();		    remove_step_breakpoint ();		    breakpoints_inserted = 0;		    another_trap = 1;		  }		break;	      }	  }	else if (stop_step_resume_break)	  {	    /* But if we have hit the step-resumption breakpoint,	       remove it.  It has done its job getting us here.	       The sp test is to make sure that we don't get hung	       up in recursive calls in functions without frame	       pointers.  If the stack pointer isn't outside of	       where the breakpoint was set (within a routine to be	       stepped over), we're in the middle of a recursive	       call. Not true for reg window machines (sparc)	       because the must change frames to call things and	       the stack pointer doesn't have to change if it	       the bp was set in a routine without a frame (pc can	       be stored in some other window).	       	       The removal of the sp test is to allow calls to	       alloca.  Nasty things were happening.  Oh, well,	       gdb can only handle one level deep of lack of	       frame pointer. */	    /*	      Disable test for step_frame_address match so that we always stop even if the	      frames don't match.  Reason: if we hit the step_resume_breakpoint, there is	      no way to temporarily disable it so that we can step past it.  If we leave	      the breakpoint in, then we loop forever repeatedly hitting, but never	      getting past the breakpoint.  This change keeps nexting over recursive	      function calls from hanging gdb.	      */#if 0	    if (* step_frame_address == 0		|| (step_frame_address == stop_frame_address))#endif	      {		remove_step_breakpoint ();		step_resume_break_address = 0;		/* If were waiting for a trap, hitting the step_resume_break		   doesn't count as getting it.  */		if (trap_expected)		  another_trap = 1;	      }	  }      /* We come here if we hit a breakpoint but should not	 stop for it.  Possibly we also were stepping	 and should stop for that.  So fall through and	 test for stepping.  But, if not stepping,	 do not stop.  */      /* If this is the breakpoint at the end of a stack dummy,	 just stop silently.  */      if (!random_signal 	 && PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address))	  {	    stop_print_frame = 0;	    stop_stack_dummy = 1;#ifdef HP_OS_BUG	    trap_expected_after_continue = 1;

⌨️ 快捷键说明

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