OSDN Git Service

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