OSDN Git Service

* unwind-dw2.c (_Unwind_FrameState): Add eh_ptr.
[pf3gnuchains/gcc-fork.git] / gcc / unwind-dw2.c
1 /* DWARF2 exception handling and frame unwind runtime interface routines.
2    Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3
4    This file is part of GNU CC.
5
6    GNU CC is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GNU CC is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GNU CC; see the file COPYING.  If not, write to
18    the Free Software Foundation, 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include "tconfig.h"
22 #include "tsystem.h"
23 #include "dwarf2.h"
24 #include "unwind.h"
25 #include "unwind-pe.h"
26 #include "unwind-dw2-fde.h"
27 #include "gthr.h"
28
29
30 #if !USING_SJLJ_EXCEPTIONS
31
32 #ifndef STACK_GROWS_DOWNWARD
33 #define STACK_GROWS_DOWNWARD 0
34 #else
35 #undef STACK_GROWS_DOWNWARD
36 #define STACK_GROWS_DOWNWARD 1
37 #endif
38
39 /* A target can override (perhaps for backward compatibility) how
40    many dwarf2 columns are unwound.  */
41 #ifndef DWARF_FRAME_REGISTERS
42 #define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
43 #endif
44
45 /* This is the register and unwind state for a particular frame.  */
46 struct _Unwind_Context
47 {
48   void *reg[DWARF_FRAME_REGISTERS+1];
49   void *cfa;
50   void *ra;
51   void *lsda;
52   struct dwarf_eh_bases bases;
53   _Unwind_Word args_size;
54 };
55
56 /* Byte size of every register managed by these routines.  */
57 static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS];
58
59 \f
60 /* The result of interpreting the frame unwind info for a frame.
61    This is all symbolic at this point, as none of the values can
62    be resolved until the target pc is located.  */
63 typedef struct
64 {
65   /* Each register save state can be described in terms of a CFA slot,
66      another register, or a location expression.  */
67   struct frame_state_reg_info
68   {
69     struct {
70       union {
71         unsigned int reg;
72         _Unwind_Sword offset;
73         const unsigned char *exp;
74       } loc;
75       enum {
76         REG_UNSAVED,
77         REG_SAVED_OFFSET,
78         REG_SAVED_REG,
79         REG_SAVED_EXP,
80       } how;
81     } reg[DWARF_FRAME_REGISTERS+1];
82
83     /* Used to implement DW_CFA_remember_state.  */
84     struct frame_state_reg_info *prev;
85   } regs;
86
87   /* The CFA can be described in terms of a reg+offset or a
88      location expression.  */
89   _Unwind_Sword cfa_offset;
90   _Unwind_Word cfa_reg;
91   const unsigned char *cfa_exp;
92   enum {
93     CFA_UNSET,
94     CFA_REG_OFFSET,
95     CFA_EXP,
96   } cfa_how;
97
98   /* The PC described by the current frame state.  */
99   void *pc;
100
101   /* The information we care about from the CIE/FDE.  */
102   _Unwind_Personality_Fn personality;
103   signed int data_align;
104   unsigned int code_align;
105   unsigned char retaddr_column;
106   unsigned char fde_encoding;
107   unsigned char lsda_encoding;
108   unsigned char saw_z;
109   void *eh_ptr;
110 } _Unwind_FrameState;
111 \f
112 /* Read unaligned data from the instruction buffer.  */
113
114 union unaligned
115 {
116   void *p;
117   unsigned u2 __attribute__ ((mode (HI)));
118   unsigned u4 __attribute__ ((mode (SI)));
119   unsigned u8 __attribute__ ((mode (DI)));
120   signed s2 __attribute__ ((mode (HI)));
121   signed s4 __attribute__ ((mode (SI)));
122   signed s8 __attribute__ ((mode (DI)));
123 } __attribute__ ((packed));
124
125 static inline void *
126 read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
127
128 static inline int
129 read_1u (const void *p) { return *(const unsigned char *)p; }
130
131 static inline int
132 read_1s (const void *p) { return *(const signed char *)p; }
133
134 static inline int
135 read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
136
137 static inline int
138 read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
139
140 static inline unsigned int
141 read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
142
143 static inline int
144 read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
145
146 static inline unsigned long
147 read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
148
149 static inline unsigned long
150 read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
151 \f
152 /* Get the value of register REG as saved in CONTEXT.  */
153
154 inline _Unwind_Word
155 _Unwind_GetGR (struct _Unwind_Context *context, int index)
156 {
157   /* This will segfault if the register hasn't been saved.  */
158   return * (_Unwind_Word *) context->reg[index];
159 }
160
161 /* Overwrite the saved value for register REG in CONTEXT with VAL.  */
162
163 inline void
164 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
165 {
166   * (_Unwind_Word *) context->reg[index] = val;
167 }
168
169 /* Retrieve the return address for CONTEXT.  */
170
171 inline _Unwind_Ptr
172 _Unwind_GetIP (struct _Unwind_Context *context)
173 {
174   return (_Unwind_Ptr) context->ra;
175 }
176
177 /* Overwrite the return address for CONTEXT with VAL.  */
178
179 inline void
180 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
181 {
182   context->ra = (void *) val;
183 }
184
185 void *
186 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
187 {
188   return context->lsda;
189 }
190
191 _Unwind_Ptr
192 _Unwind_GetRegionStart (struct _Unwind_Context *context)
193 {
194   return (_Unwind_Ptr) context->bases.func;
195 }
196
197 #ifndef __ia64__
198 _Unwind_Ptr
199 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
200 {
201   return (_Unwind_Ptr) context->bases.dbase;
202 }
203
204 _Unwind_Ptr
205 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
206 {
207   return (_Unwind_Ptr) context->bases.tbase;
208 }
209 #endif
210 \f
211 /* Extract any interesting information from the CIE for the translation
212    unit F belongs to.  Return a pointer to the byte after the augmentation,
213    or NULL if we encountered an undecipherable augmentation.  */
214
215 static const unsigned char *
216 extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
217                   _Unwind_FrameState *fs)
218 {
219   const unsigned char *aug = cie->augmentation;
220   const unsigned char *p = aug + strlen (aug) + 1;
221   const unsigned char *ret = NULL;
222   _Unwind_Ptr tmp;
223
224   /* g++ v2 "eh" has pointer immediately following augmentation string,
225      so it must be handled first.  */
226   if (aug[0] == 'e' && aug[1] == 'h')
227     {
228       fs->eh_ptr = read_pointer (p);
229       p += sizeof (void *);
230       aug += 2;
231     }
232
233   /* Immediately following the augmentation are the code and
234      data alignment and return address column.  */
235   p = read_uleb128 (p, &tmp); fs->code_align = tmp;
236   p = read_sleb128 (p, &tmp); fs->data_align = (saddr) tmp;
237   fs->retaddr_column = *p++;
238   fs->lsda_encoding = DW_EH_PE_omit;
239
240   /* If the augmentation starts with 'z', then a uleb128 immediately
241      follows containing the length of the augmentation field following
242      the size.  */
243   if (*aug == 'z')
244     {
245       p = read_uleb128 (p, &tmp);
246       ret = p + tmp;
247
248       fs->saw_z = 1;
249       ++aug;
250     }
251
252   /* Iterate over recognized augmentation subsequences.  */
253   while (*aug != '\0')
254     {
255       /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
256       if (aug[0] == 'L')
257         {
258           fs->lsda_encoding = *p++;
259           aug += 1;
260         }
261
262       /* "R" indicates a byte indicating how FDE addresses are encoded.  */
263       else if (aug[0] == 'R')
264         {
265           fs->fde_encoding = *p++;
266           aug += 1;
267         }
268
269       /* "P" indicates a personality routine in the CIE augmentation.  */
270       else if (aug[0] == 'P')
271         {
272           p = read_encoded_value (context, *p, p + 1,
273                                   (_Unwind_Ptr *) &fs->personality);
274           aug += 1;
275         }
276
277       /* Otherwise we have an unknown augmentation string.
278          Bail unless we saw a 'z' prefix.  */
279       else
280         return ret;
281     }
282
283   return ret ? ret : p;
284 }
285
286
287 /* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
288    onto the stack to start.  */
289
290 static _Unwind_Word
291 execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
292                   struct _Unwind_Context *context, _Unwind_Word initial)
293 {
294   _Unwind_Word stack[64];       /* ??? Assume this is enough. */
295   int stack_elt;
296
297   stack[0] = initial;
298   stack_elt = 1;
299
300   while (op_ptr < op_end)
301     {
302       enum dwarf_location_atom op = *op_ptr++;
303       _Unwind_Word result, reg;
304       _Unwind_Sword offset;
305       _Unwind_Ptr ptrtmp;
306
307       switch (op)
308         {
309         case DW_OP_lit0:
310         case DW_OP_lit1:
311         case DW_OP_lit2:
312         case DW_OP_lit3:
313         case DW_OP_lit4:
314         case DW_OP_lit5:
315         case DW_OP_lit6:
316         case DW_OP_lit7:
317         case DW_OP_lit8:
318         case DW_OP_lit9:
319         case DW_OP_lit10:
320         case DW_OP_lit11:
321         case DW_OP_lit12:
322         case DW_OP_lit13:
323         case DW_OP_lit14:
324         case DW_OP_lit15:
325         case DW_OP_lit16:
326         case DW_OP_lit17:
327         case DW_OP_lit18:
328         case DW_OP_lit19:
329         case DW_OP_lit20:
330         case DW_OP_lit21:
331         case DW_OP_lit22:
332         case DW_OP_lit23:
333         case DW_OP_lit24:
334         case DW_OP_lit25:
335         case DW_OP_lit26:
336         case DW_OP_lit27:
337         case DW_OP_lit28:
338         case DW_OP_lit29:
339         case DW_OP_lit30:
340         case DW_OP_lit31:
341           result = op - DW_OP_lit0;
342           break;
343
344         case DW_OP_addr:
345           result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
346           op_ptr += sizeof (void *);
347           break;
348
349         case DW_OP_const1u:
350           result = read_1u (op_ptr);
351           op_ptr += 1;
352           break;
353         case DW_OP_const1s:
354           result = read_1s (op_ptr);
355           op_ptr += 1;
356           break;
357         case DW_OP_const2u:
358           result = read_2u (op_ptr);
359           op_ptr += 2;
360           break;
361         case DW_OP_const2s:
362           result = read_2s (op_ptr);
363           op_ptr += 2;
364           break;
365         case DW_OP_const4u:
366           result = read_4u (op_ptr);
367           op_ptr += 4;
368           break;
369         case DW_OP_const4s:
370           result = read_4s (op_ptr);
371           op_ptr += 4;
372           break;
373         case DW_OP_const8u:
374           result = read_8u (op_ptr);
375           op_ptr += 8;
376           break;
377         case DW_OP_const8s:
378           result = read_8s (op_ptr);
379           op_ptr += 8;
380           break;
381         case DW_OP_constu:
382           op_ptr = read_uleb128 (op_ptr, &ptrtmp);
383           result = ptrtmp;
384           break;
385         case DW_OP_consts:
386           op_ptr = read_sleb128 (op_ptr, &ptrtmp);
387           result = (saddr)ptrtmp;
388           break;
389
390         case DW_OP_reg0:
391         case DW_OP_reg1:
392         case DW_OP_reg2:
393         case DW_OP_reg3:
394         case DW_OP_reg4:
395         case DW_OP_reg5:
396         case DW_OP_reg6:
397         case DW_OP_reg7:
398         case DW_OP_reg8:
399         case DW_OP_reg9:
400         case DW_OP_reg10:
401         case DW_OP_reg11:
402         case DW_OP_reg12:
403         case DW_OP_reg13:
404         case DW_OP_reg14:
405         case DW_OP_reg15:
406         case DW_OP_reg16:
407         case DW_OP_reg17:
408         case DW_OP_reg18:
409         case DW_OP_reg19:
410         case DW_OP_reg20:
411         case DW_OP_reg21:
412         case DW_OP_reg22:
413         case DW_OP_reg23:
414         case DW_OP_reg24:
415         case DW_OP_reg25:
416         case DW_OP_reg26:
417         case DW_OP_reg27:
418         case DW_OP_reg28:
419         case DW_OP_reg29:
420         case DW_OP_reg30:
421         case DW_OP_reg31:
422           result = _Unwind_GetGR (context, op - DW_OP_reg0);
423           break;
424         case DW_OP_regx:
425           op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp;
426           result = _Unwind_GetGR (context, reg);
427           break;
428
429         case DW_OP_breg0:
430         case DW_OP_breg1:
431         case DW_OP_breg2:
432         case DW_OP_breg3:
433         case DW_OP_breg4:
434         case DW_OP_breg5:
435         case DW_OP_breg6:
436         case DW_OP_breg7:
437         case DW_OP_breg8:
438         case DW_OP_breg9:
439         case DW_OP_breg10:
440         case DW_OP_breg11:
441         case DW_OP_breg12:
442         case DW_OP_breg13:
443         case DW_OP_breg14:
444         case DW_OP_breg15:
445         case DW_OP_breg16:
446         case DW_OP_breg17:
447         case DW_OP_breg18:
448         case DW_OP_breg19:
449         case DW_OP_breg20:
450         case DW_OP_breg21:
451         case DW_OP_breg22:
452         case DW_OP_breg23:
453         case DW_OP_breg24:
454         case DW_OP_breg25:
455         case DW_OP_breg26:
456         case DW_OP_breg27:
457         case DW_OP_breg28:
458         case DW_OP_breg29:
459         case DW_OP_breg30:
460         case DW_OP_breg31:
461           op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp;
462           result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
463           break;
464         case DW_OP_bregx:
465           op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp;
466           op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp;
467           result = _Unwind_GetGR (context, reg) + offset;
468           break;
469
470         case DW_OP_dup:
471           if (stack_elt < 1)
472             abort ();
473           result = stack[stack_elt - 1];
474           break;
475
476         case DW_OP_drop:
477           if (--stack_elt < 0)
478             abort ();
479           goto no_push;
480
481         case DW_OP_pick:
482           offset = *op_ptr++;
483           if (offset >= stack_elt - 1)
484             abort ();
485           result = stack[stack_elt - 1 - offset];
486           break;
487
488         case DW_OP_over:
489           if (stack_elt < 2)
490             abort ();
491           result = stack[stack_elt - 2];
492           break;
493
494         case DW_OP_rot:
495           {
496             _Unwind_Word t1, t2, t3;
497
498             if (stack_elt < 3)
499               abort ();
500             t1 = stack[stack_elt - 1];
501             t2 = stack[stack_elt - 2];
502             t3 = stack[stack_elt - 3];
503             stack[stack_elt - 1] = t2;
504             stack[stack_elt - 2] = t3;
505             stack[stack_elt - 3] = t1;
506             goto no_push;
507           }
508
509         case DW_OP_deref:
510         case DW_OP_deref_size:
511         case DW_OP_abs:
512         case DW_OP_neg:
513         case DW_OP_not:
514         case DW_OP_plus_uconst:
515           /* Unary operations.  */
516           if (--stack_elt < 0)
517             abort ();
518           result = stack[stack_elt];
519
520           switch (op)
521             {
522             case DW_OP_deref:
523               {
524                 void *ptr = (void *)(_Unwind_Ptr) result;
525                 result = (_Unwind_Ptr) read_pointer (ptr);
526               }
527               break;
528
529             case DW_OP_deref_size:
530               {
531                 void *ptr = (void *)(_Unwind_Ptr) result;
532                 switch (*op_ptr++)
533                   {
534                   case 1:
535                     result = read_1u (ptr);
536                     break;
537                   case 2:
538                     result = read_2u (ptr);
539                     break;
540                   case 4:
541                     result = read_4u (ptr);
542                     break;
543                   case 8:
544                     result = read_8u (ptr);
545                     break;
546                   default:
547                     abort ();
548                   }
549               }
550               break;
551
552             case DW_OP_abs:
553               if ((_Unwind_Sword) result < 0)
554                 result = -result;
555               break;
556             case DW_OP_neg:
557               result = -result;
558               break;
559             case DW_OP_not:
560               result = ~result;
561               break;
562             case DW_OP_plus_uconst:
563               op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp;
564               result += reg;
565               break;
566             }
567           break;
568
569         case DW_OP_and:
570         case DW_OP_div:
571         case DW_OP_minus:
572         case DW_OP_mod:
573         case DW_OP_mul:
574         case DW_OP_or:
575         case DW_OP_plus:
576         case DW_OP_le:
577         case DW_OP_ge:
578         case DW_OP_eq:
579         case DW_OP_lt:
580         case DW_OP_gt:
581         case DW_OP_ne:
582           {
583             /* Binary operations.  */
584             _Unwind_Word first, second;
585           if ((stack_elt -= 2) < 0)
586             abort ();
587           second = stack[stack_elt];
588           first = stack[stack_elt + 1];
589
590           switch (op)
591             {
592             case DW_OP_and:
593               result = second & first;
594               break;
595             case DW_OP_div:
596               result = (_Unwind_Sword)second / (_Unwind_Sword)first;
597               break;
598             case DW_OP_minus:
599               result = second - first;
600               break;
601             case DW_OP_mod:
602               result = (_Unwind_Sword)second % (_Unwind_Sword)first;
603               break;
604             case DW_OP_mul:
605               result = second * first;
606               break;
607             case DW_OP_or:
608               result = second | first;
609               break;
610             case DW_OP_plus:
611               result = second + first;
612               break;
613             case DW_OP_shl:
614               result = second << first;
615               break;
616             case DW_OP_shr:
617               result = second >> first;
618               break;
619             case DW_OP_shra:
620               result = (_Unwind_Sword)second >> first;
621               break;
622             case DW_OP_xor:
623               result = second ^ first;
624               break;
625             case DW_OP_le:
626               result = (_Unwind_Sword)first <= (_Unwind_Sword)second;
627               break;
628             case DW_OP_ge:
629               result = (_Unwind_Sword)first >= (_Unwind_Sword)second;
630               break;
631             case DW_OP_eq:
632               result = (_Unwind_Sword)first == (_Unwind_Sword)second;
633               break;
634             case DW_OP_lt:
635               result = (_Unwind_Sword)first < (_Unwind_Sword)second;
636               break;
637             case DW_OP_gt:
638               result = (_Unwind_Sword)first > (_Unwind_Sword)second;
639               break;
640             case DW_OP_ne:
641               result = (_Unwind_Sword)first != (_Unwind_Sword)second;
642               break;
643             }
644           }
645           break;
646
647         case DW_OP_skip:
648           offset = read_2s (op_ptr);
649           op_ptr += 2;
650           op_ptr += offset;
651           goto no_push;
652
653         case DW_OP_bra:
654           if (--stack_elt < 0)
655             abort ();
656           offset = read_2s (op_ptr);
657           op_ptr += 2;
658           if (stack[stack_elt] != 0)
659             op_ptr += offset;
660           goto no_push;
661
662         case DW_OP_nop:
663           goto no_push;
664
665         default:
666           abort ();
667         }
668
669       /* Most things push a result value.  */
670       if ((size_t) stack_elt >= sizeof(stack)/sizeof(*stack))
671         abort ();
672       stack[++stack_elt] = result;
673     no_push:;
674     }
675
676   /* We were executing this program to get a value.  It should be
677      at top of stack.  */
678   if (--stack_elt < 0)
679     abort ();
680   return stack[stack_elt];
681 }
682
683
684 /* Decode DWARF 2 call frame information. Takes pointers the
685    instruction sequence to decode, current register information and
686    CIE info, and the PC range to evaluate.  */
687
688 static void
689 execute_cfa_program (const unsigned char *insn_ptr,
690                      const unsigned char *insn_end,
691                      struct _Unwind_Context *context,
692                      _Unwind_FrameState *fs)
693 {
694   struct frame_state_reg_info *unused_rs = NULL;
695
696   /* Don't allow remember/restore between CIE and FDE programs.  */
697   fs->regs.prev = NULL;
698
699   while (insn_ptr < insn_end && fs->pc < context->ra)
700     {
701       unsigned char insn = *insn_ptr++;
702       _Unwind_Word reg;
703       _Unwind_Sword offset;
704       _Unwind_Ptr ptrtmp;
705
706       if (insn & DW_CFA_advance_loc)
707         fs->pc += (insn & 0x3f) * fs->code_align;
708       else if (insn & DW_CFA_offset)
709         {
710           reg = insn & 0x3f;
711           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
712           offset = ptrtmp * fs->data_align;
713           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
714           fs->regs.reg[reg].loc.offset = offset;
715         }
716       else if (insn & DW_CFA_restore)
717         {
718           reg = insn & 0x3f;
719           fs->regs.reg[reg].how = REG_UNSAVED;
720         }
721       else switch (insn)
722         {
723         case DW_CFA_set_loc:
724           insn_ptr = read_encoded_value (context, fs->fde_encoding,
725                                          insn_ptr, (_Unwind_Ptr *) &fs->pc);
726           break;
727
728         case DW_CFA_advance_loc1:
729           fs->pc += read_1u (insn_ptr) * fs->code_align;
730           insn_ptr += 1;
731           break;
732         case DW_CFA_advance_loc2:
733           fs->pc += read_2u (insn_ptr) * fs->code_align;
734           insn_ptr += 2;
735           break;
736         case DW_CFA_advance_loc4:
737           fs->pc += read_4u (insn_ptr) * fs->code_align;
738           insn_ptr += 4;
739           break;
740
741         case DW_CFA_offset_extended:
742           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
743           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
744           offset = ptrtmp * fs->data_align;
745           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
746           fs->regs.reg[reg].loc.offset = offset;
747           break;
748
749         case DW_CFA_restore_extended:
750           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
751           fs->regs.reg[reg].how = REG_UNSAVED;
752           break;
753
754         case DW_CFA_undefined:
755         case DW_CFA_same_value:
756         case DW_CFA_nop:
757           break;
758
759         case DW_CFA_register:
760           {
761             _Unwind_Word reg2;
762             insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
763             insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg2 = ptrtmp;
764             fs->regs.reg[reg].how = REG_SAVED_REG;
765             fs->regs.reg[reg].loc.reg = reg2;
766           }
767           break;
768       
769         case DW_CFA_remember_state:
770           {
771             struct frame_state_reg_info *new_rs;
772             if (unused_rs)
773               {
774                 new_rs = unused_rs;
775                 unused_rs = unused_rs->prev;
776               }
777             else
778               new_rs = alloca (sizeof (struct frame_state_reg_info));
779
780             *new_rs = fs->regs;
781             fs->regs.prev = new_rs;
782           }
783           break;
784
785         case DW_CFA_restore_state:
786           {
787             struct frame_state_reg_info *old_rs = fs->regs.prev;
788             fs->regs = *old_rs;
789             old_rs->prev = unused_rs;
790             unused_rs = old_rs;
791           }
792           break;
793
794         case DW_CFA_def_cfa:
795           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
796           fs->cfa_reg = ptrtmp;
797           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
798           fs->cfa_offset = ptrtmp;
799           fs->cfa_how = CFA_REG_OFFSET;
800           break;
801
802         case DW_CFA_def_cfa_register:
803           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
804           fs->cfa_reg = ptrtmp;
805           fs->cfa_how = CFA_REG_OFFSET;
806           break;
807
808         case DW_CFA_def_cfa_offset:
809           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
810           fs->cfa_offset = ptrtmp;
811           /* cfa_how deliberately not set.  */
812           break;
813
814         case DW_CFA_def_cfa_expression:
815           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
816           fs->cfa_exp = insn_ptr;
817           fs->cfa_how = CFA_EXP;
818           insn_ptr += ptrtmp;
819           break;
820
821         case DW_CFA_expression:
822           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
823           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
824           fs->regs.reg[reg].how = REG_SAVED_EXP;
825           fs->regs.reg[reg].loc.exp = insn_ptr;
826           insn_ptr += ptrtmp;
827           break;
828
829           /* From the 2.1 draft.  */
830         case DW_CFA_offset_extended_sf:
831           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
832           insn_ptr = read_sleb128 (insn_ptr, &ptrtmp);
833           offset = (saddr)ptrtmp * fs->data_align;
834           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
835           fs->regs.reg[reg].loc.offset = offset;
836           break;
837           
838         case DW_CFA_def_cfa_sf:
839           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
840           fs->cfa_reg = ptrtmp;
841           insn_ptr = read_sleb128 (insn_ptr, &ptrtmp);
842           fs->cfa_offset = (saddr)ptrtmp;
843           fs->cfa_how = CFA_REG_OFFSET;
844           break;
845
846         case DW_CFA_def_cfa_offset_sf:
847           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
848           fs->cfa_offset = ptrtmp;
849           /* cfa_how deliberately not set.  */
850           break;
851
852         case DW_CFA_GNU_window_save:
853           /* ??? Hardcoded for SPARC register window configuration.  */
854           for (reg = 16; reg < 32; ++reg)
855             {
856               fs->regs.reg[reg].how = REG_SAVED_OFFSET;
857               fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
858             }
859           break;
860
861         case DW_CFA_GNU_args_size:
862           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
863           context->args_size = ptrtmp;
864           break;
865
866         case DW_CFA_GNU_negative_offset_extended:
867           /* Obsoleted by DW_CFA_offset_extended_sf, but used by
868              older PowerPC code.  */
869           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
870           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
871           offset = ptrtmp * fs->data_align;
872           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
873           fs->regs.reg[reg].loc.offset = -offset;
874           break;
875
876         default:
877           abort ();
878         }
879     }
880 }
881 \f
882 static _Unwind_Reason_Code
883 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
884 {
885   struct dwarf_fde *fde;
886   struct dwarf_cie *cie;
887   const unsigned char *aug, *insn, *end;
888
889   memset (fs, 0, sizeof (*fs));
890   context->args_size = 0;
891   context->lsda = 0;
892
893   fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
894   if (fde == NULL)
895     {
896       /* Couldn't find frame unwind info for this function.  Try a
897          target-specific fallback mechanism.  This will necessarily
898          not profide a personality routine or LSDA.  */
899 #ifdef MD_FALLBACK_FRAME_STATE_FOR
900       MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
901       return _URC_END_OF_STACK;
902     success:
903       return _URC_NO_REASON;
904 #else
905       return _URC_END_OF_STACK;
906 #endif
907     }
908
909   fs->pc = context->bases.func;
910
911   cie = get_cie (fde);
912   insn = extract_cie_info (cie, context, fs);
913   if (insn == NULL)
914     /* CIE contained unknown augmentation.  */
915     return _URC_FATAL_PHASE1_ERROR;
916
917   /* First decode all the insns in the CIE.  */
918   end = (unsigned char *) next_fde ((struct dwarf_fde *) cie);
919   execute_cfa_program (insn, end, context, fs);
920
921   /* Locate augmentation for the fde.  */
922   aug = (unsigned char *)fde + sizeof (*fde);
923   aug += 2 * size_of_encoded_value (fs->fde_encoding);
924   insn = NULL;
925   if (fs->saw_z)
926     {
927       _Unwind_Ptr i;
928       aug = read_uleb128 (aug, &i);
929       insn = aug + i;
930     }
931   if (fs->lsda_encoding != DW_EH_PE_omit)
932     aug = read_encoded_value (context, fs->lsda_encoding, aug,
933                               (_Unwind_Ptr *) &context->lsda);
934
935   /* Then the insns in the FDE up to our target PC.  */
936   if (insn == NULL)
937     insn = aug;
938   end = (unsigned char *) next_fde (fde);
939   execute_cfa_program (insn, end, context, fs);
940
941   return _URC_NO_REASON;
942 }
943 \f
944 typedef struct frame_state
945 {
946   void *cfa;
947   void *eh_ptr;
948   long cfa_offset;
949   long args_size;
950   long reg_or_offset[DWARF_FRAME_REGISTERS+1];
951   unsigned short cfa_reg;
952   unsigned short retaddr_column;
953   char saved[DWARF_FRAME_REGISTERS+1];
954 } frame_state;
955
956 struct frame_state * __frame_state_for (void *, struct frame_state *);
957
958 /* Called from pre-G++ 3.0 __throw to find the registers to restore for
959    a given PC_TARGET.  The caller should allocate a local variable of
960    `struct frame_state' and pass its address to STATE_IN.  */
961
962 struct frame_state *
963 __frame_state_for (void *pc_target, struct frame_state *state_in)
964 {
965   struct _Unwind_Context context;
966   _Unwind_FrameState fs;
967   int reg;
968
969   memset (&context, 0, sizeof (struct _Unwind_Context));
970   context.ra = pc_target + 1;
971
972   if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
973     return 0;
974
975   /* We have no way to pass a location expression for the CFA to our
976      caller.  It wouldn't understand it anyway.  */
977   if (fs.cfa_how == CFA_EXP)
978     return 0;
979
980   for (reg = 0; reg < DWARF_FRAME_REGISTERS + 1; reg++)
981     {
982       state_in->saved[reg] = fs.regs.reg[reg].how;
983       switch (state_in->saved[reg])
984         {
985         case REG_SAVED_REG:
986           state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
987           break;
988         case REG_SAVED_OFFSET:
989           state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
990           break;
991         default:
992           state_in->reg_or_offset[reg] = 0;
993           break;
994         }
995     }
996
997   state_in->cfa_offset = fs.cfa_offset;
998   state_in->cfa_reg = fs.cfa_reg;
999   state_in->retaddr_column = fs.retaddr_column;
1000   state_in->args_size = context.args_size;
1001   state_in->eh_ptr = fs.eh_ptr;
1002
1003   return state_in;
1004 }
1005 \f
1006 static void
1007 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1008 {
1009   struct _Unwind_Context orig_context = *context;
1010   void *cfa;
1011   long i;
1012
1013   /* Compute this frame's CFA.  */
1014   switch (fs->cfa_how)
1015     {
1016     case CFA_REG_OFFSET:
1017       /* Special handling here: Many machines do not use a frame pointer,
1018          and track the CFA only through offsets from the stack pointer from
1019          one frame to the next.  In this case, the stack pointer is never
1020          stored, so it has no saved address in the context.  What we do 
1021          have is the CFA from the previous stack frame.  */
1022       if (context->reg[fs->cfa_reg] == NULL)
1023         cfa = context->cfa;
1024       else
1025         cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->cfa_reg);
1026       cfa += fs->cfa_offset;
1027       break;
1028
1029     case CFA_EXP:
1030       /* ??? No way of knowing what register number is the stack pointer
1031          to do the same sort of handling as above.  Assume that if the
1032          CFA calculation is so complicated as to require a stack program
1033          that this will not be a problem.  */
1034       {
1035         const unsigned char *exp = fs->cfa_exp;
1036         _Unwind_Ptr len;
1037
1038         exp = read_uleb128 (exp, &len);
1039         cfa = (void *) (_Unwind_Ptr)
1040           execute_stack_op (exp, exp + len, context, 0);
1041         break;
1042       }
1043
1044     default:
1045       abort ();
1046     }
1047   context->cfa = cfa;
1048
1049   /* Compute the addresses of all registers saved in this frame.  */
1050   for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
1051     switch (fs->regs.reg[i].how)
1052       {
1053       case REG_UNSAVED:
1054         break;
1055       case REG_SAVED_OFFSET:
1056         context->reg[i] = cfa + fs->regs.reg[i].loc.offset;
1057         break;
1058       case REG_SAVED_REG:
1059         context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg];
1060         break;
1061       case REG_SAVED_EXP:
1062         {
1063           const unsigned char *exp = fs->regs.reg[i].loc.exp;
1064           _Unwind_Ptr len;
1065           _Unwind_Ptr val;
1066
1067           exp = read_uleb128 (exp, &len);
1068           val = execute_stack_op (exp, exp + len, &orig_context,
1069                                   (_Unwind_Ptr) cfa);
1070           context->reg[i] = (void *) val;
1071         }
1072         break;
1073       }
1074 }
1075
1076 static void
1077 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1078 {
1079   uw_update_context_1 (context, fs);
1080
1081   /* Compute the return address now, since the return address column
1082      can change from frame to frame.  */
1083   context->ra = __builtin_extract_return_addr
1084     ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column));
1085 }
1086 \f
1087 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
1088    level will be the return address and the CFA.  */
1089    
1090 #define uw_init_context(CONTEXT)                                        \
1091 do {                                                                    \
1092   /* Do any necessary initialization to access arbitrary stack frames.  \
1093      On the SPARC, this means flushing the register windows.  */        \
1094   __builtin_unwind_init ();                                             \
1095   uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),                   \
1096                      __builtin_return_address (0));                     \
1097 } while (0)
1098
1099 static void
1100 uw_init_context_1 (struct _Unwind_Context *context,
1101                    void *outer_cfa, void *outer_ra)
1102 {
1103   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
1104   _Unwind_FrameState fs;
1105
1106   memset (context, 0, sizeof (struct _Unwind_Context));
1107   context->ra = ra;
1108
1109   if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
1110     abort ();
1111
1112   /* Force the frame state to use the known cfa value.  */
1113   context->cfa = outer_cfa;
1114   fs.cfa_how = CFA_REG_OFFSET;
1115   fs.cfa_reg = 0;
1116   fs.cfa_offset = 0;
1117
1118   uw_update_context_1 (context, &fs);
1119
1120   /* If the return address column was saved in a register in the
1121      initialization context, then we can't see it in the given
1122      call frame data.  So have the initialization context tell us.  */
1123   context->ra = __builtin_extract_return_addr (outer_ra);
1124 }
1125
1126
1127 /* Install TARGET into CURRENT so that we can return to it.  This is a
1128    macro because __builtin_eh_return must be invoked in the context of
1129    our caller.  */
1130
1131 #define uw_install_context(CURRENT, TARGET)                             \
1132 do {                                                                    \
1133   long offset = uw_install_context_1 ((CURRENT), (TARGET));             \
1134   void *handler = __builtin_frob_return_addr ((TARGET)->ra);            \
1135   __builtin_eh_return (offset, handler);                                \
1136 } while (0)
1137
1138 static inline void
1139 init_dwarf_reg_size_table (void)
1140 {
1141   __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
1142 }
1143
1144 static long
1145 uw_install_context_1 (struct _Unwind_Context *current,
1146                       struct _Unwind_Context *target)
1147 {
1148   long i;
1149
1150 #if __GTHREADS
1151   {
1152     static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
1153     if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
1154         || dwarf_reg_size_table[0] == 0)
1155       init_dwarf_reg_size_table ();
1156   }
1157 #else
1158   if (dwarf_reg_size_table[0] == 0)
1159     init_dwarf_reg_size_table ();
1160 #endif
1161
1162   for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
1163     {
1164       void *c = current->reg[i];
1165       void *t = target->reg[i];
1166       if (t && c && t != c)
1167         memcpy (c, t, dwarf_reg_size_table[i]);
1168     }
1169
1170   /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
1171   if (STACK_GROWS_DOWNWARD)
1172     return target->cfa - current->cfa + target->args_size;
1173   else
1174     return current->cfa - target->cfa - target->args_size;
1175 }
1176
1177 static inline _Unwind_Ptr
1178 uw_identify_context (struct _Unwind_Context *context)
1179 {
1180   return _Unwind_GetIP (context);
1181 }
1182
1183
1184 #include "unwind.inc"
1185
1186 #endif /* !USING_SJLJ_EXCEPTIONS */