GDB 4.17 Patch for debugging frame pointerless i386 code

John Wehle john@feith.com
Mon Nov 2 21:29:00 GMT 1998


This patch adds support for debugging functions where the
frame pointer has been eliminated and the stack pointer
is unchanging.

ChangeLog:

Mon Nov  2 23:39:37 EST 1998  John Wehle  (john@feith.com)

	* i386-tdep.c (codestream_fill): Use read_memory_nobpt.
	(i386_analyze_prologue, i386_frame_chain,
	i386_init_extra_frame_info): New functions.
	(i386_get_frame_setup, i386_frame_find_saved_regs,
	i386_skip_prologue, i386_pop_frame): Support prologues
	which don't setup a frame pointer.
	* tm-i386.h (EXTRA_FRAME_INFO, INIT_EXTRA_FRAME_INFO,
	INIT_FRAME_PC): Define.
	(FRAME_CHAIN): Call i386_frame_chain.
	(FRAME_FIND_SAVED_REGS, FRAME_SAVED_PC): Use fsr to
	locate the saved registers.
	(FRAMELESS_FUNCTION_INVOCATION): Don't define.
	(i386_init_extra_frame_info, i386_frame_chain): Add
	prototypes.

-- John Wehle
------------------8<------------------------8<------------------------
*** gdb/i386-tdep.c.ORIGINAL	Sat Apr 11 01:39:37 1998
--- gdb/i386-tdep.c	Mon Nov  2 23:23:59 1998
*************** Foundation, Inc., 59 Temple Place - Suit
*** 28,37 ****
  #include "symtab.h"
  #include "gdbcmd.h"
  
- static long i386_get_frame_setup PARAMS ((CORE_ADDR));
- 
- static void i386_follow_jump PARAMS ((void));
- 
  static void codestream_read PARAMS ((unsigned char *, int));
  
  static void codestream_seek PARAMS ((CORE_ADDR));
--- 28,33 ----
*************** static unsigned char 
*** 72,82 ****
  codestream_fill (peek_flag)
      int peek_flag;
  {
    codestream_addr = codestream_next_addr;
    codestream_next_addr += CODESTREAM_BUFSIZ;
    codestream_off = 0;
    codestream_cnt = CODESTREAM_BUFSIZ;
!   read_memory (codestream_addr, (char *) codestream_buf, CODESTREAM_BUFSIZ);
    
    if (peek_flag)
      return (codestream_peek());
--- 68,83 ----
  codestream_fill (peek_flag)
      int peek_flag;
  {
+   int status;
+ 
    codestream_addr = codestream_next_addr;
    codestream_next_addr += CODESTREAM_BUFSIZ;
    codestream_off = 0;
    codestream_cnt = CODESTREAM_BUFSIZ;
!   status = read_memory_nobpt (codestream_addr,
! 			      (char *) codestream_buf, CODESTREAM_BUFSIZ);
!   if (status != 0)
!     memory_error (status, codestream_addr);
    
    if (peek_flag)
      return (codestream_peek());
*************** i386_follow_jump ()
*** 161,185 ****
  }
  
  /*
!  * find & return amound a local space allocated, and advance codestream to
!  * first register push (if any)
   *
!  * if entry sequence doesn't make sense, return -1, and leave 
!  * codestream pointer random
   */
  
! static long
! i386_get_frame_setup (pc)
!      CORE_ADDR pc;
  {
    unsigned char op;
  
-   codestream_seek (pc);
- 
-   i386_follow_jump ();
- 
    op = codestream_get ();
- 
    if (op == 0x58)		/* popl %eax */
      {
        /*
--- 162,186 ----
  }
  
  /*
!  * Determine the amount of local space allocated, and advance codestream to
!  * first register push (if any).
   *
!  * If the entry sequence doesn't make sense, then assume it is a frameless
!  * function with no local space.
   */
  
! #define MY_FRAME_IN_SP   0x1
! #define MY_FRAME_IN_FP   0x2
! #define NO_MORE_FRAMES   0x4
! #define INCOMPLETE_FRAME 0x8
! 
! static void
! i386_get_frame_setup (fi)
!      struct frame_info *fi;
  {
    unsigned char op;
  
    op = codestream_get ();
    if (op == 0x58)		/* popl %eax */
      {
        /*
*************** i386_get_frame_setup (pc)
*** 214,275 ****
    if (op == 0x55)		/* pushl %ebp */
      {			
        /* check for movl %esp, %ebp - can be written two ways */
!       switch (codestream_get ())
! 	{
! 	case 0x8b:
! 	  if (codestream_get () != 0xec)
! 	    return (-1);
! 	  break;
! 	case 0x89:
! 	  if (codestream_get () != 0xe5)
! 	    return (-1);
! 	  break;
! 	default:
! 	  return (-1);
! 	}
!       /* check for stack adjustment 
!        *
!        *  subl $XXX, %esp
!        *
!        * note: you can't subtract a 16 bit immediate
!        * from a 32 bit reg, so we don't have to worry
!        * about a data16 prefix 
!        */
!       op = codestream_peek ();
!       if (op == 0x83)
! 	{
! 	  /* subl with 8 bit immed */
! 	  codestream_get ();
! 	  if (codestream_get () != 0xec)
! 	    /* Some instruction starting with 0x83 other than subl.  */
! 	    {
! 	      codestream_seek (codestream_tell () - 2);
! 	      return 0;
! 	    }
! 	  /* subl with signed byte immediate 
! 	   * (though it wouldn't make sense to be negative)
! 	   */
! 	  return (codestream_get());
! 	}
!       else if (op == 0x81)
! 	{
! 	  char buf[4];
! 	  /* Maybe it is subl with 32 bit immedediate.  */
! 	  codestream_get();
! 	  if (codestream_get () != 0xec)
! 	    /* Some instruction starting with 0x81 other than subl.  */
! 	    {
! 	      codestream_seek (codestream_tell () - 2);
! 	      return 0;
! 	    }
! 	  /* It is subl with 32 bit immediate.  */
! 	  codestream_read ((unsigned char *)buf, 4);
! 	  return extract_signed_integer (buf, 4);
! 	}
!       else
! 	{
! 	  return (0);
  	}
      }
    else if (op == 0xc8)
      {
--- 215,232 ----
    if (op == 0x55)		/* pushl %ebp */
      {			
        /* check for movl %esp, %ebp - can be written two ways */
!       unsigned char buf[2];
!       static unsigned char proto1[2] = { 0x8b,0xec };
!       static unsigned char proto2[2] = { 0x89,0xe5 };
!       codestream_read (buf, sizeof(buf));
!       if (memcmp (buf, proto1, 2) != 0
! 	  && memcmp (buf, proto2, 2) != 0)
! 	{
! 	  /* frameless function with no local space */
! 	  codestream_seek (codestream_tell () - 3);
! 	  return;
  	}
+       fi->status = MY_FRAME_IN_FP;
      }
    else if (op == 0xc8)
      {
*************** i386_get_frame_setup (pc)
*** 277,285 ****
        /* enter instruction: arg is 16 bit unsigned immed */
        codestream_read ((unsigned char *)buf, 2);
        codestream_get (); /* flush final byte of enter instruction */
!       return extract_unsigned_integer (buf, 2);
      }
!   return (-1);
  }
  
  /* Return number of args passed to a frame.
--- 234,287 ----
        /* enter instruction: arg is 16 bit unsigned immed */
        codestream_read ((unsigned char *)buf, 2);
        codestream_get (); /* flush final byte of enter instruction */
!       fi->status = MY_FRAME_IN_FP;
!       fi->stack_size = extract_unsigned_integer (buf, 2);
!       return;
      }
!   else
!     codestream_seek (codestream_tell () - 1);
! 
!   /* check for stack adjustment 
!    *
!    *  subl $XXX, %esp
!    *
!    * note: you can't subtract a 16 bit immediate
!    * from a 32 bit reg, so we don't have to worry
!    * about a data16 prefix 
!    */
!   op = codestream_peek ();
!   if (op == 0x83)
!     {
!       /* subl with 8 bit immed */
!       codestream_get ();
!       if (codestream_get () != 0xec)
! 	/* Some instruction starting with 0x83 other than subl.  */
! 	{
! 	  codestream_seek (codestream_tell () - 2);
! 	  return;
! 	}
!       /* subl with signed byte immediate 
!        * (though it wouldn't make sense to be negative)
!        */
!       fi->stack_size = codestream_get();
!     }
!   else if (op == 0x81)
!     {
!       char buf[4];
!       /* Maybe it is subl with 32 bit immedediate.  */
!       codestream_get();
!       if (codestream_get () != 0xec)
! 	/* Some instruction starting with 0x81 other than subl.  */
! 	{
! 	  codestream_seek (codestream_tell () - 2);
! 	  return;
! 	}
!       /* It is subl with 32 bit immediate.  */
!       codestream_read ((unsigned char *)buf, 4);
!       fi->stack_size = extract_signed_integer (buf, 4);
!     }
! 
!   return;
  }
  
  /* Return number of args passed to a frame.
*************** i386_frame_num_args (fi)
*** 359,372 ****
  }
  
  /*
!  * parse the first few instructions of the function to see
!  * what registers were stored.
   *
   * We handle these cases:
   *
   * The startup sequence can be at the start of the function,
   * or the function can start with a branch to startup code at the end.
   *
   * %ebp can be set up with either the 'enter' instruction, or 
   * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful,
   * but was once used in the sys5 compiler)
--- 361,447 ----
  }
  
  /*
!  * Determine where the registers were stored.
!  */
! 
! static void
! i386_frame_find_saved_regs (fi)
!      struct frame_info *fi;
! {
!   unsigned char op;
!   CORE_ADDR adr;
!   int i;
!   int offset;
!   
!   /*
!    * First determine the offset of each register that has
!    * been placed on the stack.
!    */
! 
!   offset = 4 + fi->stack_size;
! 
!   for (i = 0; i < 8; i++) 
!     {
!       op = codestream_peek ();
!       if (op < 0x50 || op > 0x57)
! 	break;
!       codestream_get ();
! #ifdef I386_REGNO_TO_SYMMETRY
!       /* Dynix uses different internal numbering.  Ick.  */
!       fi->fsr.regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = offset;
! #else
!       fi->fsr.regs[op - 0x50] = offset;
! #endif
!       offset += 4;
!     }
! 
!   /*
!    * Then determine where some important registers are located
!    * and fix fi->frame if it's bogus.
!    */
! 
!   if (fi->status == MY_FRAME_IN_FP)
!     {
!       fi->fsr.regs[FP_REGNUM] = fi->frame;
!       fi->fsr.regs[PC_REGNUM] = fi->frame + 4;
!     }
!   else if (fi->status == MY_FRAME_IN_SP)
!     {
!       /* Fix fi->frame if it's bogus at this point.  */
!       if (fi->next == NULL)
! 	fi->frame = read_sp() + (offset - 4);
!       fi->fsr.regs[PC_REGNUM] = fi->frame;
!     }
! 
!   /*
!    * Finally determine the actual location of each register
!    * that has been placed on the stack.
!    */
! 
!   for (i = 0; i < 8; i++) 
!     {
! #ifdef I386_REGNO_TO_SYMMETRY
!       /* Dynix uses different internal numbering.  Ick.  */
!       if (fi->fsr.regs[I386_REGNO_TO_SYMMETRY(i)])
! 	fi->fsr.regs[I386_REGNO_TO_SYMMETRY(i)] =
! 	  fi->frame - fi->fsr.regs[I386_REGNO_TO_SYMMETRY(i)];
! #else
!       if (fi->fsr.regs[i])
! 	fi->fsr.regs[i] = fi->frame - fi->fsr.regs[i];
! #endif
!     }
! }
! 
! /*
!  * Parse the prologue.
   *
   * We handle these cases:
   *
   * The startup sequence can be at the start of the function,
   * or the function can start with a branch to startup code at the end.
   *
+  * The function can be frameless.
+  *
   * %ebp can be set up with either the 'enter' instruction, or 
   * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful,
   * but was once used in the sys5 compiler)
*************** i386_frame_num_args (fi)
*** 374,448 ****
   * Local space is allocated just below the saved %ebp by either the
   * 'enter' instruction, or by 'subl $<size>, %esp'.  'enter' has
   * a 16 bit unsigned argument for space to allocate, and the
!  * 'addl' instruction could have either a signed byte, or
   * 32 bit immediate.
   *
   * Next, the registers used by this function are pushed.  In
   * the sys5 compiler they will always be in the order: %edi, %esi, %ebx
   * (and sometimes a harmless bug causes it to also save but not restore %eax);
!  * however, the code below is willing to see the pushes in any order,
   * and will handle up to 8 of them.
   *
   * If the setup sequence is at the end of the function, then the
   * next instruction will be a branch back to the start.
   */
  
! void
! i386_frame_find_saved_regs (fip, fsrp)
!      struct frame_info *fip;
!      struct frame_saved_regs *fsrp;
  {
!   long locals = -1;
    unsigned char op;
!   CORE_ADDR dummy_bottom;
!   CORE_ADDR adr;
!   CORE_ADDR pc;
!   int i;
!   
!   memset (fsrp, 0, sizeof *fsrp);
!   
!   /* if frame is the end of a dummy, compute where the
!    * beginning would be
!    */
!   dummy_bottom = fip->frame - 4 - REGISTER_BYTES - CALL_DUMMY_LENGTH;
!   
!   /* check if the PC is in the stack, in a dummy frame */
!   if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) 
      {
!       /* all regs were saved by push_call_dummy () */
!       adr = fip->frame;
!       for (i = 0; i < NUM_REGS; i++) 
  	{
! 	  adr -= REGISTER_RAW_SIZE (i);
! 	  fsrp->regs[i] = adr;
  	}
-       return;
      }
    
!   pc = get_pc_function_start (fip->pc);
!   if (pc != 0)
!     locals = i386_get_frame_setup (pc);
!   
!   if (locals >= 0) 
      {
!       adr = fip->frame - 4 - locals;
!       for (i = 0; i < 8; i++) 
! 	{
! 	  op = codestream_get ();
! 	  if (op < 0x50 || op > 0x57)
! 	    break;
  #ifdef I386_REGNO_TO_SYMMETRY
! 	  /* Dynix uses different internal numbering.  Ick.  */
! 	  fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
  #else
! 	  fsrp->regs[op - 0x50] = adr;
  #endif
! 	  adr -= 4;
! 	}
      }
-   
-   fsrp->regs[PC_REGNUM] = fip->frame + 4;
-   fsrp->regs[FP_REGNUM] = fip->frame;
  }
  
  /* return pc of first real instruction */
--- 449,604 ----
   * Local space is allocated just below the saved %ebp by either the
   * 'enter' instruction, or by 'subl $<size>, %esp'.  'enter' has
   * a 16 bit unsigned argument for space to allocate, and the
!  * 'subl' instruction could have either a signed byte, or
   * 32 bit immediate.
   *
   * Next, the registers used by this function are pushed.  In
   * the sys5 compiler they will always be in the order: %edi, %esi, %ebx
   * (and sometimes a harmless bug causes it to also save but not restore %eax);
!  * however, the code is willing to see the pushes in any order,
   * and will handle up to 8 of them.
   *
   * If the setup sequence is at the end of the function, then the
   * next instruction will be a branch back to the start.
   */
  
! static void
! i386_analyze_prologue (fi, skip_prologue)
!     struct frame_info *fi;
!     int skip_prologue;
  {
!   CORE_ADDR func_addr, func_end;
!   char *name;
    unsigned char op;
!   int status;
! 
!   /* Find the start of this function.  */
!   status = find_pc_partial_function (fi->pc, &name, &func_addr, &func_end);
! 
!   /* Do nothing if we couldn't find the start of this function.  */
!   if (status == 0)
!     return;
! 
!   /* If we're in start, then give up.  */
!   if (strcmp (name, "start") == 0)
      {
!       fi->status = NO_MORE_FRAMES;
!       return;
!     }
! 
!   /* At the start of a function our frame is in the stack pointer.  */
!   fi->status = MY_FRAME_IN_SP;
!   fi->stack_size = 0;
! 
!   /* If we're physically on the first insn of a prologue, then our frame
!      hasn't been allocated yet.  And if we're physically on an "return"
!      instruction, then our frame has already been deallocated.  */
!   if (!skip_prologue)
!     {
!       codestream_seek (fi->pc);
!       op = codestream_peek();
!       if (fi->pc == func_addr
! 	  || op == 0xc2 || op == 0xc3 || op == 0xca || op == 0xcb)
  	{
! 	  if (fi->next == NULL)
! 	    {
! 	      fi->frame = read_sp();
! 	      fi->fsr.regs[PC_REGNUM] = fi->frame;
! 	      fi->status = INCOMPLETE_FRAME;
! 	    }
!           return;
  	}
      }
+ 
+   /* Start scanning on the first instruction of this function.  */
+   codestream_seek (func_addr);
+ 
+   i386_follow_jump ();
+ 
+   i386_get_frame_setup (fi);
    
!   i386_frame_find_saved_regs (fi);
! }
! 
! /* Function: frame_chain
!    Figure out and return the caller's frame pointer given current
!    frame_info struct.
! 
!    We don't handle dummy frames yet but we would probably just return the
!    stack pointer that was in use at the time the function call was made?  */
! 
! CORE_ADDR
! i386_frame_chain (fi)
!      struct frame_info *fi;
! {
!   struct frame_info dummy_frame;
! 
!   /* Walk through the prologue to determine the stack size,
!      location of saved registers, end of the prologue, etc.  */
!   if (fi->status == 0)
!     i386_analyze_prologue (fi, 0);
! 
!   /* Quit now if i386_analyze_prologue set NO_MORE_FRAMES.  */
!   if (fi->status & NO_MORE_FRAMES)
!     return 0;
! 
!   /* Now that we've analyzed our prologue, determine the frame
!      pointer for our caller.
! 
!      If our caller has a frame pointer, then we need to
!      find the entry value of %ebp to our function.
! 
!        If fsr.regs[FP_REGNUM] is nonzero, then it's at the memory
!        location pointed to by fsr.regs[FP_REGNUM].
! 
!        Else it's still in %ebp.
! 
!      If our caller does not have a frame pointer, then his
!      frame base is fi->frame + <pc save space> +
!      <caller's register save space> + <caller's stack size>
!      assuming that the caller's stack pointer was unchanging.
!        
!      The easiest way to get that info is to analyze our caller's frame.
!      So we set up a dummy frame and call i386_init_extra_frame_info to
!      find stuff for us.  BTW, the actual value of dummy_frame.frame
!      doesn't matter so long as it isn't zero.  */
! 
!   dummy_frame.next = fi;
!   dummy_frame.frame = fi->frame;
!   i386_init_extra_frame_info (&dummy_frame);
! 
!   if (dummy_frame.status & MY_FRAME_IN_FP)
!     {
!       /* Our caller has a frame pointer.  So find the frame in %ebp or
!          in the stack.  */
!       if (fi->fsr.regs[FP_REGNUM])
! 	return read_memory_integer (fi->fsr.regs[FP_REGNUM], REGISTER_SIZE);
!       else
! 	return read_register (FP_REGNUM);
!     }
!   else
      {
!       int offset;
!       int i;
! 
!       offset = 4 + dummy_frame.stack_size;
! 
!       for (i = 0; i < 8; i++)
  #ifdef I386_REGNO_TO_SYMMETRY
! 	/* Dynix uses different internal numbering.  Ick.  */
! 	if (dummy_frame.fsr.regs[I386_REGNO_TO_SYMMETRY(i)])
! 	  offset += 4;
  #else
! 	if (dummy_frame.fsr.regs[i])
! 	  offset += 4;
  #endif
! 
!       /* Our caller does not have a frame pointer.  Assume his stack
! 	 pointer was constant which means that his frame starts at
! 	 the base of our frame (fi->frame) + pc save space +
! 	 <his register save space> + <his size>. */
!       return fi->frame + offset;
      }
  }
  
  /* return pc of first real instruction */
*************** i386_skip_prologue (pc)
*** 457,479 ****
  				      0x5b,             /* popl   %ebx */
  				    };
    CORE_ADDR pos;
    
!   if (i386_get_frame_setup (pc) < 0)
!     return (pc);
!   
!   /* found valid frame setup - codestream now points to 
!    * start of push instructions for saving registers
!    */
!   
!   /* skip over register saves */
!   for (i = 0; i < 8; i++)
!     {
!       op = codestream_peek ();
!       /* break if not pushl inst */
!       if (op < 0x50 || op > 0x57) 
! 	break;
!       codestream_get ();
!     }
  
    /* The native cc on SVR4 in -K PIC mode inserts the following code to get
       the address of the global offset table (GOT) into register %ebx.
--- 613,624 ----
  				      0x5b,             /* popl   %ebx */
  				    };
    CORE_ADDR pos;
+   struct frame_info fi;
    
!   fi.frame = NULL;
!   fi.pc = pc;
! 
!   i386_analyze_prologue (&fi, 1);
  
    /* The native cc on SVR4 in -K PIC mode inserts the following code to get
       the address of the global offset table (GOT) into register %ebx.
*************** i386_skip_prologue (pc)
*** 525,531 ****
    
    i386_follow_jump ();
    
!   return (codestream_tell ());
  }
  
  void
--- 670,676 ----
    
    i386_follow_jump ();
    
!   return codestream_tell ();
  }
  
  void
*************** void
*** 550,561 ****
  i386_pop_frame ()
  {
    struct frame_info *frame = get_current_frame ();
-   CORE_ADDR fp;
    int regnum;
    struct frame_saved_regs fsr;
    char regbuf[MAX_REGISTER_RAW_SIZE];
    
-   fp = FRAME_FP (frame);
    get_frame_saved_regs (frame, &fsr);
    for (regnum = 0; regnum < NUM_REGS; regnum++) 
      {
--- 695,704 ----
*************** i386_pop_frame ()
*** 568,576 ****
  				REGISTER_RAW_SIZE (regnum));
  	}
      }
!   write_register (FP_REGNUM, read_memory_integer (fp, 4));
!   write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
!   write_register (SP_REGNUM, fp + 8);
    flush_cached_frames ();
  }
  
--- 711,718 ----
  				REGISTER_RAW_SIZE (regnum));
  	}
      }
!   write_register (PC_REGNUM, read_memory_integer (fsr.regs[PC_REGNUM], 4));
!   write_register (SP_REGNUM, fsr.regs[PC_REGNUM] + 4);
    flush_cached_frames ();
  }
  
*************** skip_trampoline_code (pc, name)
*** 712,717 ****
--- 854,887 ----
    return 0;			/* not a trampoline */
  }
  
+ /* Function: init_extra_frame_info
+    Setup the frame's frame pointer, pc, and frame addresses for saved
+    registers.  Most of the work is done in i386_analyze_prologue().
+ 
+    Note that when we are called for the last frame (currently active frame),
+    that fi->pc and fi->frame will already be setup.  However, fi->frame will
+    be valid only if this routine uses FP.  For previous frames, fi->frame will
+    always be correct.  i386_analyze_prologue will fix fi->frame if
+    it's not valid.
+ 
+    We can be called with the PC in the call dummy under two circumstances.
+    First, during normal backtracing, second, while figuring out the frame
+    pointer just prior to calling the target function (see run_stack_dummy).  */
+ 
+ void
+ i386_init_extra_frame_info (fi)
+      struct frame_info *fi;
+ {
+ 
+   if (fi->next)
+     fi->pc = FRAME_SAVED_PC (fi->next);
+ 
+   memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
+   fi->status = 0;
+   fi->stack_size = 0;
+ 
+   i386_analyze_prologue (fi, 0);
+ }
  
  void
  _initialize_i386_tdep ()
*** gdb/config/i386/tm-i386.h.ORIGINAL	Thu Jan  4 02:23:24 1996
--- gdb/config/i386/tm-i386.h	Mon Nov  2 23:11:50 1998
*************** extern void i386_extract_return_value PA
*** 188,193 ****
--- 188,200 ----
  
  #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
  
+ #define EXTRA_FRAME_INFO struct frame_saved_regs fsr; int status; int stack_size;
+ 
+ #define INIT_EXTRA_FRAME_INFO(fromleaf, fi) i386_init_extra_frame_info (fi)
+ #define INIT_FRAME_PC		/* Not necessary */
+ 
+ extern void i386_init_extra_frame_info PARAMS ((struct frame_info *));
+ 
  /* The following redefines make backtracing through sigtramp work.
     They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
     from the sigcontext structure which is pushed by the kernel on the
*************** extern void i386_extract_return_value PA
*** 202,228 ****
    ((thisframe)->signal_handler_caller \
     ? (thisframe)->frame \
     : (!inside_entry_file ((thisframe)->pc) \
!       ? read_memory_integer ((thisframe)->frame, 4) \
        : 0))
  
! /* A macro that tells us whether the function invocation represented
!    by FI does not have a frame on the stack associated with it.  If it
!    does not, FRAMELESS is set to 1, else 0.  */
! 
! #define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
!   do { \
!     if ((FI)->signal_handler_caller) \
!       (FRAMELESS) = 0; \
!     else \
!       (FRAMELESS) = frameless_look_for_prologue(FI); \
!   } while (0)
  
  /* Saved Pc.  Get it from sigcontext if within sigtramp.  */
  
  #define FRAME_SAVED_PC(FRAME) \
    (((FRAME)->signal_handler_caller \
      ? sigtramp_saved_pc (FRAME) \
!     : read_memory_integer ((FRAME)->frame + 4, 4)) \
     )
  
  extern CORE_ADDR sigtramp_saved_pc PARAMS ((struct frame_info *));
--- 209,225 ----
    ((thisframe)->signal_handler_caller \
     ? (thisframe)->frame \
     : (!inside_entry_file ((thisframe)->pc) \
!       ? i386_frame_chain (thisframe) \
        : 0))
  
! extern CORE_ADDR i386_frame_chain PARAMS ((struct frame_info *));
  
  /* Saved Pc.  Get it from sigcontext if within sigtramp.  */
  
  #define FRAME_SAVED_PC(FRAME) \
    (((FRAME)->signal_handler_caller \
      ? sigtramp_saved_pc (FRAME) \
!     : read_memory_integer ((FRAME)->fsr.regs[PC_REGNUM], 4)) \
     )
  
  extern CORE_ADDR sigtramp_saved_pc PARAMS ((struct frame_info *));
*************** extern int i386_frame_num_args PARAMS ((
*** 248,259 ****
     ways in the stack frame.  sp is even more special:
     the address we return for it IS the sp for the next frame.  */
  
! #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
! { i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
! 
! extern void i386_frame_find_saved_regs PARAMS ((struct frame_info *,
! 						struct frame_saved_regs *));
! 
  
  /* Things needed for making the inferior call functions.  */
  
--- 245,251 ----
     ways in the stack frame.  sp is even more special:
     the address we return for it IS the sp for the next frame.  */
  
! #define FRAME_FIND_SAVED_REGS(fi, regaddr) regaddr = fi->fsr
  
  /* Things needed for making the inferior call functions.  */
  
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------




More information about the Gdb-patches mailing list