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