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

📄 infrun.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif	    break;	  }            if (step_resume_break_address)	/* Having a step-resume breakpoint overrides anything	   else having to do with stepping commands until	   that breakpoint is reached.  */	;      /* If stepping through a line, keep going if still within it.  */      else if (!random_signal	       && step_range_end	       && stop_pc >= step_range_start	       && stop_pc < step_range_end	       /* The step range might include the start of the		  function, so if we are at the start of the		  step range and either the stack or frame pointers		  just changed, we've stepped outside */	       && !(stop_pc == step_range_start		    && stop_frame_address		    && (stop_sp INNER_THAN prev_sp			|| stop_frame_address != step_frame_address)))	{	  ;	}            /* We stepped out of the stepping range.  See if that was due	 to a subroutine call that we should proceed to the end of.  */      else if (!random_signal && step_range_end)	{	  if (stop_func_start)	    {	      prologue_pc = stop_func_start;	      SKIP_PROLOGUE (prologue_pc);	    }	  /* Did we just take a signal?  */	  if (IN_SIGTRAMP (stop_pc, stop_func_name)	      && !IN_SIGTRAMP (prev_pc, prev_func_name))	    {	      /* This code is needed at least in the following case:		 The user types "next" and then a signal arrives (before		 the "next" is done).  */	      /* We've just taken a signal; go until we are back to		 the point where we took it and one more.  */	      step_resume_break_address = prev_pc;	      step_resume_break_duplicate =		breakpoint_here_p (step_resume_break_address);	      if (breakpoints_inserted)		insert_step_breakpoint ();	      /* Make sure that the stepping range gets us past		 that instruction.  */	      if (step_range_end == 1)		step_range_end = (step_range_start = prev_pc) + 1;	      remove_breakpoints_on_following_step = 1;	      goto save_pc;	    }	  /* ==> See comments at top of file on this algorithm.  <==*/	  	  if ((stop_pc == stop_func_start	       || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name))	      && (stop_func_start != prev_func_start		  || prologue_pc != stop_func_start		  || stop_sp != prev_sp))	    {	      /* It's a subroutine call.		 (0)  If we are not stepping over any calls ("stepi"), we		      just stop.		 (1)  If we're doing a "next", we want to continue through		      the call ("step over the call").		 (2)  If we are in a function-call trampoline (a stub between		      the calling routine and the real function), locate		      the real function and change stop_func_start.		 (3)  If we're doing a "step", and there are no debug symbols		      at the target of the call, we want to continue through		      it ("step over the call").		 (4)  Otherwise, we want to stop soon, after the function		      prologue ("step into the call"). */	      if (step_over_calls == 0)		{		  /* I presume that step_over_calls is only 0 when we're		     supposed to be stepping at the assembly language level. */		  stop_step = 1;		  break;		}	      if (step_over_calls > 0)		goto step_over_function;	      tmp = SKIP_TRAMPOLINE_CODE (stop_pc);	      if (tmp != 0)		stop_func_start = tmp;	      if (find_pc_function (stop_func_start) != 0)	        goto step_into_function;step_over_function:	      /* A subroutine call has happened.  */	      /* Set a special breakpoint after the return */	      step_resume_break_address =		ADDR_BITS_REMOVE		  (SAVED_PC_AFTER_CALL (get_current_frame ()));	      step_resume_break_duplicate		= breakpoint_here_p (step_resume_break_address);	      if (breakpoints_inserted)		insert_step_breakpoint ();	      goto save_pc;step_into_function:	      /* Subroutine call with source code we should not step over.		 Do step to the first line of code in it.  */	      SKIP_PROLOGUE (stop_func_start);	      sal = find_pc_line (stop_func_start, 0);	      /* Use the step_resume_break to step until		 the end of the prologue, even if that involves jumps		 (as it seems to on the vax under 4.2).  */	      /* If the prologue ends in the middle of a source line,		 continue to the end of that source line.		 Otherwise, just go to end of prologue.  */#ifdef PROLOGUE_FIRSTLINE_OVERLAP	      /* no, don't either.  It skips any code that's		 legitimately on the first line.  */#else	      if (sal.end && sal.pc != stop_func_start)		stop_func_start = sal.end;#endif	      if (stop_func_start == stop_pc)		{		  /* We are already there: stop now.  */		  stop_step = 1;		  break;		}		      else		/* Put the step-breakpoint there and go until there. */		{		  step_resume_break_address = stop_func_start;		  		  step_resume_break_duplicate		    = breakpoint_here_p (step_resume_break_address);		  if (breakpoints_inserted)		    insert_step_breakpoint ();		  /* Do not specify what the fp should be when we stop		     since on some machines the prologue		     is where the new fp value is established.  */		  step_frame_address = 0;		  /* And make sure stepping stops right away then.  */		  step_range_end = step_range_start;		}	      goto save_pc;	    }	  /* We've wandered out of the step range (but haven't done a	     subroutine call or return).  */	  sal = find_pc_line(stop_pc, 0);	  	  if (step_range_end == 1 ||	/* stepi or nexti */	      sal.line == 0 ||		/* ...or no line # info */	      (stop_pc == sal.pc	/* ...or we're at the start */	       && current_line != sal.line)) {	/* of a different line */	    /* Stop because we're done stepping.  */	    stop_step = 1;	    break;	  } else {	    /* We aren't done stepping, and we have line number info for $pc.	       Optimize by setting the step_range for the line.  	       (We might not be in the original line, but if we entered a	       new line in mid-statement, we continue stepping.  This makes 	       things like for(;;) statements work better.)  */	    step_range_start = sal.pc;	    step_range_end = sal.end;	    goto save_pc;	  }	  /* We never fall through here */	}      if (trap_expected	  && IN_SIGTRAMP (stop_pc, stop_func_name)	  && !IN_SIGTRAMP (prev_pc, prev_func_name))	{	  /* What has happened here is that we have just stepped the inferior	     with a signal (because it is a signal which shouldn't make	     us stop), thus stepping into sigtramp.	     So we need to set a step_resume_break_address breakpoint	     and continue until we hit it, and then step.  */	  step_resume_break_address = prev_pc;	  /* Always 1, I think, but it's probably easier to have	     the step_resume_break as usual rather than trying to	     re-use the breakpoint which is already there.  */	  step_resume_break_duplicate =	    breakpoint_here_p (step_resume_break_address);	  if (breakpoints_inserted)	    insert_step_breakpoint ();	  remove_breakpoints_on_following_step = 1;	  another_trap = 1;	}/* My apologies to the gods of structured programming. *//* Come to this label when you need to resume the inferior.  It's really much   cleaner at this time to do a goto than to try and figure out what the   if-else chain ought to look like!! */    keep_going:save_pc:      /* Save the pc before execution, to compare with pc after stop.  */      prev_pc = read_pc ();	/* Might have been DECR_AFTER_BREAK */      prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER					  BREAK is defined, the					  original pc would not have					  been at the start of a					  function. */      prev_func_name = stop_func_name;      prev_sp = stop_sp;      /* If we did not do break;, it means we should keep	 running the inferior and not return to debugger.  */      if (trap_expected && stop_signal != SIGTRAP)	{	  /* We took a signal (which we are supposed to pass through to	     the inferior, else we'd have done a break above) and we	     haven't yet gotten our trap.  Simply continue.  */	  resume ((step_range_end && !step_resume_break_address)		  || (trap_expected && !step_resume_break_address)		  || bpstat_should_step (),		  stop_signal);	}      else	{	  /* Either the trap was not expected, but we are continuing	     anyway (the user asked that this signal be passed to the	     child)	       -- or --	     The signal was SIGTRAP, e.g. it was our signal, but we	     decided we should resume from it.	     We're going to run this baby now!	     Insert breakpoints now, unless we are trying	     to one-proceed past a breakpoint.  */	  /* If we've just finished a special step resume and we don't	     want to hit a breakpoint, pull em out.  */	  if (!step_resume_break_address &&	      remove_breakpoints_on_following_step)	    {	      remove_breakpoints_on_following_step = 0;	      remove_breakpoints ();	      breakpoints_inserted = 0;	    }	  else if (!breakpoints_inserted &&		   (step_resume_break_address != 0 || !another_trap))	    {	      insert_step_breakpoint ();	      breakpoints_failed = insert_breakpoints ();	      if (breakpoints_failed)		break;	      breakpoints_inserted = 1;	    }	  trap_expected = another_trap;	  if (stop_signal == SIGTRAP)	    stop_signal = 0;#ifdef SHIFT_INST_REGS	  /* I'm not sure when this following segment applies.  I do know, now,	     that we shouldn't rewrite the regs when we were stopped by a	     random signal from the inferior process.  */          if (!bpstat_explains_signal (stop_bpstat)	      && (stop_signal != SIGCLD)               && !stopped_by_random_signal)            {            CORE_ADDR pc_contents = read_register (PC_REGNUM);            CORE_ADDR npc_contents = read_register (NPC_REGNUM);            if (pc_contents != npc_contents)              {              write_register (NNPC_REGNUM, npc_contents);              write_register (NPC_REGNUM, pc_contents);	      }            }#endif /* SHIFT_INST_REGS */	  resume ((!step_resume_break_address		   && !handling_longjmp		   && (step_range_end		       || trap_expected))		  || bpstat_should_step (),		  stop_signal);	}    } stop_stepping:  if (target_has_execution)    {      /* Assuming the inferior still exists, set these up for next	 time, just like we did above if we didn't break out of the	 loop.  */      prev_pc = read_pc ();      prev_func_start = stop_func_start;      prev_func_name = stop_func_name;      prev_sp = stop_sp;    }}/* Here to return control to GDB when the inferior stops for real.   Print appropriate messages, remove breakpoints, give terminal our modes.   STOP_PRINT_FRAME nonzero means print the executing frame   (pc, function, args, file, line number and line text).   BREAKPOINTS_FAILED nonzero means stop was due to error   attempting to insert breakpoints.  */voidnormal_stop (){  char *tem;  struct cmd_list_element *c;  /* Make sure that the current_frame's pc is correct.  This     is a correction for setting up the frame info before doing     DECR_PC_AFTER_BREAK */  if (target_has_execution)    (get_current_frame ())->pc = read_pc ();    if (breakpoints_failed)    {      target_terminal_ours_for_output ();      print_sys_errmsg ("ptrace", breakpoints_failed);      printf_filtered ("Stopped; cannot insert breakpoints.\n\The same program may be running in another process.\n");    }  if (target_has_execution)    remove_step_breakpoint ();  if (target_has_execution && breakpoints_inserted)    if (remove_breakpoints ())      {	target_terminal_ours_for_output ();	printf_filtered ("Cannot remove breakpoints because program is no longer writable.\n\It might be running in another process.\n\Further execution is probably impossible.\n");      }  breakpoints_inserted = 0;  /* Delete the breakpoint we stopped at, if it wants to be deleted.     Delete any breakpoint that is to be deleted at the next stop.  */  breakpoint_auto_delete (stop_bpstat);  /* If an auto-display called a function and that got a signal,     delete that auto-display to avoid an infinite recursion.  */  if (stopped_by_random_signal)    disable_current_display ();  if (step_multi && stop_step)    return;  target_terminal_ours ();  /* Look up the hook_stop and run it if it exists.  */  if (stop_command->hook)    {      catch_errors (hook_stop_stub, (char *)stop_command->hook,		    "Error while running hook_stop:\n");    }  if (!target_has_stack)    return;  /* Select innermost stack frame except on return from a stack dummy routine,     or if the program has exited.  Print it without a level number if     we have changed functions or hit a breakpoint.  Print source line     if we have one.  */  if (!stop_stack_dummy)    {      select_frame (get_current_frame (), 0);      if (stop_print_frame)	{	  int source_only;	  source_only = bpstat_print (stop_bpstat);	  source_only = source_only ||	        (   stop_step		 && step_frame_address == stop_frame_address		 && step_start_function == find_pc_function (stop_pc));          print_stack_frame (selected_frame, -1, source_only? -1: 1);	  /* Display the auto-display expressions.  */	  do_displays ();	}    } else {      /* Pop the empty frame that contains the stack dummy.         POP_FRAME ends with a setting of the current frame, so we	 can use that next. */#ifndef NEW_CALL_FUNCTION      POP_FRAME;#endif      select_frame (get_current_frame (), 0);    }}static inthook_stop_stub (cmd)     char *cmd;{  execute_user_command ((struct cmd_list_element *)cmd, 0);}static voidinsert_step_breakpoint (){  if (step_resume_break_address && !step_resume_break_duplicate)    target_insert_breakpoint (step_resume_break_address,			      step_resume_break_shadow);}static voidremove_step_breakpoint (){  if (step_resume_break_address && !step_resume_break_duplicate)

⌨️ 快捷键说明

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