3535//! 
3636//! Once stack has been unwound down to the handler frame level, unwinding stops 
3737//! and the last personality routine transfers control to the catch block. 
38+ #![ forbid( unsafe_op_in_unsafe_fn) ]  
3839
3940use  super :: dwarf:: eh:: { self ,  EHAction ,  EHContext } ; 
4041use  crate :: ffi:: c_int; 
@@ -92,7 +93,11 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
9293// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c 
9394
9495cfg_if:: cfg_if! { 
95-     if  #[ cfg( all( not( all( target_vendor = "apple" ,  not( target_os = "watchos" ) ) ) ,  target_arch = "arm" ,  not( target_os = "netbsd" ) ) ) ]  { 
96+     if  #[ cfg( all( 
97+             target_arch = "arm" , 
98+             not( all( target_vendor = "apple" ,  not( target_os = "watchos" ) ) ) , 
99+             not( target_os = "netbsd" ) , 
100+         ) ) ]  { 
96101        // ARM EHABI personality routine. 
97102        // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf 
98103        // 
@@ -104,90 +109,94 @@ cfg_if::cfg_if! {
104109            exception_object:  * mut  uw:: _Unwind_Exception, 
105110            context:  * mut  uw:: _Unwind_Context, 
106111        )  -> uw:: _Unwind_Reason_Code { 
107-             let  state = state as  c_int; 
108-             let  action = state &  uw:: _US_ACTION_MASK as  c_int; 
109-             let  search_phase = if  action == uw:: _US_VIRTUAL_UNWIND_FRAME as  c_int { 
110-                 // Backtraces on ARM will call the personality routine with 
111-                 // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases 
112-                 // we want to continue unwinding the stack, otherwise all our backtraces 
113-                 // would end at __rust_try 
114-                 if  state &  uw:: _US_FORCE_UNWIND as  c_int != 0  { 
112+             unsafe  { 
113+                 let  state = state as  c_int; 
114+                 let  action = state &  uw:: _US_ACTION_MASK as  c_int; 
115+                 let  search_phase = if  action == uw:: _US_VIRTUAL_UNWIND_FRAME as  c_int { 
116+                     // Backtraces on ARM will call the personality routine with 
117+                     // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases 
118+                     // we want to continue unwinding the stack, otherwise all our backtraces 
119+                     // would end at __rust_try 
120+                     if  state &  uw:: _US_FORCE_UNWIND as  c_int != 0  { 
121+                         return  continue_unwind( exception_object,  context) ; 
122+                     } 
123+                     true 
124+                 }  else if  action == uw:: _US_UNWIND_FRAME_STARTING as  c_int { 
125+                     false 
126+                 }  else if  action == uw:: _US_UNWIND_FRAME_RESUME as  c_int { 
115127                    return  continue_unwind( exception_object,  context) ; 
116-                 } 
117-                 true 
118-             }  else if  action == uw:: _US_UNWIND_FRAME_STARTING as  c_int { 
119-                 false 
120-             }  else if  action == uw:: _US_UNWIND_FRAME_RESUME as  c_int { 
121-                 return  continue_unwind( exception_object,  context) ; 
122-             }  else { 
123-                 return  uw:: _URC_FAILURE; 
124-             } ; 
128+                 }  else { 
129+                     return  uw:: _URC_FAILURE; 
130+                 } ; 
125131
126-             // The DWARF unwinder assumes that _Unwind_Context holds things like the function 
127-             // and LSDA pointers, however ARM EHABI places them into the exception object. 
128-             // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which 
129-             // take only the context pointer, GCC personality routines stash a pointer to 
130-             // exception_object in the context, using location reserved for ARM's 
131-             // "scratch register" (r12). 
132-             uw:: _Unwind_SetGR( context,  uw:: UNWIND_POINTER_REG ,  exception_object as  uw:: _Unwind_Ptr) ; 
133-             // ...A more principled approach would be to provide the full definition of ARM's 
134-             // _Unwind_Context in our libunwind bindings and fetch the required data from there 
135-             // directly, bypassing DWARF compatibility functions. 
132+                  // The DWARF unwinder assumes that _Unwind_Context holds things like the function 
133+                  // and LSDA pointers, however ARM EHABI places them into the exception object. 
134+                  // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which 
135+                  // take only the context pointer, GCC personality routines stash a pointer to 
136+                  // exception_object in the context, using location reserved for ARM's 
137+                  // "scratch register" (r12). 
138+                  uw:: _Unwind_SetGR( context,  uw:: UNWIND_POINTER_REG ,  exception_object as  uw:: _Unwind_Ptr) ; 
139+                  // ...A more principled approach would be to provide the full definition of ARM's 
140+                  // _Unwind_Context in our libunwind bindings and fetch the required data from there 
141+                  // directly, bypassing DWARF compatibility functions. 
136142
137-             let  eh_action = match  find_eh_action( context)  { 
138-                 Ok ( action)  => action, 
139-                 Err ( _)  => return  uw:: _URC_FAILURE, 
140-             } ; 
141-             if  search_phase { 
142-                 match  eh_action { 
143-                     EHAction :: None  | EHAction :: Cleanup ( _)  => { 
144-                         return  continue_unwind( exception_object,  context) ; 
143+                 let  eh_action = match  find_eh_action( context)  { 
144+                     Ok ( action)  => action, 
145+                     Err ( _)  => return  uw:: _URC_FAILURE, 
146+                 } ; 
147+                 if  search_phase { 
148+                     match  eh_action { 
149+                         EHAction :: None  | EHAction :: Cleanup ( _)  => { 
150+                             return  continue_unwind( exception_object,  context) ; 
151+                         } 
152+                         EHAction :: Catch ( _)  | EHAction :: Filter ( _)  => { 
153+                             // EHABI requires the personality routine to update the 
154+                             // SP value in the barrier cache of the exception object. 
155+                             ( * exception_object) . private[ 5 ]  =
156+                                 uw:: _Unwind_GetGR( context,  uw:: UNWIND_SP_REG ) ; 
157+                             return  uw:: _URC_HANDLER_FOUND; 
158+                         } 
159+                         EHAction :: Terminate  => return  uw:: _URC_FAILURE, 
145160                    } 
146-                     EHAction :: Catch ( _)  | EHAction :: Filter ( _)  => { 
147-                         // EHABI requires the personality routine to update the 
148-                         // SP value in the barrier cache of the exception object. 
149-                         ( * exception_object) . private[ 5 ]  =
150-                             uw:: _Unwind_GetGR( context,  uw:: UNWIND_SP_REG ) ; 
151-                         return  uw:: _URC_HANDLER_FOUND; 
152-                     } 
153-                     EHAction :: Terminate  => return  uw:: _URC_FAILURE, 
154-                 } 
155-             }  else { 
156-                 match  eh_action { 
157-                     EHAction :: None  => return  continue_unwind( exception_object,  context) , 
158-                     EHAction :: Filter ( _)  if  state &  uw:: _US_FORCE_UNWIND as  c_int != 0  => return  continue_unwind( exception_object,  context) , 
159-                     EHAction :: Cleanup ( lpad)  | EHAction :: Catch ( lpad)  | EHAction :: Filter ( lpad)  => { 
160-                         uw:: _Unwind_SetGR( 
161-                             context, 
162-                             UNWIND_DATA_REG . 0 , 
163-                             exception_object as  uw:: _Unwind_Ptr, 
164-                         ) ; 
165-                         uw:: _Unwind_SetGR( context,  UNWIND_DATA_REG . 1 ,  core:: ptr:: null( ) ) ; 
166-                         uw:: _Unwind_SetIP( context,  lpad) ; 
167-                         return  uw:: _URC_INSTALL_CONTEXT; 
161+                 }  else { 
162+                     match  eh_action { 
163+                         EHAction :: None  => return  continue_unwind( exception_object,  context) , 
164+                         EHAction :: Filter ( _)  if  state &  uw:: _US_FORCE_UNWIND as  c_int != 0  => return  continue_unwind( exception_object,  context) , 
165+                         EHAction :: Cleanup ( lpad)  | EHAction :: Catch ( lpad)  | EHAction :: Filter ( lpad)  => { 
166+                             uw:: _Unwind_SetGR( 
167+                                 context, 
168+                                 UNWIND_DATA_REG . 0 , 
169+                                 exception_object as  uw:: _Unwind_Ptr, 
170+                             ) ; 
171+                             uw:: _Unwind_SetGR( context,  UNWIND_DATA_REG . 1 ,  core:: ptr:: null( ) ) ; 
172+                             uw:: _Unwind_SetIP( context,  lpad) ; 
173+                             return  uw:: _URC_INSTALL_CONTEXT; 
174+                         } 
175+                         EHAction :: Terminate  => return  uw:: _URC_FAILURE, 
168176                    } 
169-                     EHAction :: Terminate  => return  uw:: _URC_FAILURE, 
170177                } 
171-             } 
172178
173-             // On ARM EHABI the personality routine is responsible for actually 
174-             // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). 
175-             unsafe  fn  continue_unwind( 
176-                 exception_object:  * mut  uw:: _Unwind_Exception, 
177-                 context:  * mut  uw:: _Unwind_Context, 
178-             )  -> uw:: _Unwind_Reason_Code { 
179-                 if  __gnu_unwind_frame( exception_object,  context)  == uw:: _URC_NO_REASON { 
180-                     uw:: _URC_CONTINUE_UNWIND
181-                 }  else { 
182-                     uw:: _URC_FAILURE
183-                 } 
184-             } 
185-             // defined in libgcc 
186-             extern "C"  { 
187-                 fn  __gnu_unwind_frame( 
179+                 // On ARM EHABI the personality routine is responsible for actually 
180+                 // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). 
181+                 unsafe  fn  continue_unwind( 
188182                    exception_object:  * mut  uw:: _Unwind_Exception, 
189183                    context:  * mut  uw:: _Unwind_Context, 
190-                 )  -> uw:: _Unwind_Reason_Code; 
184+                 )  -> uw:: _Unwind_Reason_Code { 
185+                     unsafe  { 
186+                         if  __gnu_unwind_frame( exception_object,  context)  == uw:: _URC_NO_REASON { 
187+                             uw:: _URC_CONTINUE_UNWIND
188+                         }  else { 
189+                             uw:: _URC_FAILURE
190+                         } 
191+                     } 
192+                 } 
193+                 // defined in libgcc 
194+                 extern "C"  { 
195+                     fn  __gnu_unwind_frame( 
196+                         exception_object:  * mut  uw:: _Unwind_Exception, 
197+                         context:  * mut  uw:: _Unwind_Context, 
198+                     )  -> uw:: _Unwind_Reason_Code; 
199+                 } 
191200            } 
192201        } 
193202    }  else { 
@@ -200,35 +209,37 @@ cfg_if::cfg_if! {
200209            exception_object:  * mut  uw:: _Unwind_Exception, 
201210            context:  * mut  uw:: _Unwind_Context, 
202211        )  -> uw:: _Unwind_Reason_Code { 
203-             if  version != 1  { 
204-                 return  uw:: _URC_FATAL_PHASE1_ERROR; 
205-             } 
206-             let  eh_action = match  find_eh_action( context)  { 
207-                 Ok ( action)  => action, 
208-                 Err ( _)  => return  uw:: _URC_FATAL_PHASE1_ERROR, 
209-             } ; 
210-             if  actions as  i32  &  uw:: _UA_SEARCH_PHASE as  i32  != 0  { 
211-                 match  eh_action { 
212-                     EHAction :: None  | EHAction :: Cleanup ( _)  => uw:: _URC_CONTINUE_UNWIND, 
213-                     EHAction :: Catch ( _)  | EHAction :: Filter ( _)  => uw:: _URC_HANDLER_FOUND, 
214-                     EHAction :: Terminate  => uw:: _URC_FATAL_PHASE1_ERROR, 
212+             unsafe  { 
213+                 if  version != 1  { 
214+                     return  uw:: _URC_FATAL_PHASE1_ERROR; 
215215                } 
216-             }  else { 
217-                 match  eh_action { 
218-                     EHAction :: None  => uw:: _URC_CONTINUE_UNWIND, 
219-                     // Forced unwinding hits a terminate action. 
220-                     EHAction :: Filter ( _)  if  actions as  i32  &  uw:: _UA_FORCE_UNWIND as  i32  != 0  => uw:: _URC_CONTINUE_UNWIND, 
221-                     EHAction :: Cleanup ( lpad)  | EHAction :: Catch ( lpad)  | EHAction :: Filter ( lpad)  => { 
222-                         uw:: _Unwind_SetGR( 
223-                             context, 
224-                             UNWIND_DATA_REG . 0 , 
225-                             exception_object. cast( ) , 
226-                         ) ; 
227-                         uw:: _Unwind_SetGR( context,  UNWIND_DATA_REG . 1 ,  core:: ptr:: null( ) ) ; 
228-                         uw:: _Unwind_SetIP( context,  lpad) ; 
229-                         uw:: _URC_INSTALL_CONTEXT
216+                 let  eh_action = match  find_eh_action( context)  { 
217+                     Ok ( action)  => action, 
218+                     Err ( _)  => return  uw:: _URC_FATAL_PHASE1_ERROR, 
219+                 } ; 
220+                 if  actions as  i32  &  uw:: _UA_SEARCH_PHASE as  i32  != 0  { 
221+                     match  eh_action { 
222+                         EHAction :: None  | EHAction :: Cleanup ( _)  => uw:: _URC_CONTINUE_UNWIND, 
223+                         EHAction :: Catch ( _)  | EHAction :: Filter ( _)  => uw:: _URC_HANDLER_FOUND, 
224+                         EHAction :: Terminate  => uw:: _URC_FATAL_PHASE1_ERROR, 
225+                     } 
226+                 }  else { 
227+                     match  eh_action { 
228+                         EHAction :: None  => uw:: _URC_CONTINUE_UNWIND, 
229+                         // Forced unwinding hits a terminate action. 
230+                         EHAction :: Filter ( _)  if  actions as  i32  &  uw:: _UA_FORCE_UNWIND as  i32  != 0  => uw:: _URC_CONTINUE_UNWIND, 
231+                         EHAction :: Cleanup ( lpad)  | EHAction :: Catch ( lpad)  | EHAction :: Filter ( lpad)  => { 
232+                             uw:: _Unwind_SetGR( 
233+                                 context, 
234+                                 UNWIND_DATA_REG . 0 , 
235+                                 exception_object. cast( ) , 
236+                             ) ; 
237+                             uw:: _Unwind_SetGR( context,  UNWIND_DATA_REG . 1 ,  core:: ptr:: null( ) ) ; 
238+                             uw:: _Unwind_SetIP( context,  lpad) ; 
239+                             uw:: _URC_INSTALL_CONTEXT
240+                         } 
241+                         EHAction :: Terminate  => uw:: _URC_FATAL_PHASE2_ERROR, 
230242                    } 
231-                     EHAction :: Terminate  => uw:: _URC_FATAL_PHASE2_ERROR, 
232243                } 
233244            } 
234245        } 
@@ -245,13 +256,15 @@ cfg_if::cfg_if! {
245256                    contextRecord:  * mut  uw:: CONTEXT , 
246257                    dispatcherContext:  * mut  uw:: DISPATCHER_CONTEXT , 
247258                )  -> uw:: EXCEPTION_DISPOSITION  { 
248-                     uw:: _GCC_specific_handler( 
249-                         exceptionRecord, 
250-                         establisherFrame, 
251-                         contextRecord, 
252-                         dispatcherContext, 
253-                         rust_eh_personality_impl, 
254-                     ) 
259+                     unsafe  { 
260+                         uw:: _GCC_specific_handler( 
261+                             exceptionRecord, 
262+                             establisherFrame, 
263+                             contextRecord, 
264+                             dispatcherContext, 
265+                             rust_eh_personality_impl, 
266+                         ) 
267+                     } 
255268                } 
256269            }  else { 
257270                // The personality routine for most of our targets. 
@@ -263,32 +276,36 @@ cfg_if::cfg_if! {
263276                    exception_object:  * mut  uw:: _Unwind_Exception, 
264277                    context:  * mut  uw:: _Unwind_Context, 
265278                )  -> uw:: _Unwind_Reason_Code { 
266-                     rust_eh_personality_impl( 
267-                         version, 
268-                         actions, 
269-                         exception_class, 
270-                         exception_object, 
271-                         context, 
272-                     ) 
279+                     unsafe  { 
280+                         rust_eh_personality_impl( 
281+                             version, 
282+                             actions, 
283+                             exception_class, 
284+                             exception_object, 
285+                             context, 
286+                         ) 
287+                     } 
273288                } 
274289            } 
275290        } 
276291    } 
277292} 
278293
279294unsafe  fn  find_eh_action ( context :  * mut  uw:: _Unwind_Context )  -> Result < EHAction ,  ( ) >  { 
280-     let  lsda = uw:: _Unwind_GetLanguageSpecificData ( context)  as  * const  u8 ; 
281-     let  mut  ip_before_instr:  c_int  = 0 ; 
282-     let  ip = uw:: _Unwind_GetIPInfo ( context,  & mut  ip_before_instr) ; 
283-     let  eh_context = EHContext  { 
284-         // The return address points 1 byte past the call instruction, 
285-         // which could be in the next IP range in LSDA range table. 
286-         // 
287-         // `ip = -1` has special meaning, so use wrapping sub to allow for that 
288-         ip :  if  ip_before_instr != 0  {  ip }  else  {  ip. wrapping_sub ( 1 )  } , 
289-         func_start :  uw:: _Unwind_GetRegionStart ( context) , 
290-         get_text_start :  & || uw:: _Unwind_GetTextRelBase ( context) , 
291-         get_data_start :  & || uw:: _Unwind_GetDataRelBase ( context) , 
292-     } ; 
293-     eh:: find_eh_action ( lsda,  & eh_context) 
295+     unsafe  { 
296+         let  lsda = uw:: _Unwind_GetLanguageSpecificData ( context)  as  * const  u8 ; 
297+         let  mut  ip_before_instr:  c_int  = 0 ; 
298+         let  ip = uw:: _Unwind_GetIPInfo ( context,  & mut  ip_before_instr) ; 
299+         let  eh_context = EHContext  { 
300+             // The return address points 1 byte past the call instruction, 
301+             // which could be in the next IP range in LSDA range table. 
302+             // 
303+             // `ip = -1` has special meaning, so use wrapping sub to allow for that 
304+             ip :  if  ip_before_instr != 0  {  ip }  else  {  ip. wrapping_sub ( 1 )  } , 
305+             func_start :  uw:: _Unwind_GetRegionStart ( context) , 
306+             get_text_start :  & || uw:: _Unwind_GetTextRelBase ( context) , 
307+             get_data_start :  & || uw:: _Unwind_GetDataRelBase ( context) , 
308+         } ; 
309+         eh:: find_eh_action ( lsda,  & eh_context) 
310+     } 
294311} 
0 commit comments