* Makefile.in (rtlanal.o): Depend on $(TM_P_H).
[official-gcc.git] / libjava / exception.cc
bloba8e6ece6e2841f75c6e6087a949a6f120470b2b0
1 // Functions for Exception Support for Java.
3 /* Copyright (C) 1998, 1999, 2001 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 #include <config.h>
13 #include <stddef.h>
14 #include <cstdlib>
16 #include <java/lang/Class.h>
17 #include <java/lang/NullPointerException.h>
18 #include <gcj/cni.h>
19 #include <jvm.h>
21 #include "unwind.h"
24 struct alignment_test_struct
26 char space;
27 char end[0] __attribute__((aligned));
30 struct java_exception_header
32 /* Cache handler details between Phase 1 and Phase 2. */
33 _Unwind_Ptr landingPad;
34 int handlerSwitchValue;
36 /* The object being thrown. Compiled code expects this to be immediately
37 before the generic exception header. Which is complicated by the fact
38 that _Unwind_Exception is ((aligned)). */
40 char pad[sizeof(jthrowable) < sizeof(alignment_test_struct)
41 ? sizeof(alignment_test_struct) - sizeof(jthrowable) : 0]
42 __attribute__((aligned));
44 jthrowable value;
46 /* The generic exception header. */
47 _Unwind_Exception unwindHeader;
50 // This is the exception class we report -- "GNUCJAVA".
51 const _Unwind_Exception_Class __gcj_exception_class
52 = ((((((((_Unwind_Exception_Class) 'G'
53 << 8 | (_Unwind_Exception_Class) 'N')
54 << 8 | (_Unwind_Exception_Class) 'U')
55 << 8 | (_Unwind_Exception_Class) 'C')
56 << 8 | (_Unwind_Exception_Class) 'J')
57 << 8 | (_Unwind_Exception_Class) 'A')
58 << 8 | (_Unwind_Exception_Class) 'V')
59 << 8 | (_Unwind_Exception_Class) 'A');
62 static inline java_exception_header *
63 get_exception_header_from_ue (_Unwind_Exception *exc)
65 return reinterpret_cast<java_exception_header *>(exc + 1) - 1;
68 /* Perform a throw, Java style. Throw will unwind through this call,
69 so there better not be any handlers or exception thrown here. */
71 extern "C" void
72 _Jv_Throw (jthrowable value)
74 java_exception_header *xh
75 = static_cast<java_exception_header *>(_Jv_AllocRawObj (sizeof (*xh)));
77 if (value == NULL)
78 value = new java::lang::NullPointerException ();
79 xh->value = value;
81 xh->unwindHeader.exception_class = __gcj_exception_class;
82 xh->unwindHeader.exception_cleanup = NULL;
84 /* We're happy with setjmp/longjmp exceptions or region-based
85 exception handlers: entry points are provided here for both. */
86 _Unwind_Reason_Code code;
87 #ifdef SJLJ_EXCEPTIONS
88 code = _Unwind_SjLj_RaiseException (&xh->unwindHeader);
89 #else
90 code = _Unwind_RaiseException (&xh->unwindHeader);
91 #endif
93 /* If code == _URC_END_OF_STACK, then we reached top of stack without
94 finding a handler for the exception. Since each thread is run in
95 a try/catch, this oughtn't happen. If code is something else, we
96 encountered some sort of heinous lossage from which we could not
97 recover. As is the way of such things, almost certainly we will have
98 crashed before now, rather than actually being able to diagnose the
99 problem. */
100 std::abort ();
104 #include "unwind-pe.h"
106 struct lsda_header_info
108 _Unwind_Ptr Start;
109 _Unwind_Ptr LPStart;
110 const unsigned char *TType;
111 const unsigned char *action_table;
112 unsigned char ttype_encoding;
113 unsigned char call_site_encoding;
116 static const unsigned char *
117 parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
118 lsda_header_info *info)
120 _Unwind_Word tmp;
121 unsigned char lpstart_encoding;
123 info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
125 // Find @LPStart, the base to which landing pad offsets are relative.
126 lpstart_encoding = *p++;
127 if (lpstart_encoding != DW_EH_PE_omit)
128 p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
129 else
130 info->LPStart = info->Start;
132 // Find @TType, the base of the handler and exception spec type data.
133 info->ttype_encoding = *p++;
134 if (info->ttype_encoding != DW_EH_PE_omit)
136 p = read_uleb128 (p, &tmp);
137 info->TType = p + tmp;
139 else
140 info->TType = 0;
142 // The encoding and length of the call-site table; the action table
143 // immediately follows.
144 info->call_site_encoding = *p++;
145 p = read_uleb128 (p, &tmp);
146 info->action_table = p + tmp;
148 return p;
151 static jclass
152 get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
154 _Unwind_Ptr ptr;
156 i *= size_of_encoded_value (info->ttype_encoding);
157 read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
159 return reinterpret_cast<jclass>(ptr);
163 // Using a different personality function name causes link failures
164 // when trying to mix code using different exception handling models.
165 #ifdef SJLJ_EXCEPTIONS
166 #define PERSONALITY_FUNCTION __gcj_personality_sj0
167 #define __builtin_eh_return_data_regno(x) x
168 #else
169 #define PERSONALITY_FUNCTION __gcj_personality_v0
170 #endif
172 extern "C" _Unwind_Reason_Code
173 PERSONALITY_FUNCTION (int version,
174 _Unwind_Action actions,
175 _Unwind_Exception_Class exception_class,
176 struct _Unwind_Exception *ue_header,
177 struct _Unwind_Context *context)
179 java_exception_header *xh = get_exception_header_from_ue (ue_header);
181 lsda_header_info info;
182 const unsigned char *language_specific_data;
183 const unsigned char *action_record;
184 const unsigned char *p;
185 _Unwind_Ptr landing_pad, ip;
186 int handler_switch_value;
187 bool saw_cleanup;
188 bool saw_handler;
191 // Interface version check.
192 if (version != 1)
193 return _URC_FATAL_PHASE1_ERROR;
195 // Shortcut for phase 2 found handler for domestic exception.
196 if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
197 && exception_class == __gcj_exception_class)
199 handler_switch_value = xh->handlerSwitchValue;
200 landing_pad = xh->landingPad;
201 goto install_context;
204 // FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of
205 // the stack trace for this exception. This will only collect Java
206 // frames, but perhaps that is acceptable.
207 // FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site
208 // index instead of a PC value. We could perhaps arrange for
209 // _Unwind_GetRegionStart to return context->fc->jbuf[1], which
210 // is the address of the handler label for __builtin_longjmp, but
211 // there is no solution for DONT_USE_BUILTIN_SETJMP.
213 language_specific_data = (const unsigned char *)
214 _Unwind_GetLanguageSpecificData (context);
216 // If no LSDA, then there are no handlers or cleanups.
217 if (! language_specific_data)
218 return _URC_CONTINUE_UNWIND;
220 // Parse the LSDA header.
221 p = parse_lsda_header (context, language_specific_data, &info);
222 ip = _Unwind_GetIP (context) - 1;
223 landing_pad = 0;
224 action_record = 0;
225 handler_switch_value = 0;
227 #ifdef SJLJ_EXCEPTIONS
228 // The given "IP" is an index into the call-site table, with two
229 // exceptions -- -1 means no-action, and 0 means terminate. But
230 // since we're using uleb128 values, we've not got random access
231 // to the array.
232 if ((int) ip <= 0)
233 return _URC_CONTINUE_UNWIND;
234 else
236 _Unwind_Word cs_lp, cs_action;
239 p = read_uleb128 (p, &cs_lp);
240 p = read_uleb128 (p, &cs_action);
242 while (--ip);
244 // Can never have null landing pad for sjlj -- that would have
245 // been indicated by a -1 call site index.
246 landing_pad = cs_lp + 1;
247 if (cs_action)
248 action_record = info.action_table + cs_action - 1;
249 goto found_something;
251 #else
252 // Search the call-site table for the action associated with this IP.
253 while (p < info.action_table)
255 _Unwind_Ptr cs_start, cs_len, cs_lp;
256 _Unwind_Word cs_action;
258 // Note that all call-site encodings are "absolute" displacements.
259 p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
260 p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
261 p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
262 p = read_uleb128 (p, &cs_action);
264 // The table is sorted, so if we've passed the ip, stop.
265 if (ip < info.Start + cs_start)
266 p = info.action_table;
267 else if (ip < info.Start + cs_start + cs_len)
269 if (cs_lp)
270 landing_pad = info.LPStart + cs_lp;
271 if (cs_action)
272 action_record = info.action_table + cs_action - 1;
273 goto found_something;
276 #endif // SJLJ_EXCEPTIONS
278 // If ip is not present in the table, C++ would call terminate.
279 // ??? It is perhaps better to tweek the LSDA so that no-action
280 // is mapped to no-entry for Java.
281 return _URC_CONTINUE_UNWIND;
283 found_something:
284 saw_cleanup = false;
285 saw_handler = false;
287 if (landing_pad == 0)
289 // If ip is present, and has a null landing pad, there are
290 // no cleanups or handlers to be run.
292 else if (action_record == 0)
294 // If ip is present, has a non-null landing pad, and a null
295 // action table offset, then there are only cleanups present.
296 // Cleanups use a zero switch value, as set above.
297 saw_cleanup = true;
299 else
301 // Otherwise we have a catch handler.
302 _Unwind_Sword ar_filter, ar_disp;
304 while (1)
306 p = action_record;
307 p = read_sleb128 (p, &ar_filter);
308 read_sleb128 (p, &ar_disp);
310 if (ar_filter == 0)
312 // Zero filter values are cleanups.
313 saw_cleanup = true;
316 // During forced unwinding, we only run cleanups. With a
317 // foreign exception class, we have no class info to match.
318 else if ((actions & _UA_FORCE_UNWIND)
319 || exception_class != __gcj_exception_class)
322 else if (ar_filter > 0)
324 // Positive filter values are handlers.
326 jclass catch_type = get_ttype_entry (context, &info, ar_filter);
328 // The catch_type is either a (java::lang::Class*) or
329 // is one more than a (Utf8Const*).
330 if ((size_t)catch_type & 1)
331 catch_type = _Jv_FindClass ((Utf8Const*)catch_type - 1, NULL);
333 if (_Jv_IsInstanceOf (xh->value, catch_type))
335 handler_switch_value = ar_filter;
336 saw_handler = true;
337 break;
340 else
342 // Negative filter values are exception specifications,
343 // which Java does not use.
344 // ??? Perhaps better to make them an index into a table
345 // of null-terminated strings instead of playing games
346 // with Utf8Const+1 as above.
347 std::abort ();
350 if (ar_disp == 0)
351 break;
352 action_record = p + ar_disp;
356 if (! saw_handler && ! saw_cleanup)
357 return _URC_CONTINUE_UNWIND;
359 if (actions & _UA_SEARCH_PHASE)
361 if (! saw_handler)
362 return _URC_CONTINUE_UNWIND;
364 // For domestic exceptions, we cache data from phase 1 for phase 2.
365 if (exception_class == __gcj_exception_class)
367 xh->handlerSwitchValue = handler_switch_value;
368 xh->landingPad = landing_pad;
370 return _URC_HANDLER_FOUND;
373 install_context:
374 _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
375 (_Unwind_Ptr) &xh->unwindHeader);
376 _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
377 handler_switch_value);
378 _Unwind_SetIP (context, landing_pad);
379 return _URC_INSTALL_CONTEXT;