linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
authorHans Boehm <Hans_Boehm@hp.com>
Fri, 28 Dec 2001 22:15:41 +0000 (14:15 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 28 Dec 2001 22:15:41 +0000 (14:15 -0800)
        * config/ia64/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
        * config/ia64/unwind-ia64.c (uw_init_context_1): Redo sp, psp,
        bsp setup.  Set pri_unat_loc to something reasonable.
        (uw_install_context): Add missing cast.
        (unw_access_gr): Fix off-by-1 indexing error.

From-SVN: r48352

gcc/ChangeLog
gcc/config/ia64/linux.h
gcc/config/ia64/unwind-ia64.c

index 70fb073130e4602c2275c5de8c6227b247791198..c81563f79ec56a23157fb1079e5343e61ea43c8d 100644 (file)
@@ -1,3 +1,11 @@
+2001-12-28  Hans Bohem  <hans_boehm@hp.com>
+
+       * config/ia64/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
+       * config/ia64/unwind-ia64.c (uw_init_context_1): Redo sp, psp,
+       bsp setup.  Set pri_unat_loc to something reasonable.
+       (uw_install_context): Add missing cast.
+       (unw_access_gr): Fix off-by-1 indexing error.
+
 2001-12-28  Kazu Hirata  <kazu@hxi.com>
 
        * except.c: Fix comment formatting.
index 91f2f39d845792b8317c5077dbc4323641bef5b6..61e80a4a0396b80639bc7dc4b92db74b5823f8bf 100644 (file)
 #undef LINK_EH_SPEC
 #define LINK_EH_SPEC ""
 
-/* End of linux.h */
+/* Do code reading to identify a signal frame, and set the frame
+   state data appropriately.  See unwind-dw2.c for the structs.  */
+
+#ifdef IN_LIBGCC2
+#include <signal.h>
+#include <sys/ucontext.h>
+
+#define IA64_GATE_AREA_START 0xa000000000000100LL
+#define IA64_GATE_AREA_END   0xa000000000010000LL
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)              \
+  if ((CONTEXT)->rp >= IA64_GATE_AREA_START                            \
+      && (CONTEXT)->rp < IA64_GATE_AREA_END)                           \
+    {                                                                  \
+      struct sigframe {                                                        \
+       char scratch[16];                                               \
+       unsigned long sig_number;                                       \
+       struct siginfo *info;                                           \
+       struct sigcontext *sc;                                          \
+      } *frame_ = (struct sigframe *)(CONTEXT)->psp;                   \
+      struct sigcontext *sc_ = frame_->sc;                             \
+                                                                       \
+      /* Restore scratch registers in case the unwinder needs to       \
+        refer to a value stored in one of them.  */                    \
+      {                                                                        \
+       int i_;                                                         \
+                                                                       \
+       for (i_ = 2; i_ < 4; i_++)                                      \
+         (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];                \
+       for (i_ = 8; i_ < 12; i_++)                                     \
+         (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];                \
+       for (i_ = 14; i_ < 32; i_++)                                    \
+         (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];                \
+      }                                                                        \
+                                                                       \
+      (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs);                          \
+      (CONTEXT)->lc_loc = &(sc_->sc_ar_lc);                            \
+      (CONTEXT)->unat_loc = &(sc_->sc_ar_unat);                                \
+      (CONTEXT)->pr = sc_->sc_pr;                                      \
+      (CONTEXT)->psp = sc_->sc_gr[12];                                 \
+                                                                       \
+      /* Don't touch the branch registers.  The kernel doesn't         \
+        pass the preserved branch registers in the sigcontext but      \
+        leaves them intact, so there's no need to do anything          \
+        with them here.  */                                            \
+                                                                       \
+      {                                                                        \
+       unsigned long sof = sc_->sc_cfm & 0x7f;                         \
+       (CONTEXT)->bsp = (unsigned long)                                \
+         ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
+      }                                                                        \
+                                                                       \
+      (FS)->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL;              \
+      (FS)->curr.reg[UNW_REG_RP].val                                   \
+       = (unsigned long)&(sc_->sc_ip) - (CONTEXT)->psp;                \
+      (FS)->curr.reg[UNW_REG_RP].when = -1;                            \
+                                                                       \
+      goto SUCCESS;                                                    \
+    }
+#endif /* IN_LIBGCC2 */
index 052f83948392249344c4a5f6b316b747dc620743..045abe5b7f60d2144a3b60ce85984ed95f341933 100644 (file)
@@ -36,9 +36,6 @@
 #include "unwind-ia64.h"
 
 #if !USING_SJLJ_EXCEPTIONS
-
-#define inline
-\f
 #define UNW_VER(x)             ((x) >> 48)
 #define UNW_FLAG_MASK          0x0000ffff00000000
 #define UNW_FLAG_OSMASK                0x0000f00000000000
@@ -174,7 +171,8 @@ struct _Unwind_Context
   unsigned long regstk_top;    /* bsp for first frame */
 
   /* Current frame info.  */
-  unsigned long bsp;           /* backing store pointer value */
+  unsigned long bsp;           /* backing store pointer value
+                                  corresponding to psp.  */
   unsigned long sp;            /* stack pointer value */
   unsigned long psp;           /* previous sp value */
   unsigned long rp;            /* return pointer */
@@ -203,10 +201,14 @@ struct _Unwind_Context
       enum unw_nat_type type : 3;
       signed long off : 61;            /* NaT word is at loc+nat.off */
     } nat;
-  } ireg[32 - 2];
+  } ireg[32 - 2];      /* Indexed by <register number> - 2 */
 
   unsigned long *br_loc[7];
   void *fr_loc[32 - 2];
+
+  /* ??? We initially point pri_unat_loc here.  The entire NAT bit
+     logic needs work.  */
+  unsigned long initial_unat;
 };
 
 typedef unsigned long unw_word;
@@ -1317,7 +1319,7 @@ unw_access_gr (struct _Unwind_Context *info, int regnum,
   else if (regnum < 32)
     {
       /* Access a non-stacked register.  */
-      ireg = &info->ireg[regnum - 1];
+      ireg = &info->ireg[regnum - 2];
       addr = ireg->loc;
       if (addr)
        {
@@ -1468,7 +1470,7 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
     {
       /* Couldn't find unwind info for this function.  Try an
         os-specific fallback mechanism.  This will necessarily
-        not profide a personality routine or LSDA.  */
+        not provide a personality routine or LSDA.  */
 #ifdef MD_FALLBACK_FRAME_STATE_FOR
       MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
 
@@ -1727,38 +1729,40 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
 }
 
 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
-   level will be the return address and the CFA.  */
+   level will be the return address and the CFA.  Note that CFA = SP+16.  */
    
-#define uw_init_context(CONTEXT) \
-  uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), __builtin_ia64_bsp ())
+#define uw_init_context(CONTEXT)                                       \
+  do {                                                                 \
+    /* ??? There is a whole lot o code in uw_install_context that      \
+       tries to avoid spilling the entire machine state here.  We      \
+       should try to make that work again.  */                         \
+    __builtin_unwind_init();                                           \
+    uw_init_context_1 (CONTEXT, __builtin_ia64_bsp ());                        \
+  } while (0)
 
 static void
-uw_init_context_1 (struct _Unwind_Context *context, void *psp, void *bsp)
+uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
 {
   void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
-  void *sp = __builtin_dwarf_cfa ();
+  /* Set psp to the caller's stack pointer. */
+  void *psp = __builtin_dwarf_cfa () - 16;
   _Unwind_FrameState fs;
 
   /* Flush the register stack to memory so that we can access it.  */
   __builtin_ia64_flushrs ();
 
   memset (context, 0, sizeof (struct _Unwind_Context));
-  context->bsp = (unsigned long) bsp;
-  context->sp = (unsigned long) sp;
+  context->bsp = context->regstk_top = (unsigned long) bsp;
   context->psp = (unsigned long) psp;
   context->rp = (unsigned long) rp;
-
+  asm ("mov %0 = sp" : "=r" (context->sp));
   asm ("mov %0 = pr" : "=r" (context->pr));
+  context->pri_unat_loc = &context->initial_unat;      /* ??? */
   /* ??? Get rnat.  Don't we have to turn off the rse for that?  */
 
   if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
     abort ();
 
-  /* Force the frame state to use the known cfa value.  */
-  fs.curr.reg[UNW_REG_PSP].when = -1;
-  fs.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
-  fs.curr.reg[UNW_REG_PSP].val = sp - psp;
-
   uw_update_context (context, &fs);
 }
 
@@ -1791,8 +1795,9 @@ uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
      target function.  The value that we install below will be
      adjusted by the BR.RET instruction based on the contents
      of AR.PFS.  So we must unadjust that here.  */
-  target->bsp
-    = ia64_rse_skip_regs (target->bsp, (*target->pfs_loc >> 7) & 0x7f);
+  target->bsp = (unsigned long)
+    ia64_rse_skip_regs ((unsigned long *)target->bsp,
+                       (*target->pfs_loc >> 7) & 0x7f);
 
   /* Provide assembly with the offsets into the _Unwind_Context.  */
   asm volatile ("uc_rnat = %0"