OSDN Git Service

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