[committed] Use pv_stack in s390-tdep.c

Ulrich Weigand uweigand@de.ibm.com
Sun Apr 9 01:21:00 GMT 2006


Hello,

this patch expands on using the prologue-value infrastructure by
switching to the pv_stack mechanism to track stack slot contents.

Tested on s390-ibm-linux and s390x-ibm-linux.
Committed to mainline.

Bye,
Ulrich


ChangeLog:

	* s390-tdep.c (struct s390_prologue_data): New field 'stack'.
	(s390_store): Call pv_area_store to track stack slots.
	(s390_load): Call pv_area_fetch to track stack slots.
	(s390_check_for_saved): New function.
	(s390_analyze_prologue): Call pv_area_scan.  Allocate and free stack.

Index: gdb/s390-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/s390-tdep.c,v
retrieving revision 1.152
diff -c -p -r1.152 s390-tdep.c
*** gdb/s390-tdep.c	9 Apr 2006 00:26:08 -0000	1.152
--- gdb/s390-tdep.c	9 Apr 2006 01:15:32 -0000
*************** is_rxy (bfd_byte *insn, int op1, int op2
*** 716,721 ****
--- 716,724 ----
  
  struct s390_prologue_data {
  
+   /* The stack.  */
+   struct pv_area *stack;
+ 
    /* The size of a GPR or FPR.  */
    int gpr_size;
    int fpr_size;
*************** s390_store (struct s390_prologue_data *d
*** 768,775 ****
  	    pv_t value)
  {
    pv_t addr = s390_addr (data, d2, x2, b2);
!   pv_t cfa, offset;
!   int i;
  
    /* Check whether we are storing the backchain.  */
    offset = pv_subtract (data->gpr[S390_SP_REGNUM - S390_R0_REGNUM], addr);
--- 771,777 ----
  	    pv_t value)
  {
    pv_t addr = s390_addr (data, d2, x2, b2);
!   pv_t offset;
  
    /* Check whether we are storing the backchain.  */
    offset = pv_subtract (data->gpr[S390_SP_REGNUM - S390_R0_REGNUM], addr);
*************** s390_store (struct s390_prologue_data *d
*** 784,820 ****
  
  
    /* Check whether we are storing a register into the stack.  */
!   cfa = pv_register (S390_SP_REGNUM, 16 * data->gpr_size + 32);
!   offset = pv_subtract (cfa, addr);
! 
!   if (pv_is_constant (offset)
!       && offset.k < INT_MAX && offset.k > 0
!       && offset.k % data->gpr_size == 0)
!     {
!       /* If we are storing the original value of a register, we want to
! 	 record the CFA offset.  If the same register is stored multiple
! 	 times, the stack slot with the highest address counts.  */
!       
!       for (i = 0; i < S390_NUM_GPRS; i++)
! 	if (size == data->gpr_size
! 	    && pv_is_register_k (value, S390_R0_REGNUM + i, 0))
! 	  if (data->gpr_slot[i] == 0
! 	      || data->gpr_slot[i] > offset.k)
! 	    {
! 	      data->gpr_slot[i] = offset.k;
! 	      return;
! 	    }
! 
!       for (i = 0; i < S390_NUM_FPRS; i++)
! 	if (size == data->fpr_size
! 	    && pv_is_register_k (value, S390_F0_REGNUM + i, 0))
! 	  if (data->fpr_slot[i] == 0
! 	      || data->fpr_slot[i] > offset.k)
! 	    {
! 	      data->fpr_slot[i] = offset.k;
! 	      return;
! 	    }
!     }
  
  
    /* Note: If this is some store we cannot identify, you might think we
--- 786,793 ----
  
  
    /* Check whether we are storing a register into the stack.  */
!   if (!pv_area_store_would_trash (data->stack, addr))
!     pv_area_store (data->stack, addr, size, value);
  
  
    /* Note: If this is some store we cannot identify, you might think we
*************** s390_load (struct s390_prologue_data *da
*** 832,839 ****
  	   
  {
    pv_t addr = s390_addr (data, d2, x2, b2);
!   pv_t cfa, offset;
!   int i;
  
    /* If it's a load from an in-line constant pool, then we can
       simulate that, under the assumption that the code isn't
--- 805,811 ----
  	   
  {
    pv_t addr = s390_addr (data, d2, x2, b2);
!   pv_t offset;
  
    /* If it's a load from an in-line constant pool, then we can
       simulate that, under the assumption that the code isn't
*************** s390_load (struct s390_prologue_data *da
*** 851,875 ****
      }
  
    /* Check whether we are accessing one of our save slots.  */
!   cfa = pv_register (S390_SP_REGNUM, 16 * data->gpr_size + 32);
!   offset = pv_subtract (cfa, addr);
  
!   if (pv_is_constant (offset)
!       && offset.k < INT_MAX && offset.k > 0)
!     {
!       for (i = 0; i < S390_NUM_GPRS; i++)
! 	if (offset.k == data->gpr_slot[i])
! 	  return pv_register (S390_R0_REGNUM + i, 0);
  
!       for (i = 0; i < S390_NUM_FPRS; i++)
! 	if (offset.k == data->fpr_slot[i])
! 	  return pv_register (S390_F0_REGNUM + i, 0);
!     }
  
!   /* Otherwise, we don't know the value.  */
!   return pv_unknown ();
  }
-             
  
  /* Analyze the prologue of the function starting at START_PC,
     continuing at most until CURRENT_PC.  Initialize DATA to
--- 823,873 ----
      }
  
    /* Check whether we are accessing one of our save slots.  */
!   return pv_area_fetch (data->stack, addr, size);
! }
  
! /* Function for finding saved registers in a 'struct pv_area'; we pass
!    this to pv_area_scan.
  
!    If VALUE is a saved register, ADDR says it was saved at a constant
!    offset from the frame base, and SIZE indicates that the whole
!    register was saved, record its offset in the reg_offset table in
!    PROLOGUE_UNTYPED.  */
! static void
! s390_check_for_saved (void *data_untyped, pv_t addr, CORE_ADDR size, pv_t value)
! {
!   struct s390_prologue_data *data = data_untyped;
!   int i, offset;
! 
!   if (!pv_is_register (addr, S390_SP_REGNUM))
!     return;
! 
!   offset = 16 * data->gpr_size + 32 - addr.k;
  
!   /* If we are storing the original value of a register, we want to
!      record the CFA offset.  If the same register is stored multiple
!      times, the stack slot with the highest address counts.  */
!  
!   for (i = 0; i < S390_NUM_GPRS; i++)
!     if (size == data->gpr_size
! 	&& pv_is_register_k (value, S390_R0_REGNUM + i, 0))
!       if (data->gpr_slot[i] == 0
! 	  || data->gpr_slot[i] > offset)
! 	{
! 	  data->gpr_slot[i] = offset;
! 	  return;
! 	}
! 
!   for (i = 0; i < S390_NUM_FPRS; i++)
!     if (size == data->fpr_size
! 	&& pv_is_register_k (value, S390_F0_REGNUM + i, 0))
!       if (data->fpr_slot[i] == 0
! 	  || data->fpr_slot[i] > offset)
! 	{
! 	  data->fpr_slot[i] = offset;
! 	  return;
! 	}
  }
  
  /* Analyze the prologue of the function starting at START_PC,
     continuing at most until CURRENT_PC.  Initialize DATA to
*************** s390_analyze_prologue (struct gdbarch *g
*** 901,906 ****
--- 899,906 ----
    {
      int i;
  
+     data->stack = make_pv_area (S390_SP_REGNUM);
+ 
      /* For the purpose of prologue tracking, we consider the GPR size to
         be equal to the ABI word size, even if it is actually larger
         (i.e. when running a 32-bit binary under a 64-bit kernel).  */
*************** s390_analyze_prologue (struct gdbarch *g
*** 1123,1128 ****
--- 1123,1134 ----
        }
      }
  
+   /* Record where all the registers were saved.  */
+   pv_area_scan (data->stack, s390_check_for_saved, data);
+ 
+   free_pv_area (data->stack);
+   data->stack = NULL;
+ 
    return result;
  }
  
-- 
  Dr. Ulrich Weigand
  Linux on zSeries Development
  Ulrich.Weigand@de.ibm.com



More information about the Gdb-patches mailing list