OSDN Git Service

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