[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

help with getting toolchain/libc up to sniff?



I have grown increasingly concerned that even with the current
Debian/unstable, there are several failures reported by "make check"
in libunwind.  This is disappointing because most of the necessary
toolchain/libc fixes have been out there for a long time but things
just haven't moved far along enough yet for Debian to pick them up in
the normal course of syncing with upstream.  To make matters worse, I
recently found on a SuSE 9 system that even with the existing fixes in
place, there were two other unwind-related bugs in GCC.  Those have
been fixed in upstream now and as of now, there are no known
unwind-related bugs left.  Thus, it would be really good to get the
Debian toolchain in sync.  Since Debian won't upgrade to gcc-3.4 and
the latest libc over night, I thought I'd spend the effort to backport
the minimal fixes to get things working right.  The result is the 3
patches below, which fix, respectively, GCC v3.3, libc6.1, and
binutils.

Now the problem is that I'd really need help to get these patches
integrated into Debian.  Any help in that direction would be greatly
appreciated (especially since I'll be distracted with my move back to
California over the next few days).

In terms of the safety of these patches: they all have been checked
into the mainline CVS trees and most have been there for months.  I'm
convinced they're all safe for ia64 and even more so for all other
arches (since they're for the most part 100% unaffected).  So really
hope that these could be merged quickly.  Of course, I'd be happy to
answer any questions in case something comes up.

Also, it would be good if GCC on ia64 could be built against
libunwind.  To do so, we'd probably want to make sure that Debian has
libunwind v0.98.2 (which I'll release next week and contains just two
minor bug fixes vs. v0.98.1) installed when building GCC and glibc.
The rest should be automatic.

With the patches below installed, "make check" in libunwind completes
without failures.  Also, I single-stepped a test-program
(test-ptrace-misc) from beginning to end, unwinding after each
instruction and no failures where detected!  Also, the GCC patches
fixes the 2 remaining unexpected libjava in GCC 3.3.5 (with no other
changes), so I really do think this gets Debian/ia64 into much better
shape.

Anybody willing to help getting these into Debian?

	--david

 config/ia64/crtbegin.asm |   22 ++++++++++++++++------
 config/ia64/crtend.asm   |    4 ++++
 config/ia64/ia64.c       |   36 +++++++++++++++++++++++++-----------
 emit-rtl.c               |    5 +++++
 gcc.c                    |    3 +++
 5 files changed, 53 insertions(+), 17 deletions(-)

diff -urN orig/gcc-3.3-3.3.5/src/gcc/config/ia64/crtbegin.asm gcc-3.3-3.3.5/src/gcc/config/ia64/crtbegin.asm
--- orig/gcc-3.3-3.3.5/src/gcc/config/ia64/crtbegin.asm	2003-01-25 09:28:42.000000000 -0800
+++ gcc-3.3-3.3.5/src/gcc/config/ia64/crtbegin.asm	2004-10-28 09:30:53.000000000 -0700
@@ -48,8 +48,9 @@
 	data8	__dso_handle#
 #else
 	.section .bss
+	.align 8
 __dso_handle:
-	data8	0
+	.skip	8
 #endif
 	.hidden __dso_handle#
 
@@ -116,11 +117,15 @@
 	.align	16
 	.proc	__do_global_dtors_aux#
 __do_global_dtors_aux:
+	.prologue
 #ifndef SHARED
 	{ .mii
+	  .save ar.pfs, r35
 	  alloc loc3 = ar.pfs, 0, 4, 1, 0
 	  addl loc0 = @gprel(dtor_ptr#), gp
+	  .save rp, loc1
 	  mov loc1 = b0
+	  .body
 	}
 	{ .mib
 	  mov loc2 = gp
@@ -133,6 +138,7 @@
 		  __cxa_finalize(__dso_handle)
 	*/
 	{ .mii
+	  .save ar.pfs, r35
 	  alloc loc3 = ar.pfs, 0, 4, 1, 0
 	  addl loc0 = @gprel(dtor_ptr#), gp
 	  addl r16 = @ltoff(@fptr(__cxa_finalize#)), gp
@@ -148,16 +154,17 @@
 	{ .mmi
 	  ld8 out0 = [out0]
 (p7)	  ld8 r18 = [r16], 8
+	  .save rp, loc1
 	  mov loc1 = b0
 	  ;;
 	}
-	{ .mfi
+	{ .mmi
 	  mov loc2 = gp
+(p7)	  ld8 gp = [r16]
 (p7)	  mov b6 = r18
 	}
 	{
 	  .mfb
-(p7)	  ld8 gp = [r16]
 (p7)	  br.call.sptk.many b0 = b6
 	}
 	{ .mfb
@@ -189,15 +196,14 @@
 	  adds r15 = 8, r15
 	  ;;
 	}
-	{ .mmi
+	{ .mii
 	  ld8 r16 = [r16]
-	  mov gp = loc2
 	  mov b0 = loc1
+	  mov ar.pfs = loc3
 	  ;;
 	}
 	{ .mib
 	  cmp.ne p6, p0 = r0, r16
-	  mov ar.pfs = loc3
 (p6)	  br.cond.sptk.few 0b
 	}
 	{ .bbb
@@ -209,7 +215,9 @@
 	.align	16
 	.proc	__do_jv_register_classes#
 __do_jv_register_classes:
+	.prologue
 	{ .mlx
+	  .save ar.pfs, r34
 	  alloc loc2 = ar.pfs, 0, 3, 1, 0
 	  movl out0 = @gprel(__JCR_LIST__)
 	  ;;
@@ -232,7 +240,9 @@
 	}
 	{ .mii
 	  ld8 r15 = [r14], 8
+	  .save rp, loc0
 	  mov loc0 = b0
+	  .body
 	  mov loc1 = gp
 	  ;;
 	}
diff -urN orig/gcc-3.3-3.3.5/src/gcc/config/ia64/crtend.asm gcc-3.3-3.3.5/src/gcc/config/ia64/crtend.asm
--- orig/gcc-3.3-3.3.5/src/gcc/config/ia64/crtend.asm	2003-01-25 09:28:42.000000000 -0800
+++ gcc-3.3-3.3.5/src/gcc/config/ia64/crtend.asm	2004-10-28 09:30:53.000000000 -0700
@@ -74,18 +74,22 @@
 #endif
 	.proc __do_global_ctors_aux#
 __do_global_ctors_aux:
+	.prologue
 	/*
 		for (loc0 = __CTOR_END__-1; *p != -1; --p)
 		  (*p) ();
 	*/
 	{ .mlx
+	  .save ar.pfs, r36
 	  alloc loc4 = ar.pfs, 0, 5, 0, 0
 	  movl loc0 = @gprel(__CTOR_END__# - 8)
 	  ;;
 	}
 	{ .mmi
 	  add loc0 = loc0, gp
+	  .save rp, loc1
 	  mov loc1 = b0
+	  .body
 	  ;;
 	}
 	{
diff -urN orig/gcc-3.3-3.3.5/src/gcc/config/ia64/ia64.c gcc-3.3-3.3.5/src/gcc/config/ia64/ia64.c
--- orig/gcc-3.3-3.3.5/src/gcc/config/ia64/ia64.c	2004-09-17 10:56:32.000000000 -0700
+++ gcc-3.3-3.3.5/src/gcc/config/ia64/ia64.c	2004-10-28 09:30:53.000000000 -0700
@@ -2884,10 +2884,13 @@
 	 preserve those input registers used as arguments to the sibling call.
 	 It is unclear how to compute that number here.  */
       if (current_frame_info.n_input_regs != 0)
-	emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
-			      GEN_INT (0), GEN_INT (0),
-			      GEN_INT (current_frame_info.n_input_regs),
-			      GEN_INT (0)));
+	{
+	  rtx n_inputs = GEN_INT (current_frame_info.n_input_regs);
+	  insn = emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
+				GEN_INT (0), GEN_INT (0),
+				n_inputs, GEN_INT (0)));
+	  RTX_FRAME_RELATED_P (insn) = 1;
+	}
     }
 }
 
@@ -7451,13 +7454,24 @@
     {
       dest_regno = REGNO (dest);
 
-      /* If this isn't the final destination for ar.pfs, the alloc
-	 shouldn't have been marked frame related.  */
-      if (dest_regno != current_frame_info.reg_save_ar_pfs)
-	abort ();
-
-      fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
-	       ia64_dbx_register_number (dest_regno));
+      /* If this is the final destination for ar.pfs, then this must
+	 be the alloc in the prologue.  */
+      if (dest_regno == current_frame_info.reg_save_ar_pfs)
+	fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
+		 ia64_dbx_register_number (dest_regno));
+      else
+	{
+	  /* This must be an alloc before a sibcall.  We must drop the
+	     old frame info.  The easiest way to drop the old frame
+	     info is to ensure we had a ".restore sp" directive
+	     followed by a new prologue.  If the procedure doesn't
+	     have a memory-stack frame, we'll issue a dummy ".restore
+	     sp" now.  */
+	  if (current_frame_info.total_size == 0)
+	    /* if haven't done process_epilogue() yet, do it now */
+	    process_epilogue ();
+	  fprintf (asm_out_file, "\t.prologue\n");
+	}
       return 1;
     }
 
diff -urN orig/gcc-3.3-3.3.5/src/gcc/emit-rtl.c gcc-3.3-3.3.5/src/gcc/emit-rtl.c
--- orig/gcc-3.3-3.3.5/src/gcc/emit-rtl.c	2004-10-29 09:09:46.799764298 -0700
+++ gcc-3.3-3.3.5/src/gcc/emit-rtl.c	2004-10-28 05:49:16.000000000 -0700
@@ -5586,6 +5586,11 @@
 
   INSN_SCOPE (new) = INSN_SCOPE (insn);
 
+  /* If the old insn is frame related, then so is the new one.  This is
+     primarily needed for IA-64 unwind info which marks epilogue insns,
+     which may be duplicated by the basic block reordering code.  */
+  RTX_FRAME_RELATED_P (new) = RTX_FRAME_RELATED_P (insn);
+
   /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
      make them.  */
   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
diff -urN orig/gcc-3.3-3.3.5/src/gcc/gcc.c gcc-3.3-3.3.5/src/gcc/gcc.c
--- orig/gcc-3.3-3.3.5/src/gcc/gcc.c	2004-10-29 09:09:46.860310347 -0700
+++ gcc-3.3-3.3.5/src/gcc/gcc.c	2004-10-28 09:33:42.000000000 -0700
@@ -1577,6 +1577,9 @@
 #else
 			    "-lgcc_s%M"
 #endif
+#ifdef USE_LIBUNWIND_EXCEPTIONS
+			    " -lunwind"
+#endif
 			    ,
 			    "-lgcc",
 			    "-lgcc_eh"
 Makeconfig                                      |   18 ++++++++-
 Makerules                                       |    4 +-
 config.h.in                                     |    3 +
 config.make.in                                  |    1 
 configure.in                                    |   17 +++++++++
 nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c |   45 +++++++++++++++++++++---
 6 files changed, 78 insertions(+), 10 deletions(-)

diff -urN orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makeconfig glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makeconfig
--- orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makeconfig	2004-10-29 09:19:49.973173566 -0700
+++ glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makeconfig	2004-10-28 10:47:59.000000000 -0700
@@ -498,12 +498,12 @@
 
 # The static libraries.
 ifeq (yes,$(build-static))
-link-libc-static = $(common-objpfx)libc.a $(gnulib) $(common-objpfx)libc.a
+link-libc-static = $(common-objpfx)libc.a $(static-gnulib) $(common-objpfx)libc.a
 link-extra-libs-static = $(foreach lib,$(LDLIBS-$(@F)),$(common-objpfx)$(lib).a)
 else
 ifeq (yes,$(build-shared))
 # We can try to link the programs with lib*_pic.a...
-link-libc-static = $(gnulib) $(common-objpfx)libc_pic.a
+link-libc-static = $(static-gnulib) $(common-objpfx)libc_pic.a
 link-extra-libs-static = $(link-extra-libs)
 endif
 endif
@@ -511,7 +511,19 @@
 link-extra-libs-bounded = $(foreach lib,$(LDLIBS-$(@F:%-bp=%)),$(common-objpfx)$(lib)_b.a)
 
 ifndef gnulib
-gnulib := -lgcc -lgcc_eh
+ifneq ($(have-cc-with-libunwind),yes)
+  libunwind =
+else
+  libunwind = -lunwind
+endif
+ifneq ($(have-as-needed),yes)
+ libgcc_eh := -lgcc_eh $(libunwind)
+else
+ libgcc_eh := -Wl,--as-needed -lgcc_s$(libgcc_s_suffix) $(libunwind) -Wl,--no-as-needed
+endif
+gnulib := -lgcc $(libgcc_eh)
+static-gnulib := -lgcc -lgcc_eh $(libunwind)
+libc.so-gnulib := -lgcc
 endif
 ifeq ($(elf),yes)
 +preinit = $(addprefix $(csu-objpfx),crti.o)
diff -urN orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makerules glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makerules
--- orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makerules	2004-10-29 09:19:50.451682658 -0700
+++ glibc-2.3.2.ds1/build-tree/glibc-2.3.2/Makerules	2004-10-28 07:58:29.000000000 -0700
@@ -569,8 +569,8 @@
 # Also omits crti.o and crtn.o, which we do not want
 # since we define our own `.init' section specially.
 LDFLAGS-c.so = -nostdlib -nostartfiles
-# But we still want to link libc.so against $(gnulib).
-LDLIBS-c.so += $(gnulib)
+# But we still want to link libc.so against $(libc.so-gnulib).
+LDLIBS-c.so += $(libc.so-gnulib)
 # Give libc.so an entry point and make it directly runnable itself.
 LDFLAGS-c.so += -e __libc_main
 # Pre-link the objects of libc_pic.a so that we can locally resolve
diff -urN orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.h.in glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.h.in
--- orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.h.in	2004-10-29 09:19:46.026938378 -0700
+++ glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.h.in	2004-10-28 08:02:30.000000000 -0700
@@ -153,6 +153,9 @@
    sections.  */
 #undef	HAVE_INITFINI_ARRAY
 
+/* Define if the compiler's exception support is based on libunwind.  */
+#undef	HAVE_CC_WITH_LIBUNWIND
+
 /* Define if the access to static and hidden variables is position independent
    and does not need relocations.  */
 #undef	PI_STATIC_AND_HIDDEN
diff -urN orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.make.in glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.make.in
--- orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.make.in	2004-10-29 09:19:50.853044366 -0700
+++ glibc-2.3.2.ds1/build-tree/glibc-2.3.2/config.make.in	2004-10-28 09:11:43.000000000 -0700
@@ -53,6 +53,7 @@
 have-cpp-asm-debuginfo = @libc_cv_cpp_asm_debuginfo@
 enable-check-abi = @enable_check_abi@
 have-forced-unwind = @libc_cv_forced_unwind@
+have-cc-with-libunwind = @libc_cv_cc_with_libunwind@
 fno-unit-at-a-time = @fno_unit_at_a_time@
 
 static-libgcc = @libc_cv_gcc_static_libgcc@
diff -urN orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/configure.in glibc-2.3.2.ds1/build-tree/glibc-2.3.2/configure.in
--- orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/configure.in	2004-10-29 09:19:50.849138169 -0700
+++ glibc-2.3.2.ds1/build-tree/glibc-2.3.2/configure.in	2004-10-28 07:55:27.000000000 -0700
@@ -1251,6 +1251,23 @@
     AC_DEFINE(HAVE_INITFINI_ARRAY)
   fi
 
+  AC_CACHE_CHECK(for libunwind-support in compiler,
+		 libc_cv_cc_with_libunwind, [
+    cat > conftest.c <<EOF
+int main (void) { return 0; }
+EOF
+    if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static -o conftest \
+       conftest.c -v 2>&1 >/dev/null | grep -q " -lunwind "; then
+      libc_cv_cc_with_libunwind=yes
+    else
+      libc_cv_cc_with_libunwind=no
+    fi
+    rm -f conftest*])
+  AC_SUBST(libc_cv_cc_with_libunwind)
+  if test $libc_cv_cc_with_libunwind = yes; then
+    AC_DEFINE(HAVE_CC_WITH_LIBUNWIND)
+  fi
+
   AC_CACHE_CHECK(for -z nodelete option,
 		 libc_cv_z_nodelete, [dnl
   cat > conftest.c <<EOF
diff -urN orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c glibc-2.3.2.ds1/build-tree/glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c
--- orig/glibc-2.3.2.ds1/build-tree/glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c	2003-03-11 01:20:41.000000000 -0800
+++ glibc-2.3.2.ds1/build-tree/glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c	2004-10-29 08:42:00.835176367 -0700
@@ -36,6 +36,22 @@
    * crtn.s puts the corresponding function epilogues
    in the .init and .fini sections. */
 
+#include <stddef.h>
+
+#ifdef HAVE_INITFINI_ARRAY
+
+__asm__ ("\n\
+#include \"defs.h\"\n\
+\n\
+/*@HEADER_ENDS*/\n\
+\n\
+/*@_init_PROLOG_BEGINS*/\n\
+	.xdata8 \".init_array\",@fptr(__pthread_initialize_minimal_internal)\n\
+/*@_init_PROLOG_ENDS*/\n\
+");
+
+#else
+
 __asm__ ("\n\
 \n\
 #include \"defs.h\"\n\
@@ -48,13 +64,16 @@
 	.global _init#\n\
 	.proc _init#\n\
 _init:\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
 	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
+	.vframe r32\n\
 	mov r32 = r12\n\
+	.save rp, r33\n\
 	mov r33 = b0\n\
+	.body\n\
 	adds r12 = -16, r12\n\
 	;;\n\
-/* we could use r35 to save gp, but we use the stack since that's what\n\
- * all the other init routines will do --davidm 00/04/05 */\n\
 	st8 [r12] = gp, -16\n\
 	br.call.sptk.many b0 = __pthread_initialize_minimal_internal# ;;\n\
 	;;\n\
@@ -62,14 +81,18 @@
 	;;\n\
 	ld8 gp = [r12]\n\
 	;;\n\
-	.align 16\n\
 	.endp _init#\n\
 \n\
 /*@_init_PROLOG_ENDS*/\n\
 \n\
 /*@_init_EPILOG_BEGINS*/\n\
 	.section .init\n\
-	.regstk 0,2,0,0\n\
+	.proc _init#\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
+	.vframe r32\n\
+	.save rp, r33\n\
+	.body\n\
 	mov r12 = r32\n\
 	mov ar.pfs = r34\n\
 	mov b0 = r33\n\
@@ -83,18 +106,28 @@
 	.global _fini#\n\
 	.proc _fini#\n\
 _fini:\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
 	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
+	.vframe r32\n\
 	mov r32 = r12\n\
+	.save rp, r33\n\
 	mov r33 = b0\n\
+	.body\n\
 	adds r12 = -16, r12\n\
 	;;\n\
-	.align 16\n\
 	.endp _fini#\n\
 \n\
 /*@_fini_PROLOG_ENDS*/\n\
 \n\
 /*@_fini_EPILOG_BEGINS*/\n\
 	.section .fini\n\
+	.proc _fini#\n\
+	.prologue\n\
+	.save ar.pfs, r34\n\
+	.vframe r32\n\
+	.save rp, r33\n\
+	.body\n\
 	mov r12 = r32\n\
 	mov ar.pfs = r34\n\
 	mov b0 = r33\n\
@@ -106,3 +139,5 @@
 /*@TRAILER_BEGINS*/\n\
 	.weak	__gmon_start__#\n\
 ");
+
+#endif
 tc-ia64.c |   42 +++++++++++++++++++++++++++---------------
 1 files changed, 27 insertions(+), 15 deletions(-)

diff -urN orig/binutils-2.15/gas/config/tc-ia64.c binutils-2.15/gas/config/tc-ia64.c
--- orig/binutils-2.15/gas/config/tc-ia64.c	2004-05-17 12:36:10.000000000 -0700
+++ binutils-2.15/gas/config/tc-ia64.c	2004-10-28 06:14:59.000000000 -0700
@@ -698,6 +698,12 @@
   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:  */
@@ -1839,7 +1845,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (rp_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -1873,7 +1879,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (pfs_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -1907,7 +1913,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (preds_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -1984,7 +1990,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (spill_base);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2009,7 +2015,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (unat_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2043,7 +2049,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (lc_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2077,7 +2083,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (fpsr_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2118,7 +2124,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (priunat_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2152,7 +2158,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (bsp_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2186,7 +2192,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (bspstore_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2220,7 +2226,7 @@
      unsigned int offset;
 {
   unw_rec_list *ptr = alloc_record (rnat_psprel);
-  ptr->r.record.p.pspoff = offset / 4;
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2277,7 +2283,7 @@
   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;
+  ptr->r.record.x.pspoff = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
@@ -2304,7 +2310,7 @@
   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.pspoff = ENCODED_PSP_OFFSET (offset);
   ptr->r.record.x.qp = predicate;
   return ptr;
 }
@@ -2770,8 +2776,14 @@
 	    break;
 	  }
 	case epilogue:
-	  ptr->r.record.b.t = rlen - 1 - t;
-	  break;
+	  if (t < rlen)
+	    ptr->r.record.b.t = rlen - 1 - t;
+	  else
+	    /* This happens when a memory-stack-less procedure uses a
+	       ".restore sp" directive at the end of a region to pop
+	       the frame state.  */
+	    ptr->r.record.b.t = 0;
+ 	  break;
 
 	case mem_stack_f:
 	case mem_stack_v:

Reply to: