OSDN Git Service

2009-08-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libjava / exception.cc
1 // Functions for Exception Support for Java.
2
3 /* Copyright (C) 1998, 1999, 2001, 2002, 2006  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12
13 #include <stddef.h>
14 #include <stdlib.h>
15
16 #include <java/lang/Class.h>
17 #include <java/lang/NullPointerException.h>
18 #include <gnu/gcj/RawData.h> 
19 #include <gcj/cni.h>
20 #include <jvm.h>
21
22 // unwind-pe.h uses std::abort(), but sometimes we compile libjava
23 // without libstdc++-v3. The following hack forces it to use
24 // stdlib.h's abort().
25 namespace std
26 {
27   static __attribute__ ((__noreturn__)) void
28   abort ()
29   {
30     ::abort ();
31   }
32 }
33 #include "unwind.h"
34
35 struct alignment_test_struct
36 {
37   char space;
38   char end[0] __attribute__((aligned));
39 };
40
41 struct java_exception_header
42 {
43   /* Cache handler details between Phase 1 and Phase 2.  */
44   _Unwind_Ptr landingPad;
45   int handlerSwitchValue;
46
47   /* The object being thrown.  Compiled code expects this to be immediately
48      before the generic exception header.  Which is complicated by the fact
49      that _Unwind_Exception is ((aligned)).  */
50
51   char pad[sizeof(jthrowable) < sizeof(alignment_test_struct)
52            ? sizeof(alignment_test_struct) - sizeof(jthrowable) : 0]
53     __attribute__((aligned));
54
55   jthrowable value;
56
57   /* The generic exception header.  */
58   _Unwind_Exception unwindHeader;
59 };
60
61 #ifdef __ARM_EABI_UNWINDER__
62 // This is the exception class we report -- "GNUCJAVA".
63
64 const _Unwind_Exception_Class __gcj_exception_class
65   = {'G', 'N', 'U', 'C', 'J', 'A', 'V', 'A'};
66
67 static inline java_exception_header *
68 get_exception_header_from_ue (_Unwind_Exception *exc)
69 {
70   return reinterpret_cast<java_exception_header *>(exc + 1) - 1;
71 }
72
73 extern "C" void __cxa_begin_cleanup (_Unwind_Exception*);
74
75 #else // !__ARM_EABI_UNWINDER__
76 // This is the exception class we report -- "GNUCJAVA".
77 const _Unwind_Exception_Class __gcj_exception_class
78 = ((((((((_Unwind_Exception_Class) 'G' 
79          << 8 | (_Unwind_Exception_Class) 'N')
80         << 8 | (_Unwind_Exception_Class) 'U')
81        << 8 | (_Unwind_Exception_Class) 'C')
82       << 8 | (_Unwind_Exception_Class) 'J')
83      << 8 | (_Unwind_Exception_Class) 'A')
84     << 8 | (_Unwind_Exception_Class) 'V')
85    << 8 | (_Unwind_Exception_Class) 'A');
86
87
88 static inline java_exception_header *
89 get_exception_header_from_ue (_Unwind_Exception *exc)
90 {
91   return reinterpret_cast<java_exception_header *>(exc + 1) - 1;
92 }
93 #endif // !__ARM_EABI_UNWINDER__
94
95 /* Perform a throw, Java style. Throw will unwind through this call,
96    so there better not be any handlers or exception thrown here. */
97
98 extern "C" void
99 _Jv_Throw (jthrowable value)
100 {
101   java_exception_header *xh
102     = static_cast<java_exception_header *>(_Jv_AllocRawObj (sizeof (*xh)));
103
104   if (value == NULL)
105     value = new java::lang::NullPointerException ();
106   xh->value = value;
107
108   memcpy (&xh->unwindHeader.exception_class, &__gcj_exception_class,
109           sizeof xh->unwindHeader.exception_class);
110   xh->unwindHeader.exception_cleanup = NULL;
111
112   /* We're happy with setjmp/longjmp exceptions or region-based
113      exception handlers: entry points are provided here for both.  */
114   _Unwind_Reason_Code code;
115 #ifdef SJLJ_EXCEPTIONS
116   code = _Unwind_SjLj_RaiseException (&xh->unwindHeader);
117 #else
118   code = _Unwind_RaiseException (&xh->unwindHeader);
119 #endif
120
121   /* If code == _URC_END_OF_STACK, then we reached top of stack without
122      finding a handler for the exception.  Since each thread is run in
123      a try/catch, this oughtn't happen.  If code is something else, we
124      encountered some sort of heinous lossage from which we could not
125      recover.  As is the way of such things, almost certainly we will have
126      crashed before now, rather than actually being able to diagnose the
127      problem.  */
128   abort();
129 }
130
131 \f
132 #include "unwind-pe.h"
133 \f
134 struct lsda_header_info
135 {
136   _Unwind_Ptr Start;
137   _Unwind_Ptr LPStart;
138   const unsigned char *TType;
139   const unsigned char *action_table;
140   unsigned char ttype_encoding;
141   unsigned char call_site_encoding;
142 };
143
144 static const unsigned char *
145 parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
146                    lsda_header_info *info)
147 {
148   _uleb128_t tmp;
149   unsigned char lpstart_encoding;
150
151   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
152
153   // Find @LPStart, the base to which landing pad offsets are relative.
154   lpstart_encoding = *p++;
155   if (lpstart_encoding != DW_EH_PE_omit)
156     p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
157   else
158     info->LPStart = info->Start;
159
160   // Find @TType, the base of the handler and exception spec type data.
161   info->ttype_encoding = *p++;
162   if (info->ttype_encoding != DW_EH_PE_omit)
163     {
164       p = read_uleb128 (p, &tmp);
165       info->TType = p + tmp;
166     }
167   else
168     info->TType = 0;
169
170   // The encoding and length of the call-site table; the action table
171   // immediately follows.
172   info->call_site_encoding = *p++;
173   p = read_uleb128 (p, &tmp);
174   info->action_table = p + tmp;
175
176   return p;
177 }
178
179 #ifdef __ARM_EABI_UNWINDER__
180
181 static void **
182 get_ttype_entry(_Unwind_Context *, lsda_header_info* info, _uleb128_t i)
183 {
184   _Unwind_Ptr ptr;
185
186   ptr = (_Unwind_Ptr) (info->TType - (i * 4));
187   ptr = _Unwind_decode_target2(ptr);
188   
189   return reinterpret_cast<void **>(ptr);
190 }
191
192 #else
193
194 static void **
195 get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
196 {
197   _Unwind_Ptr ptr;
198
199   i *= size_of_encoded_value (info->ttype_encoding);
200   read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
201
202   return reinterpret_cast<void **>(ptr);
203 }
204
205 #endif
206
207 // Using a different personality function name causes link failures
208 // when trying to mix code using different exception handling models.
209 #ifdef SJLJ_EXCEPTIONS
210 #define PERSONALITY_FUNCTION    __gcj_personality_sj0
211 #define __builtin_eh_return_data_regno(x) x
212 #else
213 #define PERSONALITY_FUNCTION    __gcj_personality_v0
214 #endif
215
216 #ifdef __ARM_EABI_UNWINDER__
217
218 #define CONTINUE_UNWINDING \
219   do                                                            \
220     {                                                           \
221       if (__gnu_unwind_frame(ue_header, context) != _URC_OK)    \
222         return _URC_FAILURE;                                    \
223       return _URC_CONTINUE_UNWIND;                              \
224     }                                                           \
225   while (0)
226
227 extern "C" _Unwind_Reason_Code
228 PERSONALITY_FUNCTION (_Unwind_State state,
229                       struct _Unwind_Exception* ue_header,
230                       struct _Unwind_Context* context)
231 #else
232
233 #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
234
235 extern "C" _Unwind_Reason_Code
236 PERSONALITY_FUNCTION (int version,
237                       _Unwind_Action actions,
238                       _Unwind_Exception_Class exception_class,
239                       struct _Unwind_Exception *ue_header,
240                       struct _Unwind_Context *context)
241
242 #endif
243 {
244   java_exception_header *xh = get_exception_header_from_ue (ue_header);
245
246   lsda_header_info info;
247   const unsigned char *language_specific_data;
248   const unsigned char *action_record;
249   const unsigned char *p;
250   _Unwind_Ptr landing_pad, ip;
251   int handler_switch_value;
252   bool saw_cleanup;
253   bool saw_handler;
254   bool foreign_exception;
255   int ip_before_insn = 0;
256
257 #ifdef __ARM_EABI_UNWINDER__
258   _Unwind_Action actions;
259
260   switch (state & _US_ACTION_MASK)
261     {
262     case _US_VIRTUAL_UNWIND_FRAME:
263       actions = _UA_SEARCH_PHASE;
264       break;
265
266     case _US_UNWIND_FRAME_STARTING:
267       actions = _UA_CLEANUP_PHASE;
268       if (!(state & _US_FORCE_UNWIND)
269           && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
270         actions |= _UA_HANDLER_FRAME;
271       break;
272
273     case _US_UNWIND_FRAME_RESUME:
274       CONTINUE_UNWINDING;
275       break;
276
277     default:
278       std::abort();
279     }
280   actions |= state & _US_FORCE_UNWIND;
281
282   // We don't know which runtime we're working with, so can't check this.
283   // However the ABI routines hide this from us, and we don't actually need
284   // to know.
285   foreign_exception = false;
286
287   // The dwarf unwinder assumes the context structure holds things like the
288   // function and LSDA pointers.  The ARM implementation caches these in
289   // the exception header (UCB).  To avoid rewriting everything we make the
290   // virtual IP register point at the UCB.
291   ip = (_Unwind_Ptr) ue_header;
292   _Unwind_SetGR(context, 12, ip);
293
294 #else
295   // Interface version check.
296   if (version != 1)
297     return _URC_FATAL_PHASE1_ERROR;
298   foreign_exception = exception_class != __gcj_exception_class;
299 #endif
300
301   // Shortcut for phase 2 found handler for domestic exception.
302   if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
303       && !foreign_exception)
304     {
305       handler_switch_value = xh->handlerSwitchValue;
306       landing_pad = xh->landingPad;
307       goto install_context;
308     }
309
310   // FIXME: In Phase 1, record _Unwind_GetIPInfo in xh->obj as a part of
311   // the stack trace for this exception.  This will only collect Java
312   // frames, but perhaps that is acceptable.
313   // FIXME2: _Unwind_GetIPInfo is nonsensical for SJLJ, being a call-site
314   // index instead of a PC value.  We could perhaps arrange for
315   // _Unwind_GetRegionStart to return context->fc->jbuf[1], which
316   // is the address of the handler label for __builtin_longjmp, but
317   // there is no solution for DONT_USE_BUILTIN_SETJMP.
318
319   language_specific_data = (const unsigned char *)
320     _Unwind_GetLanguageSpecificData (context);
321
322   // If no LSDA, then there are no handlers or cleanups.
323   if (! language_specific_data)
324     CONTINUE_UNWINDING;
325
326   // Parse the LSDA header.
327   p = parse_lsda_header (context, language_specific_data, &info);
328 #ifdef HAVE_GETIPINFO
329   ip = _Unwind_GetIPInfo (context, &ip_before_insn);
330 #else
331   ip = _Unwind_GetIP (context) - 1;
332 #endif
333   if (! ip_before_insn)
334     --ip;
335   landing_pad = 0;
336   action_record = 0;
337   handler_switch_value = 0;
338
339 #ifdef SJLJ_EXCEPTIONS
340   // The given "IP" is an index into the call-site table, with two
341   // exceptions -- -1 means no-action, and 0 means terminate.  But
342   // since we're using uleb128 values, we've not got random access
343   // to the array.
344   if ((int) ip <= 0)
345     return _URC_CONTINUE_UNWIND;
346   else
347     {
348       _uleb128_t cs_lp, cs_action;
349       do
350         {
351           p = read_uleb128 (p, &cs_lp);
352           p = read_uleb128 (p, &cs_action);
353         }
354       while (--ip);
355
356       // Can never have null landing pad for sjlj -- that would have
357       // been indicated by a -1 call site index.
358       landing_pad = cs_lp + 1;
359       if (cs_action)
360         action_record = info.action_table + cs_action - 1;
361       goto found_something;
362     }
363 #else
364   // Search the call-site table for the action associated with this IP.
365   while (p < info.action_table)
366     {
367       _Unwind_Ptr cs_start, cs_len, cs_lp;
368       _uleb128_t cs_action;
369
370       // Note that all call-site encodings are "absolute" displacements.
371       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
372       p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
373       p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
374       p = read_uleb128 (p, &cs_action);
375
376       // The table is sorted, so if we've passed the ip, stop.
377       if (ip < info.Start + cs_start)
378         p = info.action_table;
379       else if (ip < info.Start + cs_start + cs_len)
380         {
381           if (cs_lp)
382             landing_pad = info.LPStart + cs_lp;
383           if (cs_action)
384             action_record = info.action_table + cs_action - 1;
385           goto found_something;
386         }
387     }
388 #endif // SJLJ_EXCEPTIONS
389
390   // If ip is not present in the table, C++ would call terminate.
391   // ??? It is perhaps better to tweek the LSDA so that no-action
392   // is mapped to no-entry for Java.
393   CONTINUE_UNWINDING;
394
395  found_something:
396   saw_cleanup = false;
397   saw_handler = false;
398
399   if (landing_pad == 0)
400     {
401       // If ip is present, and has a null landing pad, there are
402       // no cleanups or handlers to be run.
403     }
404   else if (action_record == 0)
405     {
406       // If ip is present, has a non-null landing pad, and a null
407       // action table offset, then there are only cleanups present.
408       // Cleanups use a zero switch value, as set above.
409       saw_cleanup = true;
410     }
411   else
412     {
413       // Otherwise we have a catch handler.
414       _sleb128_t ar_filter, ar_disp;
415
416       while (1)
417         {
418           p = action_record;
419           p = read_sleb128 (p, &ar_filter);
420           read_sleb128 (p, &ar_disp);
421
422           if (ar_filter == 0)
423             {
424               // Zero filter values are cleanups.
425               saw_cleanup = true;
426             }
427
428           // During forced unwinding, we only run cleanups.  With a
429           // foreign exception class, we have no class info to match.
430           else if ((actions & _UA_FORCE_UNWIND)
431                    || foreign_exception)
432             ;
433
434           else if (ar_filter > 0)
435             {
436               // Positive filter values are handlers.
437
438               void **catch_word = get_ttype_entry (context, &info, ar_filter);
439               jclass catch_type = (jclass)*catch_word;
440
441               // FIXME: This line is a kludge to work around exception
442               // handlers written in C++, which don't yet use indirect
443               // dispatch.
444               if (catch_type == *(void **)&java::lang::Class::class$)
445                 catch_type = (jclass)catch_word;
446
447               if (_Jv_IsInstanceOf (xh->value, catch_type))
448                 {
449                   handler_switch_value = ar_filter;
450                   saw_handler = true;
451                   break;
452                 }
453             }
454           else
455             {
456               // Negative filter values are exception specifications,
457               // which Java does not use.
458               // ??? Perhaps better to make them an index into a table
459               // of null-terminated strings instead of playing games
460               // with Utf8Const+1 as above.
461               abort ();
462             }
463
464           if (ar_disp == 0)
465             break;
466           action_record = p + ar_disp;
467         }
468     }
469
470   if (! saw_handler && ! saw_cleanup)
471         CONTINUE_UNWINDING;
472
473   if (actions & _UA_SEARCH_PHASE)
474     {
475       if (! saw_handler)
476         CONTINUE_UNWINDING;
477
478       // For domestic exceptions, we cache data from phase 1 for phase 2.
479       if (! foreign_exception)
480         {
481           xh->handlerSwitchValue = handler_switch_value;
482           xh->landingPad = landing_pad;
483         }
484       return _URC_HANDLER_FOUND;
485     }
486
487  install_context:
488   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
489                  (_Unwind_Ptr) &xh->unwindHeader);
490   _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
491                  handler_switch_value);
492   _Unwind_SetIP (context, landing_pad);
493 #ifdef __ARM_EABI_UNWINDER__
494   if (saw_cleanup)
495     __cxa_begin_cleanup(ue_header);
496 #endif
497   return _URC_INSTALL_CONTEXT;
498 }