unwind-dw2.c (_Unwind_FrameState): Add eh_ptr.
authorMark Kettenis <kettenis@wins.uva.nl>
Thu, 19 Jul 2001 18:20:49 +0000 (20:20 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 19 Jul 2001 18:20:49 +0000 (20:20 +0200)
* unwind-dw2.c (_Unwind_FrameState): Add eh_ptr.
(extract_cie_info): Handle "eh" augmentation properly,
remember eh_ptr.
(struct frame_state, __frame_state_for): New.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r44155

gcc/ChangeLog
gcc/unwind-dw2.c

index 88ab499e2260a397ffaf0bae0b954a13920c3ba2..9d23e01d3d375296e25198fed1dadfae7918f092 100644 (file)
@@ -1,3 +1,11 @@
+2001-07-19  Mark Kettenis  <kettenis@wins.uva.nl>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       * unwind-dw2.c (_Unwind_FrameState): Add eh_ptr.
+       (extract_cie_info): Handle "eh" augmentation properly,
+       remember eh_ptr.
+       (struct frame_state, __frame_state_for): New.
+
 2001-07-19  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
        * config/alpha/osf.h (ASM_OUTPUT_WEAK_ALIAS, ASM_WEAKEN_LABEL,
index 3011bc7341f396fad76227b90f2794c9b450911a..c1aa67fdb5ad2d3b8c1340f660472895b5b263c0 100644 (file)
@@ -106,6 +106,7 @@ typedef struct
   unsigned char fde_encoding;
   unsigned char lsda_encoding;
   unsigned char saw_z;
+  void *eh_ptr;
 } _Unwind_FrameState;
 \f
 /* Read unaligned data from the instruction buffer.  */
@@ -220,6 +221,15 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
   const unsigned char *ret = NULL;
   _Unwind_Ptr tmp;
 
+  /* g++ v2 "eh" has pointer immediately following augmentation string,
+     so it must be handled first.  */
+  if (aug[0] == 'e' && aug[1] == 'h')
+    {
+      fs->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+      aug += 2;
+    }
+
   /* Immediately following the augmentation are the code and
      data alignment and return address column.  */
   p = read_uleb128 (p, &tmp); fs->code_align = tmp;
@@ -242,15 +252,8 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
   /* Iterate over recognized augmentation subsequences.  */
   while (*aug != '\0')
     {
-      /* "eh" was used by g++ v2; recognize and skip.  */
-      if (aug[0] == 'e' && aug[1] == 'h')
-       {
-         p += sizeof (void *);
-         aug += 2;
-       }
-
       /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
-      else if (aug[0] == 'L')
+      if (aug[0] == 'L')
        {
          fs->lsda_encoding = *p++;
          aug += 1;
@@ -937,8 +940,69 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
 
   return _URC_NO_REASON;
 }
+\f
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+struct frame_state * __frame_state_for (void *, struct frame_state *);
+
+/* Called from pre-G++ 3.0 __throw to find the registers to restore for
+   a given PC_TARGET.  The caller should allocate a local variable of
+   `struct frame_state' and pass its address to STATE_IN.  */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+  struct _Unwind_Context context;
+  _Unwind_FrameState fs;
+  int reg;
+
+  memset (&context, 0, sizeof (struct _Unwind_Context));
+  context.ra = pc_target + 1;
+
+  if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
+    return 0;
 
+  /* We have no way to pass a location expression for the CFA to our
+     caller.  It wouldn't understand it anyway.  */
+  if (fs.cfa_how == CFA_EXP)
+    return 0;
 
+  for (reg = 0; reg < DWARF_FRAME_REGISTERS + 1; reg++)
+    {
+      state_in->saved[reg] = fs.regs.reg[reg].how;
+      switch (state_in->saved[reg])
+       {
+       case REG_SAVED_REG:
+         state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
+         break;
+       case REG_SAVED_OFFSET:
+         state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
+         break;
+       default:
+         state_in->reg_or_offset[reg] = 0;
+         break;
+       }
+    }
+
+  state_in->cfa_offset = fs.cfa_offset;
+  state_in->cfa_reg = fs.cfa_reg;
+  state_in->retaddr_column = fs.retaddr_column;
+  state_in->args_size = context.args_size;
+  state_in->eh_ptr = fs.eh_ptr;
+
+  return state_in;
+}
+\f
 static void
 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
 {