OSDN Git Service

* Makefile.in, alias.c, basic-block.h, bb-reorder.c, bitmap.c,
[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 GCC.
5
6    GCC is free software; you can redistribute it and/or modify it
7    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    GCC is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GCC; see the file COPYING.  If not, write to the Free
18    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19    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             default:
568               abort ();
569             }
570           break;
571
572         case DW_OP_and:
573         case DW_OP_div:
574         case DW_OP_minus:
575         case DW_OP_mod:
576         case DW_OP_mul:
577         case DW_OP_or:
578         case DW_OP_plus:
579         case DW_OP_le:
580         case DW_OP_ge:
581         case DW_OP_eq:
582         case DW_OP_lt:
583         case DW_OP_gt:
584         case DW_OP_ne:
585           {
586             /* Binary operations.  */
587             _Unwind_Word first, second;
588           if ((stack_elt -= 2) < 0)
589             abort ();
590           second = stack[stack_elt];
591           first = stack[stack_elt + 1];
592
593           switch (op)
594             {
595             case DW_OP_and:
596               result = second & first;
597               break;
598             case DW_OP_div:
599               result = (_Unwind_Sword)second / (_Unwind_Sword)first;
600               break;
601             case DW_OP_minus:
602               result = second - first;
603               break;
604             case DW_OP_mod:
605               result = (_Unwind_Sword)second % (_Unwind_Sword)first;
606               break;
607             case DW_OP_mul:
608               result = second * first;
609               break;
610             case DW_OP_or:
611               result = second | first;
612               break;
613             case DW_OP_plus:
614               result = second + first;
615               break;
616             case DW_OP_shl:
617               result = second << first;
618               break;
619             case DW_OP_shr:
620               result = second >> first;
621               break;
622             case DW_OP_shra:
623               result = (_Unwind_Sword)second >> first;
624               break;
625             case DW_OP_xor:
626               result = second ^ first;
627               break;
628             case DW_OP_le:
629               result = (_Unwind_Sword)first <= (_Unwind_Sword)second;
630               break;
631             case DW_OP_ge:
632               result = (_Unwind_Sword)first >= (_Unwind_Sword)second;
633               break;
634             case DW_OP_eq:
635               result = (_Unwind_Sword)first == (_Unwind_Sword)second;
636               break;
637             case DW_OP_lt:
638               result = (_Unwind_Sword)first < (_Unwind_Sword)second;
639               break;
640             case DW_OP_gt:
641               result = (_Unwind_Sword)first > (_Unwind_Sword)second;
642               break;
643             case DW_OP_ne:
644               result = (_Unwind_Sword)first != (_Unwind_Sword)second;
645               break;
646
647             default:
648               abort ();
649             }
650           }
651           break;
652
653         case DW_OP_skip:
654           offset = read_2s (op_ptr);
655           op_ptr += 2;
656           op_ptr += offset;
657           goto no_push;
658
659         case DW_OP_bra:
660           if (--stack_elt < 0)
661             abort ();
662           offset = read_2s (op_ptr);
663           op_ptr += 2;
664           if (stack[stack_elt] != 0)
665             op_ptr += offset;
666           goto no_push;
667
668         case DW_OP_nop:
669           goto no_push;
670
671         default:
672           abort ();
673         }
674
675       /* Most things push a result value.  */
676       if ((size_t) stack_elt >= sizeof(stack)/sizeof(*stack))
677         abort ();
678       stack[++stack_elt] = result;
679     no_push:;
680     }
681
682   /* We were executing this program to get a value.  It should be
683      at top of stack.  */
684   if (--stack_elt < 0)
685     abort ();
686   return stack[stack_elt];
687 }
688
689
690 /* Decode DWARF 2 call frame information. Takes pointers the
691    instruction sequence to decode, current register information and
692    CIE info, and the PC range to evaluate.  */
693
694 static void
695 execute_cfa_program (const unsigned char *insn_ptr,
696                      const unsigned char *insn_end,
697                      struct _Unwind_Context *context,
698                      _Unwind_FrameState *fs)
699 {
700   struct frame_state_reg_info *unused_rs = NULL;
701
702   /* Don't allow remember/restore between CIE and FDE programs.  */
703   fs->regs.prev = NULL;
704
705   while (insn_ptr < insn_end && fs->pc < context->ra)
706     {
707       unsigned char insn = *insn_ptr++;
708       _Unwind_Word reg;
709       _Unwind_Sword offset;
710       _Unwind_Ptr ptrtmp;
711
712       if (insn & DW_CFA_advance_loc)
713         fs->pc += (insn & 0x3f) * fs->code_align;
714       else if (insn & DW_CFA_offset)
715         {
716           reg = insn & 0x3f;
717           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
718           offset = ptrtmp * fs->data_align;
719           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
720           fs->regs.reg[reg].loc.offset = offset;
721         }
722       else if (insn & DW_CFA_restore)
723         {
724           reg = insn & 0x3f;
725           fs->regs.reg[reg].how = REG_UNSAVED;
726         }
727       else switch (insn)
728         {
729         case DW_CFA_set_loc:
730           insn_ptr = read_encoded_value (context, fs->fde_encoding,
731                                          insn_ptr, (_Unwind_Ptr *) &fs->pc);
732           break;
733
734         case DW_CFA_advance_loc1:
735           fs->pc += read_1u (insn_ptr) * fs->code_align;
736           insn_ptr += 1;
737           break;
738         case DW_CFA_advance_loc2:
739           fs->pc += read_2u (insn_ptr) * fs->code_align;
740           insn_ptr += 2;
741           break;
742         case DW_CFA_advance_loc4:
743           fs->pc += read_4u (insn_ptr) * fs->code_align;
744           insn_ptr += 4;
745           break;
746
747         case DW_CFA_offset_extended:
748           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
749           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
750           offset = ptrtmp * fs->data_align;
751           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
752           fs->regs.reg[reg].loc.offset = offset;
753           break;
754
755         case DW_CFA_restore_extended:
756           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
757           fs->regs.reg[reg].how = REG_UNSAVED;
758           break;
759
760         case DW_CFA_undefined:
761         case DW_CFA_same_value:
762         case DW_CFA_nop:
763           break;
764
765         case DW_CFA_register:
766           {
767             _Unwind_Word reg2;
768             insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
769             insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg2 = ptrtmp;
770             fs->regs.reg[reg].how = REG_SAVED_REG;
771             fs->regs.reg[reg].loc.reg = reg2;
772           }
773           break;
774       
775         case DW_CFA_remember_state:
776           {
777             struct frame_state_reg_info *new_rs;
778             if (unused_rs)
779               {
780                 new_rs = unused_rs;
781                 unused_rs = unused_rs->prev;
782               }
783             else
784               new_rs = alloca (sizeof (struct frame_state_reg_info));
785
786             *new_rs = fs->regs;
787             fs->regs.prev = new_rs;
788           }
789           break;
790
791         case DW_CFA_restore_state:
792           {
793             struct frame_state_reg_info *old_rs = fs->regs.prev;
794             fs->regs = *old_rs;
795             old_rs->prev = unused_rs;
796             unused_rs = old_rs;
797           }
798           break;
799
800         case DW_CFA_def_cfa:
801           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
802           fs->cfa_reg = ptrtmp;
803           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
804           fs->cfa_offset = ptrtmp;
805           fs->cfa_how = CFA_REG_OFFSET;
806           break;
807
808         case DW_CFA_def_cfa_register:
809           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
810           fs->cfa_reg = ptrtmp;
811           fs->cfa_how = CFA_REG_OFFSET;
812           break;
813
814         case DW_CFA_def_cfa_offset:
815           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
816           fs->cfa_offset = ptrtmp;
817           /* cfa_how deliberately not set.  */
818           break;
819
820         case DW_CFA_def_cfa_expression:
821           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
822           fs->cfa_exp = insn_ptr;
823           fs->cfa_how = CFA_EXP;
824           insn_ptr += ptrtmp;
825           break;
826
827         case DW_CFA_expression:
828           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
829           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
830           fs->regs.reg[reg].how = REG_SAVED_EXP;
831           fs->regs.reg[reg].loc.exp = insn_ptr;
832           insn_ptr += ptrtmp;
833           break;
834
835           /* From the 2.1 draft.  */
836         case DW_CFA_offset_extended_sf:
837           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
838           insn_ptr = read_sleb128 (insn_ptr, &ptrtmp);
839           offset = (saddr)ptrtmp * fs->data_align;
840           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
841           fs->regs.reg[reg].loc.offset = offset;
842           break;
843           
844         case DW_CFA_def_cfa_sf:
845           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
846           fs->cfa_reg = ptrtmp;
847           insn_ptr = read_sleb128 (insn_ptr, &ptrtmp);
848           fs->cfa_offset = (saddr)ptrtmp;
849           fs->cfa_how = CFA_REG_OFFSET;
850           break;
851
852         case DW_CFA_def_cfa_offset_sf:
853           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
854           fs->cfa_offset = ptrtmp;
855           /* cfa_how deliberately not set.  */
856           break;
857
858         case DW_CFA_GNU_window_save:
859           /* ??? Hardcoded for SPARC register window configuration.  */
860           for (reg = 16; reg < 32; ++reg)
861             {
862               fs->regs.reg[reg].how = REG_SAVED_OFFSET;
863               fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
864             }
865           break;
866
867         case DW_CFA_GNU_args_size:
868           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
869           context->args_size = ptrtmp;
870           break;
871
872         case DW_CFA_GNU_negative_offset_extended:
873           /* Obsoleted by DW_CFA_offset_extended_sf, but used by
874              older PowerPC code.  */
875           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp;
876           insn_ptr = read_uleb128 (insn_ptr, &ptrtmp);
877           offset = ptrtmp * fs->data_align;
878           fs->regs.reg[reg].how = REG_SAVED_OFFSET;
879           fs->regs.reg[reg].loc.offset = -offset;
880           break;
881
882         default:
883           abort ();
884         }
885     }
886 }
887 \f
888 static _Unwind_Reason_Code
889 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
890 {
891   struct dwarf_fde *fde;
892   struct dwarf_cie *cie;
893   const unsigned char *aug, *insn, *end;
894
895   memset (fs, 0, sizeof (*fs));
896   context->args_size = 0;
897   context->lsda = 0;
898
899   fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
900   if (fde == NULL)
901     {
902       /* Couldn't find frame unwind info for this function.  Try a
903          target-specific fallback mechanism.  This will necessarily
904          not profide a personality routine or LSDA.  */
905 #ifdef MD_FALLBACK_FRAME_STATE_FOR
906       MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
907       return _URC_END_OF_STACK;
908     success:
909       return _URC_NO_REASON;
910 #else
911       return _URC_END_OF_STACK;
912 #endif
913     }
914
915   fs->pc = context->bases.func;
916
917   cie = get_cie (fde);
918   insn = extract_cie_info (cie, context, fs);
919   if (insn == NULL)
920     /* CIE contained unknown augmentation.  */
921     return _URC_FATAL_PHASE1_ERROR;
922
923   /* First decode all the insns in the CIE.  */
924   end = (unsigned char *) next_fde ((struct dwarf_fde *) cie);
925   execute_cfa_program (insn, end, context, fs);
926
927   /* Locate augmentation for the fde.  */
928   aug = (unsigned char *)fde + sizeof (*fde);
929   aug += 2 * size_of_encoded_value (fs->fde_encoding);
930   insn = NULL;
931   if (fs->saw_z)
932     {
933       _Unwind_Ptr i;
934       aug = read_uleb128 (aug, &i);
935       insn = aug + i;
936     }
937   if (fs->lsda_encoding != DW_EH_PE_omit)
938     aug = read_encoded_value (context, fs->lsda_encoding, aug,
939                               (_Unwind_Ptr *) &context->lsda);
940
941   /* Then the insns in the FDE up to our target PC.  */
942   if (insn == NULL)
943     insn = aug;
944   end = (unsigned char *) next_fde (fde);
945   execute_cfa_program (insn, end, context, fs);
946
947   return _URC_NO_REASON;
948 }
949 \f
950 typedef struct frame_state
951 {
952   void *cfa;
953   void *eh_ptr;
954   long cfa_offset;
955   long args_size;
956   long reg_or_offset[DWARF_FRAME_REGISTERS+1];
957   unsigned short cfa_reg;
958   unsigned short retaddr_column;
959   char saved[DWARF_FRAME_REGISTERS+1];
960 } frame_state;
961
962 struct frame_state * __frame_state_for (void *, struct frame_state *);
963
964 /* Called from pre-G++ 3.0 __throw to find the registers to restore for
965    a given PC_TARGET.  The caller should allocate a local variable of
966    `struct frame_state' and pass its address to STATE_IN.  */
967
968 struct frame_state *
969 __frame_state_for (void *pc_target, struct frame_state *state_in)
970 {
971   struct _Unwind_Context context;
972   _Unwind_FrameState fs;
973   int reg;
974
975   memset (&context, 0, sizeof (struct _Unwind_Context));
976   context.ra = pc_target + 1;
977
978   if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
979     return 0;
980
981   /* We have no way to pass a location expression for the CFA to our
982      caller.  It wouldn't understand it anyway.  */
983   if (fs.cfa_how == CFA_EXP)
984     return 0;
985
986   for (reg = 0; reg < DWARF_FRAME_REGISTERS + 1; reg++)
987     {
988       state_in->saved[reg] = fs.regs.reg[reg].how;
989       switch (state_in->saved[reg])
990         {
991         case REG_SAVED_REG:
992           state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
993           break;
994         case REG_SAVED_OFFSET:
995           state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
996           break;
997         default:
998           state_in->reg_or_offset[reg] = 0;
999           break;
1000         }
1001     }
1002
1003   state_in->cfa_offset = fs.cfa_offset;
1004   state_in->cfa_reg = fs.cfa_reg;
1005   state_in->retaddr_column = fs.retaddr_column;
1006   state_in->args_size = context.args_size;
1007   state_in->eh_ptr = fs.eh_ptr;
1008
1009   return state_in;
1010 }
1011 \f
1012 static void
1013 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1014 {
1015   struct _Unwind_Context orig_context = *context;
1016   void *cfa;
1017   long i;
1018
1019   /* Compute this frame's CFA.  */
1020   switch (fs->cfa_how)
1021     {
1022     case CFA_REG_OFFSET:
1023       /* Special handling here: Many machines do not use a frame pointer,
1024          and track the CFA only through offsets from the stack pointer from
1025          one frame to the next.  In this case, the stack pointer is never
1026          stored, so it has no saved address in the context.  What we do 
1027          have is the CFA from the previous stack frame.  */
1028       if (context->reg[fs->cfa_reg] == NULL)
1029         cfa = context->cfa;
1030       else
1031         cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->cfa_reg);
1032       cfa += fs->cfa_offset;
1033       break;
1034
1035     case CFA_EXP:
1036       /* ??? No way of knowing what register number is the stack pointer
1037          to do the same sort of handling as above.  Assume that if the
1038          CFA calculation is so complicated as to require a stack program
1039          that this will not be a problem.  */
1040       {
1041         const unsigned char *exp = fs->cfa_exp;
1042         _Unwind_Ptr len;
1043
1044         exp = read_uleb128 (exp, &len);
1045         cfa = (void *) (_Unwind_Ptr)
1046           execute_stack_op (exp, exp + len, context, 0);
1047         break;
1048       }
1049
1050     default:
1051       abort ();
1052     }
1053   context->cfa = cfa;
1054
1055   /* Compute the addresses of all registers saved in this frame.  */
1056   for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
1057     switch (fs->regs.reg[i].how)
1058       {
1059       case REG_UNSAVED:
1060         break;
1061       case REG_SAVED_OFFSET:
1062         context->reg[i] = cfa + fs->regs.reg[i].loc.offset;
1063         break;
1064       case REG_SAVED_REG:
1065         context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg];
1066         break;
1067       case REG_SAVED_EXP:
1068         {
1069           const unsigned char *exp = fs->regs.reg[i].loc.exp;
1070           _Unwind_Ptr len;
1071           _Unwind_Ptr val;
1072
1073           exp = read_uleb128 (exp, &len);
1074           val = execute_stack_op (exp, exp + len, &orig_context,
1075                                   (_Unwind_Ptr) cfa);
1076           context->reg[i] = (void *) val;
1077         }
1078         break;
1079       }
1080 }
1081
1082 static void
1083 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1084 {
1085   uw_update_context_1 (context, fs);
1086
1087   /* Compute the return address now, since the return address column
1088      can change from frame to frame.  */
1089   context->ra = __builtin_extract_return_addr
1090     ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column));
1091 }
1092 \f
1093 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
1094    level will be the return address and the CFA.  */
1095    
1096 #define uw_init_context(CONTEXT)                                        \
1097 do {                                                                    \
1098   /* Do any necessary initialization to access arbitrary stack frames.  \
1099      On the SPARC, this means flushing the register windows.  */        \
1100   __builtin_unwind_init ();                                             \
1101   uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),                   \
1102                      __builtin_return_address (0));                     \
1103 } while (0)
1104
1105 static void
1106 uw_init_context_1 (struct _Unwind_Context *context,
1107                    void *outer_cfa, void *outer_ra)
1108 {
1109   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
1110   _Unwind_FrameState fs;
1111
1112   memset (context, 0, sizeof (struct _Unwind_Context));
1113   context->ra = ra;
1114
1115   if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
1116     abort ();
1117
1118   /* Force the frame state to use the known cfa value.  */
1119   context->cfa = outer_cfa;
1120   fs.cfa_how = CFA_REG_OFFSET;
1121   fs.cfa_reg = 0;
1122   fs.cfa_offset = 0;
1123
1124   uw_update_context_1 (context, &fs);
1125
1126   /* If the return address column was saved in a register in the
1127      initialization context, then we can't see it in the given
1128      call frame data.  So have the initialization context tell us.  */
1129   context->ra = __builtin_extract_return_addr (outer_ra);
1130 }
1131
1132
1133 /* Install TARGET into CURRENT so that we can return to it.  This is a
1134    macro because __builtin_eh_return must be invoked in the context of
1135    our caller.  */
1136
1137 #define uw_install_context(CURRENT, TARGET)                             \
1138 do {                                                                    \
1139   long offset = uw_install_context_1 ((CURRENT), (TARGET));             \
1140   void *handler = __builtin_frob_return_addr ((TARGET)->ra);            \
1141   __builtin_eh_return (offset, handler);                                \
1142 } while (0)
1143
1144 static inline void
1145 init_dwarf_reg_size_table (void)
1146 {
1147   __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
1148 }
1149
1150 static long
1151 uw_install_context_1 (struct _Unwind_Context *current,
1152                       struct _Unwind_Context *target)
1153 {
1154   long i;
1155
1156 #if __GTHREADS
1157   {
1158     static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
1159     if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
1160         || dwarf_reg_size_table[0] == 0)
1161       init_dwarf_reg_size_table ();
1162   }
1163 #else
1164   if (dwarf_reg_size_table[0] == 0)
1165     init_dwarf_reg_size_table ();
1166 #endif
1167
1168   for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
1169     {
1170       void *c = current->reg[i];
1171       void *t = target->reg[i];
1172       if (t && c && t != c)
1173         memcpy (c, t, dwarf_reg_size_table[i]);
1174     }
1175
1176   /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
1177   if (STACK_GROWS_DOWNWARD)
1178     return target->cfa - current->cfa + target->args_size;
1179   else
1180     return current->cfa - target->cfa - target->args_size;
1181 }
1182
1183 static inline _Unwind_Ptr
1184 uw_identify_context (struct _Unwind_Context *context)
1185 {
1186   return _Unwind_GetIP (context);
1187 }
1188
1189
1190 #include "unwind.inc"
1191
1192 #endif /* !USING_SJLJ_EXCEPTIONS */