OSDN Git Service

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