OSDN Git Service

b40b16fda552b84c96ec7b0c843f4f1a4e17cea9
[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, 2003, 2004, 2005, 2006
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    In addition to the permissions in the GNU General Public License, the
13    Free Software Foundation gives you unlimited permission to link the
14    compiled version of this file into combinations with other programs,
15    and to distribute those combinations without any restriction coming
16    from the use of this file.  (The General Public License restrictions
17    do apply in other respects; for example, they cover modification of
18    the file, and distribution when not linked into a combined
19    executable.)
20
21    GCC is distributed in the hope that it will be useful, but WITHOUT
22    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
24    License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with GCC; see the file COPYING.  If not, write to the Free
28    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29    02110-1301, USA.  */
30
31 #include "tconfig.h"
32 #include "tsystem.h"
33 #include "coretypes.h"
34 #include "tm.h"
35 #include "dwarf2.h"
36 #include "unwind.h"
37 #ifdef __USING_SJLJ_EXCEPTIONS__
38 # define NO_SIZE_OF_ENCODED_VALUE
39 #endif
40 #include "unwind-pe.h"
41 #include "unwind-dw2-fde.h"
42 #include "gthr.h"
43 #include "unwind-dw2.h"
44
45 #ifndef __USING_SJLJ_EXCEPTIONS__
46
47 #ifndef STACK_GROWS_DOWNWARD
48 #define STACK_GROWS_DOWNWARD 0
49 #else
50 #undef STACK_GROWS_DOWNWARD
51 #define STACK_GROWS_DOWNWARD 1
52 #endif
53
54 /* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
55 #ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
56 #define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
57 #endif
58
59 #ifndef DWARF_REG_TO_UNWIND_COLUMN
60 #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
61 #endif
62
63 /* This is the register and unwind state for a particular frame.  This
64    provides the information necessary to unwind up past a frame and return
65    to its caller.  */
66 struct _Unwind_Context
67 {
68   void *reg[DWARF_FRAME_REGISTERS+1];
69   void *cfa;
70   void *ra;
71   void *lsda;
72   struct dwarf_eh_bases bases;
73   /* Signal frame context.  */
74 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
75   /* Context which has version/args_size/by_value fields.  */
76 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
77   _Unwind_Word flags;
78   /* 0 for now, can be increased when further fields are added to
79      struct _Unwind_Context.  */
80   _Unwind_Word version;
81   _Unwind_Word args_size;
82   char by_value[DWARF_FRAME_REGISTERS+1];
83 };
84
85 /* Byte size of every register managed by these routines.  */
86 static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
87
88 \f
89 /* Read unaligned data from the instruction buffer.  */
90
91 union unaligned
92 {
93   void *p;
94   unsigned u2 __attribute__ ((mode (HI)));
95   unsigned u4 __attribute__ ((mode (SI)));
96   unsigned u8 __attribute__ ((mode (DI)));
97   signed s2 __attribute__ ((mode (HI)));
98   signed s4 __attribute__ ((mode (SI)));
99   signed s8 __attribute__ ((mode (DI)));
100 } __attribute__ ((packed));
101
102 static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
103 static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
104                                                _Unwind_FrameState *);
105
106 static inline void *
107 read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
108
109 static inline int
110 read_1u (const void *p) { return *(const unsigned char *) p; }
111
112 static inline int
113 read_1s (const void *p) { return *(const signed char *) p; }
114
115 static inline int
116 read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
117
118 static inline int
119 read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
120
121 static inline unsigned int
122 read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
123
124 static inline int
125 read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
126
127 static inline unsigned long
128 read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
129
130 static inline unsigned long
131 read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
132 \f
133 static inline _Unwind_Word
134 _Unwind_IsSignalFrame (struct _Unwind_Context *context)
135 {
136   return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
137 }
138
139 static inline void
140 _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
141 {
142   if (val)
143     context->flags |= SIGNAL_FRAME_BIT;
144   else
145     context->flags &= ~SIGNAL_FRAME_BIT;
146 }
147
148 static inline _Unwind_Word
149 _Unwind_IsExtendedContext (struct _Unwind_Context *context)
150 {
151   return context->flags & EXTENDED_CONTEXT_BIT;
152 }
153 \f
154 /* Get the value of register INDEX as saved in CONTEXT.  */
155
156 inline _Unwind_Word
157 _Unwind_GetGR (struct _Unwind_Context *context, int index)
158 {
159   int size;
160   void *ptr;
161
162 #ifdef DWARF_ZERO_REG
163   if (index == DWARF_ZERO_REG)
164     return 0;
165 #endif
166
167   index = DWARF_REG_TO_UNWIND_COLUMN (index);
168   gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
169   size = dwarf_reg_size_table[index];
170   ptr = context->reg[index];
171
172   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
173     return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
174
175   /* This will segfault if the register hasn't been saved.  */
176   if (size == sizeof(_Unwind_Ptr))
177     return * (_Unwind_Ptr *) ptr;
178   else
179     {
180       gcc_assert (size == sizeof(_Unwind_Word));
181       return * (_Unwind_Word *) ptr;
182     }
183 }
184
185 static inline void *
186 _Unwind_GetPtr (struct _Unwind_Context *context, int index)
187 {
188   return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
189 }
190
191 /* Get the value of the CFA as saved in CONTEXT.  */
192
193 _Unwind_Word
194 _Unwind_GetCFA (struct _Unwind_Context *context)
195 {
196   return (_Unwind_Ptr) context->cfa;
197 }
198
199 /* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
200
201 inline void
202 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
203 {
204   int size;
205   void *ptr;
206
207   index = DWARF_REG_TO_UNWIND_COLUMN (index);
208   gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
209   size = dwarf_reg_size_table[index];
210
211   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
212     {
213       context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
214       return;
215     }
216
217   ptr = context->reg[index];
218
219   if (size == sizeof(_Unwind_Ptr))
220     * (_Unwind_Ptr *) ptr = val;
221   else
222     {
223       gcc_assert (size == sizeof(_Unwind_Word));
224       * (_Unwind_Word *) ptr = val;
225     }
226 }
227
228 /* Get the pointer to a register INDEX as saved in CONTEXT.  */
229
230 static inline void *
231 _Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
232 {
233   index = DWARF_REG_TO_UNWIND_COLUMN (index);
234   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
235     return &context->reg[index];
236   return context->reg[index];
237 }
238
239 /* Set the pointer to a register INDEX as saved in CONTEXT.  */
240
241 static inline void
242 _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
243 {
244   index = DWARF_REG_TO_UNWIND_COLUMN (index);
245   if (_Unwind_IsExtendedContext (context))
246     context->by_value[index] = 0;
247   context->reg[index] = p;
248 }
249
250 /* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
251
252 static inline void
253 _Unwind_SetGRValue (struct _Unwind_Context *context, int index,
254                     _Unwind_Word val)
255 {
256   index = DWARF_REG_TO_UNWIND_COLUMN (index);
257   gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
258   gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
259
260   context->by_value[index] = 1;
261   context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
262 }
263
264 /* Return nonzero if register INDEX is stored by value rather than
265    by reference.  */
266
267 static inline int
268 _Unwind_GRByValue (struct _Unwind_Context *context, int index)
269 {
270   index = DWARF_REG_TO_UNWIND_COLUMN (index);
271   return context->by_value[index];
272 }
273
274 /* Retrieve the return address for CONTEXT.  */
275
276 inline _Unwind_Ptr
277 _Unwind_GetIP (struct _Unwind_Context *context)
278 {
279   return (_Unwind_Ptr) context->ra;
280 }
281
282 /* Retrieve the return address and flag whether that IP is before
283    or after first not yet fully executed instruction.  */
284
285 inline _Unwind_Ptr
286 _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
287 {
288   *ip_before_insn = _Unwind_IsSignalFrame (context);
289   return (_Unwind_Ptr) context->ra;
290 }
291
292 /* Overwrite the return address for CONTEXT with VAL.  */
293
294 inline void
295 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
296 {
297   context->ra = (void *) val;
298 }
299
300 void *
301 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
302 {
303   return context->lsda;
304 }
305
306 _Unwind_Ptr
307 _Unwind_GetRegionStart (struct _Unwind_Context *context)
308 {
309   return (_Unwind_Ptr) context->bases.func;
310 }
311
312 void *
313 _Unwind_FindEnclosingFunction (void *pc)
314 {
315   struct dwarf_eh_bases bases;
316   const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
317   if (fde)
318     return bases.func;
319   else
320     return NULL;
321 }
322
323 #ifndef __ia64__
324 _Unwind_Ptr
325 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
326 {
327   return (_Unwind_Ptr) context->bases.dbase;
328 }
329
330 _Unwind_Ptr
331 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
332 {
333   return (_Unwind_Ptr) context->bases.tbase;
334 }
335 #endif
336
337 #ifdef MD_UNWIND_SUPPORT
338 #include MD_UNWIND_SUPPORT
339 #endif
340 \f
341 /* Extract any interesting information from the CIE for the translation
342    unit F belongs to.  Return a pointer to the byte after the augmentation,
343    or NULL if we encountered an undecipherable augmentation.  */
344
345 static const unsigned char *
346 extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
347                   _Unwind_FrameState *fs)
348 {
349   const unsigned char *aug = cie->augmentation;
350   const unsigned char *p = aug + strlen ((const char *)aug) + 1;
351   const unsigned char *ret = NULL;
352   _uleb128_t utmp;
353   _sleb128_t stmp;
354
355   /* g++ v2 "eh" has pointer immediately following augmentation string,
356      so it must be handled first.  */
357   if (aug[0] == 'e' && aug[1] == 'h')
358     {
359       fs->eh_ptr = read_pointer (p);
360       p += sizeof (void *);
361       aug += 2;
362     }
363
364   /* Immediately following the augmentation are the code and
365      data alignment and return address column.  */
366   p = read_uleb128 (p, &utmp);
367   fs->code_align = (_Unwind_Word)utmp;
368   p = read_sleb128 (p, &stmp);
369   fs->data_align = (_Unwind_Sword)stmp;
370   if (cie->version == 1)
371     fs->retaddr_column = *p++;
372   else
373     {
374       p = read_uleb128 (p, &utmp);
375       fs->retaddr_column = (_Unwind_Word)utmp;
376     }
377   fs->lsda_encoding = DW_EH_PE_omit;
378
379   /* If the augmentation starts with 'z', then a uleb128 immediately
380      follows containing the length of the augmentation field following
381      the size.  */
382   if (*aug == 'z')
383     {
384       p = read_uleb128 (p, &utmp);
385       ret = p + utmp;
386
387       fs->saw_z = 1;
388       ++aug;
389     }
390
391   /* Iterate over recognized augmentation subsequences.  */
392   while (*aug != '\0')
393     {
394       /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
395       if (aug[0] == 'L')
396         {
397           fs->lsda_encoding = *p++;
398           aug += 1;
399         }
400
401       /* "R" indicates a byte indicating how FDE addresses are encoded.  */
402       else if (aug[0] == 'R')
403         {
404           fs->fde_encoding = *p++;
405           aug += 1;
406         }
407
408       /* "P" indicates a personality routine in the CIE augmentation.  */
409       else if (aug[0] == 'P')
410         {
411           _Unwind_Ptr personality;
412           
413           p = read_encoded_value (context, *p, p + 1, &personality);
414           fs->personality = (_Unwind_Personality_Fn) personality;
415           aug += 1;
416         }
417
418       /* "S" indicates a signal frame.  */
419       else if (aug[0] == 'S')
420         {
421           fs->signal_frame = 1;
422           aug += 1;
423         }
424
425       /* Otherwise we have an unknown augmentation string.
426          Bail unless we saw a 'z' prefix.  */
427       else
428         return ret;
429     }
430
431   return ret ? ret : p;
432 }
433
434
435 /* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
436    onto the stack to start.  */
437
438 static _Unwind_Word
439 execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
440                   struct _Unwind_Context *context, _Unwind_Word initial)
441 {
442   _Unwind_Word stack[64];       /* ??? Assume this is enough.  */
443   int stack_elt;
444
445   stack[0] = initial;
446   stack_elt = 1;
447
448   while (op_ptr < op_end)
449     {
450       enum dwarf_location_atom op = *op_ptr++;
451       _Unwind_Word result;
452       _uleb128_t reg, utmp;
453       _sleb128_t offset, stmp;
454
455       switch (op)
456         {
457         case DW_OP_lit0:
458         case DW_OP_lit1:
459         case DW_OP_lit2:
460         case DW_OP_lit3:
461         case DW_OP_lit4:
462         case DW_OP_lit5:
463         case DW_OP_lit6:
464         case DW_OP_lit7:
465         case DW_OP_lit8:
466         case DW_OP_lit9:
467         case DW_OP_lit10:
468         case DW_OP_lit11:
469         case DW_OP_lit12:
470         case DW_OP_lit13:
471         case DW_OP_lit14:
472         case DW_OP_lit15:
473         case DW_OP_lit16:
474         case DW_OP_lit17:
475         case DW_OP_lit18:
476         case DW_OP_lit19:
477         case DW_OP_lit20:
478         case DW_OP_lit21:
479         case DW_OP_lit22:
480         case DW_OP_lit23:
481         case DW_OP_lit24:
482         case DW_OP_lit25:
483         case DW_OP_lit26:
484         case DW_OP_lit27:
485         case DW_OP_lit28:
486         case DW_OP_lit29:
487         case DW_OP_lit30:
488         case DW_OP_lit31:
489           result = op - DW_OP_lit0;
490           break;
491
492         case DW_OP_addr:
493           result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
494           op_ptr += sizeof (void *);
495           break;
496
497         case DW_OP_const1u:
498           result = read_1u (op_ptr);
499           op_ptr += 1;
500           break;
501         case DW_OP_const1s:
502           result = read_1s (op_ptr);
503           op_ptr += 1;
504           break;
505         case DW_OP_const2u:
506           result = read_2u (op_ptr);
507           op_ptr += 2;
508           break;
509         case DW_OP_const2s:
510           result = read_2s (op_ptr);
511           op_ptr += 2;
512           break;
513         case DW_OP_const4u:
514           result = read_4u (op_ptr);
515           op_ptr += 4;
516           break;
517         case DW_OP_const4s:
518           result = read_4s (op_ptr);
519           op_ptr += 4;
520           break;
521         case DW_OP_const8u:
522           result = read_8u (op_ptr);
523           op_ptr += 8;
524           break;
525         case DW_OP_const8s:
526           result = read_8s (op_ptr);
527           op_ptr += 8;
528           break;
529         case DW_OP_constu:
530           op_ptr = read_uleb128 (op_ptr, &utmp);
531           result = (_Unwind_Word)utmp;
532           break;
533         case DW_OP_consts:
534           op_ptr = read_sleb128 (op_ptr, &stmp);
535           result = (_Unwind_Sword)stmp;
536           break;
537
538         case DW_OP_reg0:
539         case DW_OP_reg1:
540         case DW_OP_reg2:
541         case DW_OP_reg3:
542         case DW_OP_reg4:
543         case DW_OP_reg5:
544         case DW_OP_reg6:
545         case DW_OP_reg7:
546         case DW_OP_reg8:
547         case DW_OP_reg9:
548         case DW_OP_reg10:
549         case DW_OP_reg11:
550         case DW_OP_reg12:
551         case DW_OP_reg13:
552         case DW_OP_reg14:
553         case DW_OP_reg15:
554         case DW_OP_reg16:
555         case DW_OP_reg17:
556         case DW_OP_reg18:
557         case DW_OP_reg19:
558         case DW_OP_reg20:
559         case DW_OP_reg21:
560         case DW_OP_reg22:
561         case DW_OP_reg23:
562         case DW_OP_reg24:
563         case DW_OP_reg25:
564         case DW_OP_reg26:
565         case DW_OP_reg27:
566         case DW_OP_reg28:
567         case DW_OP_reg29:
568         case DW_OP_reg30:
569         case DW_OP_reg31:
570           result = _Unwind_GetGR (context, op - DW_OP_reg0);
571           break;
572         case DW_OP_regx:
573           op_ptr = read_uleb128 (op_ptr, &reg);
574           result = _Unwind_GetGR (context, reg);
575           break;
576
577         case DW_OP_breg0:
578         case DW_OP_breg1:
579         case DW_OP_breg2:
580         case DW_OP_breg3:
581         case DW_OP_breg4:
582         case DW_OP_breg5:
583         case DW_OP_breg6:
584         case DW_OP_breg7:
585         case DW_OP_breg8:
586         case DW_OP_breg9:
587         case DW_OP_breg10:
588         case DW_OP_breg11:
589         case DW_OP_breg12:
590         case DW_OP_breg13:
591         case DW_OP_breg14:
592         case DW_OP_breg15:
593         case DW_OP_breg16:
594         case DW_OP_breg17:
595         case DW_OP_breg18:
596         case DW_OP_breg19:
597         case DW_OP_breg20:
598         case DW_OP_breg21:
599         case DW_OP_breg22:
600         case DW_OP_breg23:
601         case DW_OP_breg24:
602         case DW_OP_breg25:
603         case DW_OP_breg26:
604         case DW_OP_breg27:
605         case DW_OP_breg28:
606         case DW_OP_breg29:
607         case DW_OP_breg30:
608         case DW_OP_breg31:
609           op_ptr = read_sleb128 (op_ptr, &offset);
610           result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
611           break;
612         case DW_OP_bregx:
613           op_ptr = read_uleb128 (op_ptr, &reg);
614           op_ptr = read_sleb128 (op_ptr, &offset);
615           result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
616           break;
617
618         case DW_OP_dup:
619           gcc_assert (stack_elt);
620           result = stack[stack_elt - 1];
621           break;
622
623         case DW_OP_drop:
624           gcc_assert (stack_elt);
625           stack_elt -= 1;
626           goto no_push;
627
628         case DW_OP_pick:
629           offset = *op_ptr++;
630           gcc_assert (offset < stack_elt - 1);
631           result = stack[stack_elt - 1 - offset];
632           break;
633
634         case DW_OP_over:
635           gcc_assert (stack_elt >= 2);
636           result = stack[stack_elt - 2];
637           break;
638
639         case DW_OP_rot:
640           {
641             _Unwind_Word t1, t2, t3;
642
643             gcc_assert (stack_elt >= 3);
644             t1 = stack[stack_elt - 1];
645             t2 = stack[stack_elt - 2];
646             t3 = stack[stack_elt - 3];
647             stack[stack_elt - 1] = t2;
648             stack[stack_elt - 2] = t3;
649             stack[stack_elt - 3] = t1;
650             goto no_push;
651           }
652
653         case DW_OP_deref:
654         case DW_OP_deref_size:
655         case DW_OP_abs:
656         case DW_OP_neg:
657         case DW_OP_not:
658         case DW_OP_plus_uconst:
659           /* Unary operations.  */
660           gcc_assert (stack_elt);
661           stack_elt -= 1;
662           
663           result = stack[stack_elt];
664
665           switch (op)
666             {
667             case DW_OP_deref:
668               {
669                 void *ptr = (void *) (_Unwind_Ptr) result;
670                 result = (_Unwind_Ptr) read_pointer (ptr);
671               }
672               break;
673
674             case DW_OP_deref_size:
675               {
676                 void *ptr = (void *) (_Unwind_Ptr) result;
677                 switch (*op_ptr++)
678                   {
679                   case 1:
680                     result = read_1u (ptr);
681                     break;
682                   case 2:
683                     result = read_2u (ptr);
684                     break;
685                   case 4:
686                     result = read_4u (ptr);
687                     break;
688                   case 8:
689                     result = read_8u (ptr);
690                     break;
691                   default:
692                     gcc_unreachable ();
693                   }
694               }
695               break;
696
697             case DW_OP_abs:
698               if ((_Unwind_Sword) result < 0)
699                 result = -result;
700               break;
701             case DW_OP_neg:
702               result = -result;
703               break;
704             case DW_OP_not:
705               result = ~result;
706               break;
707             case DW_OP_plus_uconst:
708               op_ptr = read_uleb128 (op_ptr, &utmp);
709               result += (_Unwind_Word)utmp;
710               break;
711
712             default:
713               gcc_unreachable ();
714             }
715           break;
716
717         case DW_OP_and:
718         case DW_OP_div:
719         case DW_OP_minus:
720         case DW_OP_mod:
721         case DW_OP_mul:
722         case DW_OP_or:
723         case DW_OP_plus:
724         case DW_OP_shl:
725         case DW_OP_shr:
726         case DW_OP_shra:
727         case DW_OP_xor:
728         case DW_OP_le:
729         case DW_OP_ge:
730         case DW_OP_eq:
731         case DW_OP_lt:
732         case DW_OP_gt:
733         case DW_OP_ne:
734           {
735             /* Binary operations.  */
736             _Unwind_Word first, second;
737             gcc_assert (stack_elt >= 2);
738             stack_elt -= 2;
739             
740             second = stack[stack_elt];
741             first = stack[stack_elt + 1];
742
743             switch (op)
744               {
745               case DW_OP_and:
746                 result = second & first;
747                 break;
748               case DW_OP_div:
749                 result = (_Unwind_Sword) second / (_Unwind_Sword) first;
750                 break;
751               case DW_OP_minus:
752                 result = second - first;
753                 break;
754               case DW_OP_mod:
755                 result = (_Unwind_Sword) second % (_Unwind_Sword) first;
756                 break;
757               case DW_OP_mul:
758                 result = second * first;
759                 break;
760               case DW_OP_or:
761                 result = second | first;
762                 break;
763               case DW_OP_plus:
764                 result = second + first;
765                 break;
766               case DW_OP_shl:
767                 result = second << first;
768                 break;
769               case DW_OP_shr:
770                 result = second >> first;
771                 break;
772               case DW_OP_shra:
773                 result = (_Unwind_Sword) second >> first;
774                 break;
775               case DW_OP_xor:
776                 result = second ^ first;
777                 break;
778               case DW_OP_le:
779                 result = (_Unwind_Sword) first <= (_Unwind_Sword) second;
780                 break;
781               case DW_OP_ge:
782                 result = (_Unwind_Sword) first >= (_Unwind_Sword) second;
783                 break;
784               case DW_OP_eq:
785                 result = (_Unwind_Sword) first == (_Unwind_Sword) second;
786                 break;
787               case DW_OP_lt:
788                 result = (_Unwind_Sword) first < (_Unwind_Sword) second;
789                 break;
790               case DW_OP_gt:
791                 result = (_Unwind_Sword) first > (_Unwind_Sword) second;
792                 break;
793               case DW_OP_ne:
794                 result = (_Unwind_Sword) first != (_Unwind_Sword) second;
795                 break;
796
797               default:
798                 gcc_unreachable ();
799               }
800           }
801           break;
802
803         case DW_OP_skip:
804           offset = read_2s (op_ptr);
805           op_ptr += 2;
806           op_ptr += offset;
807           goto no_push;
808
809         case DW_OP_bra:
810           gcc_assert (stack_elt);
811           stack_elt -= 1;
812           
813           offset = read_2s (op_ptr);
814           op_ptr += 2;
815           if (stack[stack_elt] != 0)
816             op_ptr += offset;
817           goto no_push;
818
819         case DW_OP_nop:
820           goto no_push;
821
822         default:
823           gcc_unreachable ();
824         }
825
826       /* Most things push a result value.  */
827       gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
828       stack[stack_elt++] = result;
829     no_push:;
830     }
831
832   /* We were executing this program to get a value.  It should be
833      at top of stack.  */
834   gcc_assert (stack_elt);
835   stack_elt -= 1;
836   return stack[stack_elt];
837 }
838
839
840 /* Decode DWARF 2 call frame information. Takes pointers the
841    instruction sequence to decode, current register information and
842    CIE info, and the PC range to evaluate.  */
843
844 static void
845 execute_cfa_program (const unsigned char *insn_ptr,
846                      const unsigned char *insn_end,
847                      struct _Unwind_Context *context,
848                      _Unwind_FrameState *fs)
849 {
850   struct frame_state_reg_info *unused_rs = NULL;
851
852   /* Don't allow remember/restore between CIE and FDE programs.  */
853   fs->regs.prev = NULL;
854
855   /* The comparison with the return address uses < rather than <= because
856      we are only interested in the effects of code before the call; for a
857      noreturn function, the return address may point to unrelated code with
858      a different stack configuration that we are not interested in.  We
859      assume that the call itself is unwind info-neutral; if not, or if
860      there are delay instructions that adjust the stack, these must be
861      reflected at the point immediately before the call insn.
862      In signal frames, return address is after last completed instruction,
863      so we add 1 to return address to make the comparison <=.  */
864   while (insn_ptr < insn_end
865          && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
866     {
867       unsigned char insn = *insn_ptr++;
868       _uleb128_t reg, utmp;
869       _sleb128_t offset, stmp;
870
871       if ((insn & 0xc0) == DW_CFA_advance_loc)
872         fs->pc += (insn & 0x3f) * fs->code_align;
873       else if ((insn & 0xc0) == DW_CFA_offset)
874         {
875           reg = insn & 0x3f;
876           insn_ptr = read_uleb128 (insn_ptr, &utmp);
877           offset = (_Unwind_Sword) utmp * fs->data_align;
878           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
879             = REG_SAVED_OFFSET;
880           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
881         }
882       else if ((insn & 0xc0) == DW_CFA_restore)
883         {
884           reg = insn & 0x3f;
885           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
886         }
887       else switch (insn)
888         {
889         case DW_CFA_set_loc:
890           {
891             _Unwind_Ptr pc;
892             
893             insn_ptr = read_encoded_value (context, fs->fde_encoding,
894                                            insn_ptr, &pc);
895             fs->pc = (void *) pc;
896           }
897           break;
898
899         case DW_CFA_advance_loc1:
900           fs->pc += read_1u (insn_ptr) * fs->code_align;
901           insn_ptr += 1;
902           break;
903         case DW_CFA_advance_loc2:
904           fs->pc += read_2u (insn_ptr) * fs->code_align;
905           insn_ptr += 2;
906           break;
907         case DW_CFA_advance_loc4:
908           fs->pc += read_4u (insn_ptr) * fs->code_align;
909           insn_ptr += 4;
910           break;
911
912         case DW_CFA_offset_extended:
913           insn_ptr = read_uleb128 (insn_ptr, &reg);
914           insn_ptr = read_uleb128 (insn_ptr, &utmp);
915           offset = (_Unwind_Sword) utmp * fs->data_align;
916           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
917             = REG_SAVED_OFFSET;
918           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
919           break;
920
921         case DW_CFA_restore_extended:
922           insn_ptr = read_uleb128 (insn_ptr, &reg);
923           /* FIXME, this is wrong; the CIE might have said that the
924              register was saved somewhere.  */
925           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
926           break;
927
928         case DW_CFA_undefined:
929         case DW_CFA_same_value:
930           insn_ptr = read_uleb128 (insn_ptr, &reg);
931           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
932           break;
933
934         case DW_CFA_nop:
935           break;
936
937         case DW_CFA_register:
938           {
939             _uleb128_t reg2;
940             insn_ptr = read_uleb128 (insn_ptr, &reg);
941             insn_ptr = read_uleb128 (insn_ptr, &reg2);
942             fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
943             fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
944               (_Unwind_Word)reg2;
945           }
946           break;
947
948         case DW_CFA_remember_state:
949           {
950             struct frame_state_reg_info *new_rs;
951             if (unused_rs)
952               {
953                 new_rs = unused_rs;
954                 unused_rs = unused_rs->prev;
955               }
956             else
957               new_rs = alloca (sizeof (struct frame_state_reg_info));
958
959             *new_rs = fs->regs;
960             fs->regs.prev = new_rs;
961           }
962           break;
963
964         case DW_CFA_restore_state:
965           {
966             struct frame_state_reg_info *old_rs = fs->regs.prev;
967             fs->regs = *old_rs;
968             old_rs->prev = unused_rs;
969             unused_rs = old_rs;
970           }
971           break;
972
973         case DW_CFA_def_cfa:
974           insn_ptr = read_uleb128 (insn_ptr, &utmp);
975           fs->regs.cfa_reg = (_Unwind_Word)utmp;
976           insn_ptr = read_uleb128 (insn_ptr, &utmp);
977           fs->regs.cfa_offset = (_Unwind_Word)utmp;
978           fs->regs.cfa_how = CFA_REG_OFFSET;
979           break;
980
981         case DW_CFA_def_cfa_register:
982           insn_ptr = read_uleb128 (insn_ptr, &utmp);
983           fs->regs.cfa_reg = (_Unwind_Word)utmp;
984           fs->regs.cfa_how = CFA_REG_OFFSET;
985           break;
986
987         case DW_CFA_def_cfa_offset:
988           insn_ptr = read_uleb128 (insn_ptr, &utmp);
989           fs->regs.cfa_offset = utmp;
990           /* cfa_how deliberately not set.  */
991           break;
992
993         case DW_CFA_def_cfa_expression:
994           fs->regs.cfa_exp = insn_ptr;
995           fs->regs.cfa_how = CFA_EXP;
996           insn_ptr = read_uleb128 (insn_ptr, &utmp);
997           insn_ptr += utmp;
998           break;
999
1000         case DW_CFA_expression:
1001           insn_ptr = read_uleb128 (insn_ptr, &reg);
1002           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
1003           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
1004           insn_ptr = read_uleb128 (insn_ptr, &utmp);
1005           insn_ptr += utmp;
1006           break;
1007
1008           /* Dwarf3.  */
1009         case DW_CFA_offset_extended_sf:
1010           insn_ptr = read_uleb128 (insn_ptr, &reg);
1011           insn_ptr = read_sleb128 (insn_ptr, &stmp);
1012           offset = stmp * fs->data_align;
1013           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1014             = REG_SAVED_OFFSET;
1015           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1016           break;
1017
1018         case DW_CFA_def_cfa_sf:
1019           insn_ptr = read_uleb128 (insn_ptr, &utmp);
1020           fs->regs.cfa_reg = (_Unwind_Word)utmp;
1021           insn_ptr = read_sleb128 (insn_ptr, &stmp);
1022           fs->regs.cfa_offset = (_Unwind_Sword)stmp;
1023           fs->regs.cfa_how = CFA_REG_OFFSET;
1024           fs->regs.cfa_offset *= fs->data_align;
1025           break;
1026
1027         case DW_CFA_def_cfa_offset_sf:
1028           insn_ptr = read_sleb128 (insn_ptr, &stmp);
1029           fs->regs.cfa_offset = (_Unwind_Sword)stmp;
1030           fs->regs.cfa_offset *= fs->data_align;
1031           /* cfa_how deliberately not set.  */
1032           break;
1033
1034         case DW_CFA_val_offset:
1035           insn_ptr = read_uleb128 (insn_ptr, &reg);
1036           insn_ptr = read_uleb128 (insn_ptr, &utmp);
1037           offset = (_Unwind_Sword) utmp * fs->data_align;
1038           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1039             = REG_SAVED_VAL_OFFSET;
1040           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1041           break;
1042
1043         case DW_CFA_val_offset_sf:
1044           insn_ptr = read_uleb128 (insn_ptr, &reg);
1045           insn_ptr = read_sleb128 (insn_ptr, &stmp);
1046           offset = stmp * fs->data_align;
1047           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1048             = REG_SAVED_VAL_OFFSET;
1049           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1050           break;
1051
1052         case DW_CFA_val_expression:
1053           insn_ptr = read_uleb128 (insn_ptr, &reg);
1054           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1055             = REG_SAVED_VAL_EXP;
1056           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
1057           insn_ptr = read_uleb128 (insn_ptr, &utmp);
1058           insn_ptr += utmp;
1059           break;
1060
1061         case DW_CFA_GNU_window_save:
1062           /* ??? Hardcoded for SPARC register window configuration.  */
1063           for (reg = 16; reg < 32; ++reg)
1064             {
1065               fs->regs.reg[reg].how = REG_SAVED_OFFSET;
1066               fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
1067             }
1068           break;
1069
1070         case DW_CFA_GNU_args_size:
1071           insn_ptr = read_uleb128 (insn_ptr, &utmp);
1072           context->args_size = (_Unwind_Word)utmp;
1073           break;
1074
1075         case DW_CFA_GNU_negative_offset_extended:
1076           /* Obsoleted by DW_CFA_offset_extended_sf, but used by
1077              older PowerPC code.  */
1078           insn_ptr = read_uleb128 (insn_ptr, &reg);
1079           insn_ptr = read_uleb128 (insn_ptr, &utmp);
1080           offset = (_Unwind_Word) utmp * fs->data_align;
1081           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1082             = REG_SAVED_OFFSET;
1083           fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
1084           break;
1085
1086         default:
1087           gcc_unreachable ();
1088         }
1089     }
1090 }
1091 \f
1092 /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
1093    its caller and decode it into FS.  This function also sets the
1094    args_size and lsda members of CONTEXT, as they are really information
1095    about the caller's frame.  */
1096
1097 static _Unwind_Reason_Code
1098 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1099 {
1100   const struct dwarf_fde *fde;
1101   const struct dwarf_cie *cie;
1102   const unsigned char *aug, *insn, *end;
1103
1104   memset (fs, 0, sizeof (*fs));
1105   context->args_size = 0;
1106   context->lsda = 0;
1107
1108   if (context->ra == 0)
1109     return _URC_END_OF_STACK;
1110
1111   fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
1112                           &context->bases);
1113   if (fde == NULL)
1114     {
1115 #ifdef MD_FALLBACK_FRAME_STATE_FOR
1116       /* Couldn't find frame unwind info for this function.  Try a
1117          target-specific fallback mechanism.  This will necessarily
1118          not provide a personality routine or LSDA.  */
1119       return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
1120 #else
1121       return _URC_END_OF_STACK;
1122 #endif
1123     }
1124
1125   fs->pc = context->bases.func;
1126
1127   cie = get_cie (fde);
1128   insn = extract_cie_info (cie, context, fs);
1129   if (insn == NULL)
1130     /* CIE contained unknown augmentation.  */
1131     return _URC_FATAL_PHASE1_ERROR;
1132
1133   /* First decode all the insns in the CIE.  */
1134   end = (unsigned char *) next_fde ((struct dwarf_fde *) cie);
1135   execute_cfa_program (insn, end, context, fs);
1136
1137   /* Locate augmentation for the fde.  */
1138   aug = (unsigned char *) fde + sizeof (*fde);
1139   aug += 2 * size_of_encoded_value (fs->fde_encoding);
1140   insn = NULL;
1141   if (fs->saw_z)
1142     {
1143       _uleb128_t i;
1144       aug = read_uleb128 (aug, &i);
1145       insn = aug + i;
1146     }
1147   if (fs->lsda_encoding != DW_EH_PE_omit)
1148     {
1149       _Unwind_Ptr lsda;
1150       
1151       aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
1152       context->lsda = (void *) lsda;
1153     }
1154
1155   /* Then the insns in the FDE up to our target PC.  */
1156   if (insn == NULL)
1157     insn = aug;
1158   end = (unsigned char *) next_fde (fde);
1159   execute_cfa_program (insn, end, context, fs);
1160
1161   return _URC_NO_REASON;
1162 }
1163 \f
1164 typedef struct frame_state
1165 {
1166   void *cfa;
1167   void *eh_ptr;
1168   long cfa_offset;
1169   long args_size;
1170   long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
1171   unsigned short cfa_reg;
1172   unsigned short retaddr_column;
1173   char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
1174 } frame_state;
1175
1176 struct frame_state * __frame_state_for (void *, struct frame_state *);
1177
1178 /* Called from pre-G++ 3.0 __throw to find the registers to restore for
1179    a given PC_TARGET.  The caller should allocate a local variable of
1180    `struct frame_state' and pass its address to STATE_IN.  */
1181
1182 struct frame_state *
1183 __frame_state_for (void *pc_target, struct frame_state *state_in)
1184 {
1185   struct _Unwind_Context context;
1186   _Unwind_FrameState fs;
1187   int reg;
1188
1189   memset (&context, 0, sizeof (struct _Unwind_Context));
1190   context.flags = EXTENDED_CONTEXT_BIT;
1191   context.ra = pc_target + 1;
1192
1193   if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
1194     return 0;
1195
1196   /* We have no way to pass a location expression for the CFA to our
1197      caller.  It wouldn't understand it anyway.  */
1198   if (fs.regs.cfa_how == CFA_EXP)
1199     return 0;
1200
1201   for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
1202     {
1203       state_in->saved[reg] = fs.regs.reg[reg].how;
1204       switch (state_in->saved[reg])
1205         {
1206         case REG_SAVED_REG:
1207           state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
1208           break;
1209         case REG_SAVED_OFFSET:
1210           state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
1211           break;
1212         default:
1213           state_in->reg_or_offset[reg] = 0;
1214           break;
1215         }
1216     }
1217
1218   state_in->cfa_offset = fs.regs.cfa_offset;
1219   state_in->cfa_reg = fs.regs.cfa_reg;
1220   state_in->retaddr_column = fs.retaddr_column;
1221   state_in->args_size = context.args_size;
1222   state_in->eh_ptr = fs.eh_ptr;
1223
1224   return state_in;
1225 }
1226 \f
1227 typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
1228
1229 static inline void
1230 _Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
1231                      _Unwind_SpTmp *tmp_sp)
1232 {
1233   int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
1234   
1235   if (size == sizeof(_Unwind_Ptr))
1236     tmp_sp->ptr = (_Unwind_Ptr) cfa;
1237   else
1238     {
1239       gcc_assert (size == sizeof(_Unwind_Word));
1240       tmp_sp->word = (_Unwind_Ptr) cfa;
1241     }
1242   _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
1243 }
1244
1245 static void
1246 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1247 {
1248   struct _Unwind_Context orig_context = *context;
1249   void *cfa;
1250   long i;
1251
1252 #ifdef EH_RETURN_STACKADJ_RTX
1253   /* Special handling here: Many machines do not use a frame pointer,
1254      and track the CFA only through offsets from the stack pointer from
1255      one frame to the next.  In this case, the stack pointer is never
1256      stored, so it has no saved address in the context.  What we do
1257      have is the CFA from the previous stack frame.
1258
1259      In very special situations (such as unwind info for signal return),
1260      there may be location expressions that use the stack pointer as well.
1261
1262      Do this conditionally for one frame.  This allows the unwind info
1263      for one frame to save a copy of the stack pointer from the previous
1264      frame, and be able to use much easier CFA mechanisms to do it.
1265      Always zap the saved stack pointer value for the next frame; carrying
1266      the value over from one frame to another doesn't make sense.  */
1267
1268   _Unwind_SpTmp tmp_sp;
1269
1270   if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
1271     _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
1272   _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
1273 #endif
1274
1275   /* Compute this frame's CFA.  */
1276   switch (fs->regs.cfa_how)
1277     {
1278     case CFA_REG_OFFSET:
1279       cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
1280       cfa += fs->regs.cfa_offset;
1281       break;
1282
1283     case CFA_EXP:
1284       {
1285         const unsigned char *exp = fs->regs.cfa_exp;
1286         _uleb128_t len;
1287
1288         exp = read_uleb128 (exp, &len);
1289         cfa = (void *) (_Unwind_Ptr)
1290           execute_stack_op (exp, exp + len, &orig_context, 0);
1291         break;
1292       }
1293
1294     default:
1295       gcc_unreachable ();
1296     }
1297   context->cfa = cfa;
1298
1299   /* Compute the addresses of all registers saved in this frame.  */
1300   for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
1301     switch (fs->regs.reg[i].how)
1302       {
1303       case REG_UNSAVED:
1304         break;
1305
1306       case REG_SAVED_OFFSET:
1307         _Unwind_SetGRPtr (context, i,
1308                           (void *) (cfa + fs->regs.reg[i].loc.offset));
1309         break;
1310
1311       case REG_SAVED_REG:
1312         if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
1313           _Unwind_SetGRValue (context, i,
1314                               _Unwind_GetGR (&orig_context,
1315                                              fs->regs.reg[i].loc.reg));
1316         else
1317           _Unwind_SetGRPtr (context, i,
1318                             _Unwind_GetGRPtr (&orig_context,
1319                                               fs->regs.reg[i].loc.reg));
1320         break;
1321
1322       case REG_SAVED_EXP:
1323         {
1324           const unsigned char *exp = fs->regs.reg[i].loc.exp;
1325           _uleb128_t len;
1326           _Unwind_Ptr val;
1327
1328           exp = read_uleb128 (exp, &len);
1329           val = execute_stack_op (exp, exp + len, &orig_context,
1330                                   (_Unwind_Ptr) cfa);
1331           _Unwind_SetGRPtr (context, i, (void *) val);
1332         }
1333         break;
1334
1335       case REG_SAVED_VAL_OFFSET:
1336         _Unwind_SetGRValue (context, i,
1337                             (_Unwind_Internal_Ptr)
1338                             (cfa + fs->regs.reg[i].loc.offset));
1339         break;
1340
1341       case REG_SAVED_VAL_EXP:
1342         {
1343           const unsigned char *exp = fs->regs.reg[i].loc.exp;
1344           _uleb128_t len;
1345           _Unwind_Ptr val;
1346
1347           exp = read_uleb128 (exp, &len);
1348           val = execute_stack_op (exp, exp + len, &orig_context,
1349                                   (_Unwind_Ptr) cfa);
1350           _Unwind_SetGRValue (context, i, val);
1351         }
1352         break;
1353       }
1354
1355   _Unwind_SetSignalFrame (context, fs->signal_frame);
1356
1357 #ifdef MD_FROB_UPDATE_CONTEXT
1358   MD_FROB_UPDATE_CONTEXT (context, fs);
1359 #endif
1360 }
1361
1362 /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
1363    of its caller.  Update CONTEXT to refer to the caller as well.  Note
1364    that the args_size and lsda members are not updated here, but later in
1365    uw_frame_state_for.  */
1366
1367 static void
1368 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1369 {
1370   uw_update_context_1 (context, fs);
1371
1372   /* Compute the return address now, since the return address column
1373      can change from frame to frame.  */
1374   context->ra = __builtin_extract_return_addr
1375     (_Unwind_GetPtr (context, fs->retaddr_column));
1376 }
1377
1378 static void
1379 uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1380 {
1381   uw_update_context (context, fs);
1382 }
1383 \f
1384 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
1385    level will be the return address and the CFA.  */
1386
1387 #define uw_init_context(CONTEXT)                                           \
1388   do                                                                       \
1389     {                                                                      \
1390       /* Do any necessary initialization to access arbitrary stack frames. \
1391          On the SPARC, this means flushing the register windows.  */       \
1392       __builtin_unwind_init ();                                            \
1393       uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),                  \
1394                          __builtin_return_address (0));                    \
1395     }                                                                      \
1396   while (0)
1397
1398 static inline void
1399 init_dwarf_reg_size_table (void)
1400 {
1401   __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
1402 }
1403
1404 static void
1405 uw_init_context_1 (struct _Unwind_Context *context,
1406                    void *outer_cfa, void *outer_ra)
1407 {
1408   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
1409   _Unwind_FrameState fs;
1410   _Unwind_SpTmp sp_slot;
1411   _Unwind_Reason_Code code;
1412
1413   memset (context, 0, sizeof (struct _Unwind_Context));
1414   context->ra = ra;
1415   context->flags = EXTENDED_CONTEXT_BIT;
1416
1417   code = uw_frame_state_for (context, &fs);
1418   gcc_assert (code == _URC_NO_REASON);
1419
1420 #if __GTHREADS
1421   {
1422     static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
1423     if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
1424         && dwarf_reg_size_table[0] == 0)
1425       init_dwarf_reg_size_table ();
1426   }
1427 #else
1428   if (dwarf_reg_size_table[0] == 0)
1429     init_dwarf_reg_size_table ();
1430 #endif
1431
1432   /* Force the frame state to use the known cfa value.  */
1433   _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
1434   fs.regs.cfa_how = CFA_REG_OFFSET;
1435   fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
1436   fs.regs.cfa_offset = 0;
1437
1438   uw_update_context_1 (context, &fs);
1439
1440   /* If the return address column was saved in a register in the
1441      initialization context, then we can't see it in the given
1442      call frame data.  So have the initialization context tell us.  */
1443   context->ra = __builtin_extract_return_addr (outer_ra);
1444 }
1445
1446
1447 /* Install TARGET into CURRENT so that we can return to it.  This is a
1448    macro because __builtin_eh_return must be invoked in the context of
1449    our caller.  */
1450
1451 #define uw_install_context(CURRENT, TARGET)                              \
1452   do                                                                     \
1453     {                                                                    \
1454       long offset = uw_install_context_1 ((CURRENT), (TARGET));          \
1455       void *handler = __builtin_frob_return_addr ((TARGET)->ra);         \
1456       __builtin_eh_return (offset, handler);                             \
1457     }                                                                    \
1458   while (0)
1459
1460 static long
1461 uw_install_context_1 (struct _Unwind_Context *current,
1462                       struct _Unwind_Context *target)
1463 {
1464   long i;
1465   _Unwind_SpTmp sp_slot;
1466
1467   /* If the target frame does not have a saved stack pointer,
1468      then set up the target's CFA.  */
1469   if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
1470     _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
1471
1472   for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
1473     {
1474       void *c = current->reg[i];
1475       void *t = target->reg[i];
1476
1477       gcc_assert (current->by_value[i] == 0);
1478       if (target->by_value[i] && c)
1479         {
1480           _Unwind_Word w;
1481           _Unwind_Ptr p;
1482           if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
1483             {
1484               w = (_Unwind_Internal_Ptr) t;
1485               memcpy (c, &w, sizeof (_Unwind_Word));
1486             }
1487           else
1488             {
1489               gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
1490               p = (_Unwind_Internal_Ptr) t;
1491               memcpy (c, &p, sizeof (_Unwind_Ptr));
1492             }
1493         }
1494       else if (t && c && t != c)
1495         memcpy (c, t, dwarf_reg_size_table[i]);
1496     }
1497
1498   /* If the current frame doesn't have a saved stack pointer, then we
1499      need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
1500      pointer value reloaded.  */
1501   if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
1502     {
1503       void *target_cfa;
1504
1505       target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
1506
1507       /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
1508       if (STACK_GROWS_DOWNWARD)
1509         return target_cfa - current->cfa + target->args_size;
1510       else
1511         return current->cfa - target_cfa - target->args_size;
1512     }
1513   return 0;
1514 }
1515
1516 static inline _Unwind_Ptr
1517 uw_identify_context (struct _Unwind_Context *context)
1518 {
1519   return _Unwind_GetIP (context);
1520 }
1521
1522
1523 #include "unwind.inc"
1524
1525 #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
1526 alias (_Unwind_Backtrace);
1527 alias (_Unwind_DeleteException);
1528 alias (_Unwind_FindEnclosingFunction);
1529 alias (_Unwind_ForcedUnwind);
1530 alias (_Unwind_GetDataRelBase);
1531 alias (_Unwind_GetTextRelBase);
1532 alias (_Unwind_GetCFA);
1533 alias (_Unwind_GetGR);
1534 alias (_Unwind_GetIP);
1535 alias (_Unwind_GetLanguageSpecificData);
1536 alias (_Unwind_GetRegionStart);
1537 alias (_Unwind_RaiseException);
1538 alias (_Unwind_Resume);
1539 alias (_Unwind_Resume_or_Rethrow);
1540 alias (_Unwind_SetGR);
1541 alias (_Unwind_SetIP);
1542 #endif
1543
1544 #endif /* !USING_SJLJ_EXCEPTIONS */