OSDN Git Service

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