+\f
+typedef struct frame_state
+{
+ void *cfa;
+ void *eh_ptr;
+ long cfa_offset;
+ long args_size;
+ long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
+ unsigned short cfa_reg;
+ unsigned short retaddr_column;
+ char saved[PRE_GCC3_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 < PRE_GCC3_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;