This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Handle_inferior_event() problem



Hi Stan,
how are things at Apple?

Remember WFI/handle_inferior_event() ? 

There is a problem doing nexti while in a function prologue.

Say you have stepped your way to the first instruction of the prologue
of a function (using stepi, for instance) and now you do a 'nexti'.
The programs runs away to the end of the function or somewhere else and
gdb gets really confused.

What happens is this. After having issued a nexti, the target runs,
and it stops at the termporary breakpoint at the correct location, but
in handle_inferior_event there is this code:

    if (stop_pc == ecs->stop_func_start		/* Quick test */
	|| (in_prologue (stop_pc, ecs->stop_func_start) &&
	    !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
	|| IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name)
	|| ecs->stop_func_name == 0)
      {
	/* It's a subroutine 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
	       ("stepi").  Just stop.  */
	    stop_step = 1;
	    print_stop_reason (END_STEPPING_RANGE, 0);
	    stop_stepping (ecs);
	    return;
	  }

	if (step_over_calls > 0 || IGNORE_HELPER_CALL (stop_pc))
	  {
	    /* We're doing a "next".  */
	    step_over_function (ecs);
	    keep_going (ecs);
	    return;
	  }


The first if is true, because 
	|| (in_prologue (stop_pc, ecs->stop_func_start) &&
	    !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))

is true.

Then, 	if (step_over_calls > 0 || IGNORE_HELPER_CALL (stop_pc))
is true if you have just done a nexti.

So we get to keep_going, which continues the inferior.
Which is not what we want.

Looking at the old cvs versions of infrun.c, there once was a very
complicated test to check whether we are in a function call or not.
That test was disabled by Stu Grossman, ifdeffed out, end eventually
deleted. That test seems to have been doing things right for this case.

Here it is:

      /* I disabled this test because it was too complicated and slow.
         The SKIP_PROLOGUE was especially slow, because it caused
         unnecessary prologue examination on various architectures.
         The code in the #else clause has been tested on the Sparc,
         Mips, PA, and Power architectures, so it's pretty likely to
         be correct.  -Stu 10/24/95 */

      /* See if we left the step range due to a subroutine call that
         we should proceed to the end of.  */

      if (stop_func_start)
        {
          struct symtab *s;

          /* Do this after the IN_SIGTRAMP check; it might give
             an error.  */
          prologue_pc = stop_func_start;

          /* Don't skip the prologue if this is assembly source */
          s = find_pc_symtab (stop_pc);
          if (s && s->language != language_asm)
            SKIP_PROLOGUE (prologue_pc);
        }

      if (!(INNER_THAN (step_sp, read_sp ()))   /* don't mistake (sig)return
                                                   as a call */
          && (                  /* Might be a non-recursive call.  If the symbols are missing
                 enough that stop_func_start == prev_func_start even though
                 they are really two functions, we will treat some calls as
                 jumps.  */
               stop_func_start != prev_func_start

      /* Might be a recursive call if either we have a prologue
                 or the call instruction itself saves the PC on the stack.  */
               || prologue_pc != stop_func_start
               || read_sp () != step_sp)
          && (                  /* PC is completely out of bounds of any known objfiles.  Treat
                 like a subroutine call. */
               !stop_func_start

      /* If we do a call, we will be at the start of a function...  */
               || stop_pc == stop_func_start

      /* ...except on the Alpha with -O (and also Irix 5 and
                 perhaps others), in which we might call the address
                 after the load of gp.  Since prologues don't contain
                 calls, we can't return to within one, and we don't
                 jump back into them, so this check is OK.  */

               || stop_pc < prologue_pc

      /* ...and if it is a leaf function, the prologue might
                 consist of gp loading only, so the call transfers to
                 the first instruction after the prologue.  */
               || (stop_pc == prologue_pc

      /* Distinguish this from the case where we jump back
                     to the first instruction after the prologue,
                     within a function.  */
                   && stop_func_start != prev_func_start)

      /* If we end up in certain places, it means we did a subroutine
                 call.  I'm not completely sure this is necessary now that we
                 have the above checks with stop_func_start (and now that
                 find_pc_partial_function is pickier).  */
               || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)

      /* If none of the above apply, it is a jump within a function,
                 or a return from a subroutine.  The other case is longjmp,
                 which can no longer happen here as long as the
                 handling_longjmp stuff is working.  */
          ))


Anyway, long story short...  How about this patch? It doesn't take
care of everything, but it solves that immediate problem.  Probably
other bugs have been introduced by eliminating that complex test. I am
not sure what should be done though.

Elena


Index: infrun.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/infrun.c,v
retrieving revision 1.277
diff -c -r1.277 infrun.c
*** infrun.c    2000/02/29 07:17:52     1.277
--- infrun.c    2000/03/07 20:47:57
***************
*** 2699,2705 ****
  
      if (stop_pc == ecs->stop_func_start               /* Quick test */
        || (in_prologue (stop_pc, ecs->stop_func_start) &&
!           !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
        || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name)
        || ecs->stop_func_name == 0)
        {
--- 2710,2717 ----
  
      if (stop_pc == ecs->stop_func_start               /* Quick test */
        || (in_prologue (stop_pc, ecs->stop_func_start) &&
!           !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name) &&
!           ecs->stop_func_start != prev_func_start)
        || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name)
        || ecs->stop_func_name == 0)
        {





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]