IA-64 patch for error in unwind info

James E Wilson wilson@specifixinc.com
Tue Sep 21 21:52:00 GMT 2004


This fixes a problem with the unwind info when registers were saved on
the stack.  The previous stack pointer (psp) relative offsets were
wrong.  They are simple psp relative offsets in the assembly language,
but in the object file they are encoded.  The assembler must translate
from the input numbers to the object file numbers, and we missed this
step when the IA-64 gas port was written.  This patch corrects the
oversight.

This was tested with a binutils build and make check.  There were no
regressions.  This was also tested with a libunwind enabled gdb build
and make check.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

-------------- next part --------------
2004-09-15  James E Wilson  <wilson@specifixinc.com>

	* config/tc-ia64.c (ENCODED_PSP_OFFSET): New.
	(output_rp_psprel, output_pfs_psprel, output_preds_psprel,
	output_spill_base, output_unat_psprel, output_lc_psprel,
	output_fpsr_psprel, output_priunat_psprel, output_bsp_psprel,
	output_bsprestore_psprel, output_rnat_psprel, output_spill_psprel,
	output_spill_psprel_p): Use it.

Index: tc-ia64.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.c,v
retrieving revision 1.116
diff -p -p -r1.116 tc-ia64.c
*** tc-ia64.c	8 Sep 2004 20:52:48 -0000	1.116
--- tc-ia64.c	17 Sep 2004 20:16:23 -0000
*************** static struct
*** 698,703 ****
--- 698,709 ----
    struct label_prologue_count * saved_prologue_counts;
  } unwind;
  
+ /* The input value is a negated offset from psp, and specifies an address
+    psp - offset.  The encoded value is psp + 16 - (4 * offset).  Thus we
+    must add 16 and divide by 4 to get the encoded value.  */
+ 
+ #define ENCODED_PSP_OFFSET(OFFSET) (((OFFSET) + 16) / 4)
+ 
  typedef void (*vbyte_func) PARAMS ((int, char *, char *));
  
  /* Forward declarations:  */
*************** output_rp_psprel (offset)
*** 1810,1816 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (rp_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 1816,1822 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (rp_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_pfs_psprel (offset)
*** 1844,1850 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (pfs_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 1850,1856 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (pfs_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_preds_psprel (offset)
*** 1878,1884 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (preds_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 1884,1890 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (preds_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_spill_base (offset)
*** 1955,1961 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (spill_base);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 1961,1967 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (spill_base);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_unat_psprel (offset)
*** 1980,1986 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (unat_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 1986,1992 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (unat_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_lc_psprel (offset)
*** 2014,2020 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (lc_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 2020,2026 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (lc_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_fpsr_psprel (offset)
*** 2048,2054 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (fpsr_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 2054,2060 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (fpsr_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_priunat_psprel (offset)
*** 2089,2095 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (priunat_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 2095,2101 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (priunat_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_bsp_psprel (offset)
*** 2123,2129 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (bsp_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 2129,2135 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (bsp_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_bspstore_psprel (offset)
*** 2157,2163 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (bspstore_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 2163,2169 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (bspstore_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_rnat_psprel (offset)
*** 2191,2197 ****
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (rnat_psprel);
!   ptr->r.record.p.pspoff = offset / 4;
    return ptr;
  }
  
--- 2197,2203 ----
       unsigned int offset;
  {
    unw_rec_list *ptr = alloc_record (rnat_psprel);
!   ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_spill_psprel (ab, reg, offset)
*** 2248,2254 ****
    unw_rec_list *ptr = alloc_record (spill_psprel);
    ptr->r.record.x.ab = ab;
    ptr->r.record.x.reg = reg;
!   ptr->r.record.x.pspoff = offset / 4;
    return ptr;
  }
  
--- 2254,2260 ----
    unw_rec_list *ptr = alloc_record (spill_psprel);
    ptr->r.record.x.ab = ab;
    ptr->r.record.x.reg = reg;
!   ptr->r.record.x.pspoff = ENCODED_PSP_OFFSET (offset);
    return ptr;
  }
  
*************** output_spill_psprel_p (ab, reg, offset, 
*** 2275,2281 ****
    unw_rec_list *ptr = alloc_record (spill_psprel_p);
    ptr->r.record.x.ab = ab;
    ptr->r.record.x.reg = reg;
!   ptr->r.record.x.pspoff = offset / 4;
    ptr->r.record.x.qp = predicate;
    return ptr;
  }
--- 2281,2287 ----
    unw_rec_list *ptr = alloc_record (spill_psprel_p);
    ptr->r.record.x.ab = ab;
    ptr->r.record.x.reg = reg;
!   ptr->r.record.x.pspoff = ENCODED_PSP_OFFSET (offset);
    ptr->r.record.x.qp = predicate;
    return ptr;
  }


More information about the Binutils mailing list