@@ -59,8 +59,7 @@ use any::{Any, AnyRefExt};
5959use c_str:: CString ;
6060use cast;
6161use kinds:: Send ;
62- use libc:: { c_char, size_t} ;
63- use libc:: { c_void, c_int} ;
62+ use libc:: { c_void, c_char, size_t} ;
6463use option:: { Some , None , Option } ;
6564use result:: { Err , Ok } ;
6665use rt:: local:: Local ;
@@ -78,6 +77,7 @@ mod libunwind {
7877
7978 use libc:: { uintptr_t, uint64_t} ;
8079
80+ #[ cfg( not( target_os = "android" ) ) ]
8181 #[ repr( C ) ]
8282 pub enum _Unwind_Action
8383 {
@@ -88,6 +88,18 @@ mod libunwind {
8888 _UA_END_OF_STACK = 16 ,
8989 }
9090
91+ #[ cfg( target_os = "android" ) ]
92+ #[ repr( C ) ]
93+ pub enum _Unwind_State
94+ {
95+ _US_VIRTUAL_UNWIND_FRAME = 0 ,
96+ _US_UNWIND_FRAME_STARTING = 1 ,
97+ _US_UNWIND_FRAME_RESUME = 2 ,
98+ _US_ACTION_MASK = 3 ,
99+ _US_FORCE_UNWIND = 8 ,
100+ _US_END_OF_STACK = 16
101+ }
102+
91103 #[ repr( C ) ]
92104 pub enum _Unwind_Reason_Code {
93105 _URC_NO_REASON = 0 ,
@@ -99,6 +111,7 @@ mod libunwind {
99111 _URC_HANDLER_FOUND = 6 ,
100112 _URC_INSTALL_CONTEXT = 7 ,
101113 _URC_CONTINUE_UNWIND = 8 ,
114+ _URC_FAILURE = 9 , // used only by ARM EABI
102115 }
103116
104117 pub type _Unwind_Exception_Class = uint64_t ;
@@ -108,8 +121,7 @@ mod libunwind {
108121 pub struct _Unwind_Exception {
109122 exception_class : _Unwind_Exception_Class ,
110123 exception_cleanup : _Unwind_Exception_Cleanup_Fn ,
111- private_1 : _Unwind_Word ,
112- private_2 : _Unwind_Word ,
124+ private : [ _Unwind_Word , ..20 ] ,
113125 }
114126
115127 pub enum _Unwind_Context { }
@@ -148,7 +160,7 @@ impl Unwinder {
148160 let ep = rust_try ( try_fn, closure. code as * c_void ,
149161 closure. env as * c_void ) ;
150162 if !ep. is_null ( ) {
151- rtdebug ! ( "Caught {}" , ( * ep) . exception_class) ;
163+ rtdebug ! ( "caught {}" , ( * ep) . exception_class) ;
152164 uw:: _Unwind_DeleteException ( ep) ;
153165 }
154166 }
@@ -190,8 +202,7 @@ impl Unwinder {
190202 let exception = ~uw:: _Unwind_Exception {
191203 exception_class : rust_exception_class ( ) ,
192204 exception_cleanup : exception_cleanup,
193- private_1 : 0 ,
194- private_2 : 0
205+ private : [ 0 , ..20 ] ,
195206 } ;
196207 let error = uw:: _Unwind_RaiseException ( cast:: transmute ( exception) ) ;
197208 rtabort ! ( "Could not unwind stack, error = {}" , error as int)
@@ -242,51 +253,107 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
242253// This is achieved by overriding the return value in search phase to always
243254// say "catch!".
244255
245- extern "C" {
246- fn __gcc_personality_v0 ( version : c_int ,
247- actions : uw:: _Unwind_Action ,
248- exception_class : uw:: _Unwind_Exception_Class ,
249- ue_header : * uw:: _Unwind_Exception ,
250- context : * uw:: _Unwind_Context )
251- -> uw:: _Unwind_Reason_Code ;
252- }
256+ #[ cfg( not( target_os = "android" ) ) ]
257+ pub mod eabi {
258+ use uw = super :: libunwind;
259+ use libc:: c_int;
253260
254- #[ lang="eh_personality" ]
255- #[ no_mangle] // so we can reference it by name from middle/trans/base.rs
256- #[ doc( hidden) ]
257- #[ cfg( not( test) ) ]
258- pub extern "C" fn rust_eh_personality (
259- version : c_int ,
260- actions : uw:: _Unwind_Action ,
261- exception_class : uw:: _Unwind_Exception_Class ,
262- ue_header : * uw:: _Unwind_Exception ,
263- context : * uw:: _Unwind_Context
264- ) -> uw:: _Unwind_Reason_Code
265- {
266- unsafe {
267- __gcc_personality_v0 ( version, actions, exception_class, ue_header,
268- context)
261+ extern "C" {
262+ fn __gcc_personality_v0 ( version : c_int ,
263+ actions : uw:: _Unwind_Action ,
264+ exception_class : uw:: _Unwind_Exception_Class ,
265+ ue_header : * uw:: _Unwind_Exception ,
266+ context : * uw:: _Unwind_Context )
267+ -> uw:: _Unwind_Reason_Code ;
268+ }
269+
270+ #[ lang="eh_personality" ]
271+ #[ no_mangle] // so we can reference it by name from middle/trans/base.rs
272+ #[ doc( hidden) ]
273+ #[ cfg( not( test) ) ]
274+ pub extern "C" fn rust_eh_personality (
275+ version : c_int ,
276+ actions : uw:: _Unwind_Action ,
277+ exception_class : uw:: _Unwind_Exception_Class ,
278+ ue_header : * uw:: _Unwind_Exception ,
279+ context : * uw:: _Unwind_Context
280+ ) -> uw:: _Unwind_Reason_Code
281+ {
282+ unsafe {
283+ __gcc_personality_v0 ( version, actions, exception_class, ue_header,
284+ context)
285+ }
286+ }
287+
288+ #[ no_mangle] // referenced from rust_try.ll
289+ #[ doc( hidden) ]
290+ #[ cfg( not( test) ) ]
291+ pub extern "C" fn rust_eh_personality_catch (
292+ version : c_int ,
293+ actions : uw:: _Unwind_Action ,
294+ exception_class : uw:: _Unwind_Exception_Class ,
295+ ue_header : * uw:: _Unwind_Exception ,
296+ context : * uw:: _Unwind_Context
297+ ) -> uw:: _Unwind_Reason_Code
298+ {
299+ if ( actions as c_int & uw:: _UA_SEARCH_PHASE as c_int ) != 0 { // search phase
300+ uw:: _URC_HANDLER_FOUND // catch!
301+ }
302+ else { // cleanup phase
303+ unsafe {
304+ __gcc_personality_v0 ( version, actions, exception_class, ue_header,
305+ context)
306+ }
307+ }
269308 }
270309}
271310
272- #[ no_mangle] // referenced from rust_try.ll
273- #[ doc( hidden) ]
274- #[ cfg( not( test) ) ]
275- pub extern "C" fn rust_eh_personality_catch (
276- version : c_int ,
277- actions : uw:: _Unwind_Action ,
278- exception_class : uw:: _Unwind_Exception_Class ,
279- ue_header : * uw:: _Unwind_Exception ,
280- context : * uw:: _Unwind_Context
281- ) -> uw:: _Unwind_Reason_Code
282- {
283- if ( actions as c_int & uw:: _UA_SEARCH_PHASE as c_int ) != 0 { // search phase
284- uw:: _URC_HANDLER_FOUND // catch!
311+ // ARM EHABI uses a slightly different personality routine signature,
312+ // but otherwise works the same.
313+ #[ cfg( target_os = "android" ) ]
314+ pub mod eabi {
315+ use uw = super :: libunwind;
316+ use libc:: c_int;
317+
318+ extern "C" {
319+ fn __gcc_personality_v0 ( state : uw:: _Unwind_State ,
320+ ue_header : * uw:: _Unwind_Exception ,
321+ context : * uw:: _Unwind_Context )
322+ -> uw:: _Unwind_Reason_Code ;
285323 }
286- else { // cleanup phase
324+
325+ #[ lang="eh_personality" ]
326+ #[ no_mangle] // so we can reference it by name from middle/trans/base.rs
327+ #[ doc( hidden) ]
328+ #[ cfg( not( test) ) ]
329+ pub extern "C" fn rust_eh_personality (
330+ state : uw:: _Unwind_State ,
331+ ue_header : * uw:: _Unwind_Exception ,
332+ context : * uw:: _Unwind_Context
333+ ) -> uw:: _Unwind_Reason_Code
334+ {
287335 unsafe {
288- __gcc_personality_v0 ( version, actions, exception_class, ue_header,
289- context)
336+ __gcc_personality_v0 ( state, ue_header, context)
337+ }
338+ }
339+
340+ #[ no_mangle] // referenced from rust_try.ll
341+ #[ doc( hidden) ]
342+ #[ cfg( not( test) ) ]
343+ pub extern "C" fn rust_eh_personality_catch (
344+ state : uw:: _Unwind_State ,
345+ ue_header : * uw:: _Unwind_Exception ,
346+ context : * uw:: _Unwind_Context
347+ ) -> uw:: _Unwind_Reason_Code
348+ {
349+ if ( state as c_int & uw:: _US_ACTION_MASK as c_int )
350+ == uw:: _US_VIRTUAL_UNWIND_FRAME as c_int { // search phase
351+ uw:: _URC_HANDLER_FOUND // catch!
352+ }
353+ else { // cleanup phase
354+ unsafe {
355+ __gcc_personality_v0 ( state, ue_header, context)
356+ }
290357 }
291358 }
292359}
0 commit comments