1 // Functions for Exception Support for Java.
3 /* Copyright (C) 1998, 1999, 2001, 2002 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
16 #include <java/lang/Class.h>
17 #include <java/lang/NullPointerException.h>
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().
26 static __attribute__ ((__noreturn__
)) void
34 struct alignment_test_struct
37 char end
[0] __attribute__((aligned
));
40 struct java_exception_header
42 /* Cache handler details between Phase 1 and Phase 2. */
43 _Unwind_Ptr landingPad
;
44 int handlerSwitchValue
;
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)). */
50 char pad
[sizeof(jthrowable
) < sizeof(alignment_test_struct
)
51 ? sizeof(alignment_test_struct
) - sizeof(jthrowable
) : 0]
52 __attribute__((aligned
));
56 /* The generic exception header. */
57 _Unwind_Exception unwindHeader
;
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');
72 static inline java_exception_header
*
73 get_exception_header_from_ue (_Unwind_Exception
*exc
)
75 return reinterpret_cast<java_exception_header
*>(exc
+ 1) - 1;
78 /* Perform a throw, Java style. Throw will unwind through this call,
79 so there better not be any handlers or exception thrown here. */
82 _Jv_Throw (jthrowable value
)
84 java_exception_header
*xh
85 = static_cast<java_exception_header
*>(_Jv_AllocRawObj (sizeof (*xh
)));
88 value
= new java::lang::NullPointerException ();
91 xh
->unwindHeader
.exception_class
= __gcj_exception_class
;
92 xh
->unwindHeader
.exception_cleanup
= NULL
;
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
);
100 code
= _Unwind_RaiseException (&xh
->unwindHeader
);
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
114 #include "unwind-pe.h"
116 struct lsda_header_info
120 const unsigned char *TType
;
121 const unsigned char *action_table
;
122 unsigned char ttype_encoding
;
123 unsigned char call_site_encoding
;
126 static const unsigned char *
127 parse_lsda_header (_Unwind_Context
*context
, const unsigned char *p
,
128 lsda_header_info
*info
)
131 unsigned char lpstart_encoding
;
133 info
->Start
= (context
? _Unwind_GetRegionStart (context
) : 0);
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
);
140 info
->LPStart
= info
->Start
;
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
)
146 p
= read_uleb128 (p
, &tmp
);
147 info
->TType
= p
+ tmp
;
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
;
162 get_ttype_entry (_Unwind_Context
*context
, lsda_header_info
*info
, long i
)
166 i
*= size_of_encoded_value (info
->ttype_encoding
);
167 read_encoded_value (context
, info
->ttype_encoding
, info
->TType
- i
, &ptr
);
169 return reinterpret_cast<jclass
>(ptr
);
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
179 #define PERSONALITY_FUNCTION __gcj_personality_v0
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
)
189 java_exception_header
*xh
= get_exception_header_from_ue (ue_header
);
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
;
201 // Interface version check.
203 return _URC_FATAL_PHASE1_ERROR
;
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
)
209 handler_switch_value
= xh
->handlerSwitchValue
;
210 landing_pad
= xh
->landingPad
;
211 goto install_context
;
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.
223 language_specific_data
= (const unsigned char *)
224 _Unwind_GetLanguageSpecificData (context
);
226 // If no LSDA, then there are no handlers or cleanups.
227 if (! language_specific_data
)
228 return _URC_CONTINUE_UNWIND
;
230 // Parse the LSDA header.
231 p
= parse_lsda_header (context
, language_specific_data
, &info
);
232 ip
= _Unwind_GetIP (context
) - 1;
235 handler_switch_value
= 0;
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
243 return _URC_CONTINUE_UNWIND
;
246 _Unwind_Word cs_lp
, cs_action
;
249 p
= read_uleb128 (p
, &cs_lp
);
250 p
= read_uleb128 (p
, &cs_action
);
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;
258 action_record
= info
.action_table
+ cs_action
- 1;
259 goto found_something
;
262 // Search the call-site table for the action associated with this IP.
263 while (p
< info
.action_table
)
265 _Unwind_Ptr cs_start
, cs_len
, cs_lp
;
266 _Unwind_Word cs_action
;
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
);
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
)
280 landing_pad
= info
.LPStart
+ cs_lp
;
282 action_record
= info
.action_table
+ cs_action
- 1;
283 goto found_something
;
286 #endif // SJLJ_EXCEPTIONS
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
;
297 if (landing_pad
== 0)
299 // If ip is present, and has a null landing pad, there are
300 // no cleanups or handlers to be run.
302 else if (action_record
== 0)
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.
311 // Otherwise we have a catch handler.
312 _Unwind_Sword ar_filter
, ar_disp
;
317 p
= read_sleb128 (p
, &ar_filter
);
318 read_sleb128 (p
, &ar_disp
);
322 // Zero filter values are cleanups.
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
)
332 else if (ar_filter
> 0)
334 // Positive filter values are handlers.
336 jclass catch_type
= get_ttype_entry (context
, &info
, ar_filter
);
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
*)catch_type
- 1, NULL
);
343 if (_Jv_IsInstanceOf (xh
->value
, catch_type
))
345 handler_switch_value
= ar_filter
;
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.
362 action_record
= p
+ ar_disp
;
366 if (! saw_handler
&& ! saw_cleanup
)
367 return _URC_CONTINUE_UNWIND
;
369 if (actions
& _UA_SEARCH_PHASE
)
372 return _URC_CONTINUE_UNWIND
;
374 // For domestic exceptions, we cache data from phase 1 for phase 2.
375 if (exception_class
== __gcj_exception_class
)
377 xh
->handlerSwitchValue
= handler_switch_value
;
378 xh
->landingPad
= landing_pad
;
380 return _URC_HANDLER_FOUND
;
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
;