OSDN Git Service

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