Changes in libcfa/src/exception.c [851fd92:3b9c674]
- File:
-
- 1 edited
-
libcfa/src/exception.c (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/exception.c
r851fd92 r3b9c674 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : T ue Apr 14 12:01:00 202013 // Update Count : 1 811 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 22 18:17:34 2018 13 // Update Count : 11 14 14 // 15 15 16 // Normally we would get this from the CFA prelude.17 16 #include <stddef.h> // for size_t 18 17 19 18 #include "exception.h" 20 19 21 // Implementation of the secret header is hardware dependent. 22 #if !( defined( __x86_64 ) || defined( __i386 ) ) 23 #error Exception Handling: No known architecture detected. 24 #endif 20 // Implementation of the secret header. 25 21 26 22 #include <stdlib.h> … … 28 24 #include <unwind.h> 29 25 #include <bits/debug.hfa> 30 #include "stdhdr/assert.h"31 26 32 27 // FIX ME: temporary hack to keep ARM build working 33 28 #ifndef _URC_FATAL_PHASE1_ERROR 34 #define _URC_FATAL_PHASE1_ERROR 329 #define _URC_FATAL_PHASE1_ERROR 2 35 30 #endif // ! _URC_FATAL_PHASE1_ERROR 36 31 #ifndef _URC_FATAL_PHASE2_ERROR … … 40 35 #include "lsda.h" 41 36 42 /* The exception class for our exceptions. Because of the vendor component43 * its value would not be standard.44 * Vendor: UWPL45 * Language: CFA\046 */47 const _Unwind_Exception_Class __cfaehm_exception_class = 0x4c50575500414643;48 37 49 38 // Base exception vtable is abstract, you should not have base exceptions. 50 struct __cfa ehm_base_exception_t_vtable51 ___cfa ehm_base_exception_t_vtable_instance = {39 struct __cfaabi_ehm__base_exception_t_vtable 40 ___cfaabi_ehm__base_exception_t_vtable_instance = { 52 41 .parent = NULL, 53 42 .size = 0, … … 60 49 // Temperary global exception context. Does not work with concurency. 61 50 struct exception_context_t { 62 struct __cfaehm_try_resume_node * top_resume; 63 64 exception_t * current_exception; 65 int current_handler_index; 66 } static shared_stack = {NULL, NULL, 0}; 51 struct __cfaabi_ehm__try_resume_node * top_resume; 52 struct __cfaabi_ehm__try_resume_node * current_resume; 53 54 exception_t * current_exception; 55 int current_handler_index; 56 } shared_stack = {NULL, NULL, 0, 0}; 67 57 68 58 // Get the current exception context. … … 72 62 return &shared_stack; 73 63 } 64 //#define SAVE_EXCEPTION_CONTEXT(to_name) 65 //struct exception_context_t * to_name = this_exception_context(); 66 //exception * this_exception() { 67 // return this_exception_context()->current_exception; 68 //} 69 70 71 // This macro should be the only thing that needs to change across machines. 72 // Used in the personality function, way down in termination. 73 // struct _Unwind_Context * -> _Unwind_Reason_Code(*)(exception_t *) 74 #define MATCHER_FROM_CONTEXT(ptr_to_context) \ 75 (*(_Unwind_Reason_Code(**)(exception_t *))(_Unwind_GetCFA(ptr_to_context) + 8)) 74 76 75 77 76 78 // RESUMPTION ================================================================ 77 79 78 static void reset_top_resume(struct __cfaehm_try_resume_node ** store) { 79 this_exception_context()->top_resume = *store; 80 } 81 82 void __cfaehm_throw_resume(exception_t * except) { 83 struct exception_context_t * context = this_exception_context(); 84 85 __cfadbg_print_safe(exception, "Throwing resumption exception\n"); 86 87 __attribute__((cleanup(reset_top_resume))) 88 struct __cfaehm_try_resume_node * original_head = context->top_resume; 89 struct __cfaehm_try_resume_node * current = context->top_resume; 80 void __cfaabi_ehm__throw_resume(exception_t * except) { 81 82 __cfaabi_dbg_print_safe("Throwing resumption exception\n"); 83 84 struct __cfaabi_ehm__try_resume_node * original_head = shared_stack.current_resume; 85 struct __cfaabi_ehm__try_resume_node * current = 86 (original_head) ? original_head->next : shared_stack.top_resume; 90 87 91 88 for ( ; current ; current = current->next) { 92 context->top_resume = current->next;89 shared_stack.current_resume = current; 93 90 if (current->handler(except)) { 91 shared_stack.current_resume = original_head; 94 92 return; 95 93 } 96 94 } 97 95 98 __cfadbg_print_safe(exception, "Unhandled exception\n"); 96 __cfaabi_dbg_print_safe("Unhandled exception\n"); 97 shared_stack.current_resume = original_head; 99 98 100 99 // Fall back to termination: 101 __cfa ehm_throw_terminate(except);100 __cfaabi_ehm__throw_terminate(except); 102 101 // TODO: Default handler for resumption. 103 102 } … … 107 106 // be added after the node is built but before it is made the top node. 108 107 109 void __cfa ehm_try_resume_setup(struct __cfaehm_try_resume_node * node,108 void __cfaabi_ehm__try_resume_setup(struct __cfaabi_ehm__try_resume_node * node, 110 109 _Bool (*handler)(exception_t * except)) { 111 struct exception_context_t * context = this_exception_context(); 112 node->next = context->top_resume; 110 node->next = shared_stack.top_resume; 113 111 node->handler = handler; 114 context->top_resume = node; 115 } 116 117 void __cfaehm_try_resume_cleanup(struct __cfaehm_try_resume_node * node) { 118 struct exception_context_t * context = this_exception_context(); 119 context->top_resume = node->next; 112 shared_stack.top_resume = node; 113 } 114 115 void __cfaabi_ehm__try_resume_cleanup(struct __cfaabi_ehm__try_resume_node * node) { 116 shared_stack.top_resume = node->next; 120 117 } 121 118 … … 126 123 // May have to move to cfa for constructors and destructors (references). 127 124 128 // How to clean up an exception in various situations. 129 static void __cfaehm_exception_cleanup( 130 _Unwind_Reason_Code reason, 131 struct _Unwind_Exception * exception) { 132 switch (reason) { 133 case _URC_FOREIGN_EXCEPTION_CAUGHT: 134 // This one we could clean-up to allow cross-language exceptions. 135 case _URC_FATAL_PHASE1_ERROR: 136 case _URC_FATAL_PHASE2_ERROR: 137 default: 138 abort(); 139 } 140 } 141 142 // We need a piece of storage to raise the exception, for now its a single 143 // piece. 144 static struct _Unwind_Exception this_exception_storage; 145 146 struct __cfaehm_node { 147 struct __cfaehm_node * next; 125 struct __cfaabi_ehm__node { 126 struct __cfaabi_ehm__node * next; 148 127 }; 149 128 150 129 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node))) 151 #define EXCEPT_TO_NODE(except) ((struct __cfa ehm_node *)(except) - 1)130 #define EXCEPT_TO_NODE(except) ((struct __cfaabi_ehm__node *)(except) - 1) 152 131 153 132 // Creates a copy of the indicated exception and sets current_exception to it. 154 static void __cfa ehm_allocate_exception( exception_t * except ) {133 static void __cfaabi_ehm__allocate_exception( exception_t * except ) { 155 134 struct exception_context_t * context = this_exception_context(); 156 135 157 136 // Allocate memory for the exception. 158 struct __cfa ehm_node * store = malloc(159 sizeof( struct __cfa ehm_node ) + except->virtual_table->size );137 struct __cfaabi_ehm__node * store = malloc( 138 sizeof( struct __cfaabi_ehm__node ) + except->virtual_table->size ); 160 139 161 140 if ( ! store ) { … … 170 149 // Copy the exception to storage. 171 150 except->virtual_table->copy( context->current_exception, except ); 172 173 // Set up the exception storage.174 this_exception_storage.exception_class = __cfaehm_exception_class;175 this_exception_storage.exception_cleanup = __cfaehm_exception_cleanup;176 151 } 177 152 178 153 // Delete the provided exception, unsetting current_exception if relivant. 179 static void __cfa ehm_delete_exception( exception_t * except ) {154 static void __cfaabi_ehm__delete_exception( exception_t * except ) { 180 155 struct exception_context_t * context = this_exception_context(); 181 156 182 __cfa dbg_print_safe(exception,"Deleting Exception\n");157 __cfaabi_dbg_print_safe("Deleting Exception\n"); 183 158 184 159 // Remove the exception from the list. 185 struct __cfa ehm_node * to_free = EXCEPT_TO_NODE(except);186 struct __cfa ehm_node * node;160 struct __cfaabi_ehm__node * to_free = EXCEPT_TO_NODE(except); 161 struct __cfaabi_ehm__node * node; 187 162 188 163 if ( context->current_exception == except ) { … … 192 167 node = EXCEPT_TO_NODE(context->current_exception); 193 168 // It may always be in the first or second position. 194 while ( to_free != node->next ) {169 while( to_free != node->next ) { 195 170 node = node->next; 196 171 } … … 204 179 205 180 // If this isn't a rethrow (*except==0), delete the provided exception. 206 void __cfaehm_cleanup_terminate( void * except ) { 207 if ( *(void**)except ) __cfaehm_delete_exception( *(exception_t **)except ); 208 } 181 void __cfaabi_ehm__cleanup_terminate( void * except ) { 182 if ( *(void**)except ) __cfaabi_ehm__delete_exception( *(exception_t **)except ); 183 } 184 185 186 // We need a piece of storage to raise the exception 187 struct _Unwind_Exception this_exception_storage; 209 188 210 189 // Function needed by force unwind … … 213 192 int version, 214 193 _Unwind_Action actions, 215 _Unwind_Exception_Class exception _class,194 _Unwind_Exception_Class exceptionClass, 216 195 struct _Unwind_Exception * unwind_exception, 217 struct _Unwind_Context * unwind_context, 218 void * stop_param) { 219 // Verify actions follow the rules we expect. 220 verify((actions & _UA_CLEANUP_PHASE) && (actions & _UA_FORCE_UNWIND)); 221 verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDER_FRAME))); 222 223 if ( actions & _UA_END_OF_STACK ) { 224 exit(1); 225 } else { 226 return _URC_NO_REASON; 227 } 196 struct _Unwind_Context * context, 197 void * some_param) { 198 if( actions & _UA_END_OF_STACK ) exit(1); 199 if( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON; 200 201 return _URC_FATAL_PHASE2_ERROR; 228 202 } 229 203 230 204 // The exception that is being thrown must already be stored. 231 static __attribute__((noreturn)) void __cfaehm_begin_unwind(void) {205 __attribute__((noreturn)) void __cfaabi_ehm__begin_unwind(void) { 232 206 if ( ! this_exception_context()->current_exception ) { 233 207 printf("UNWIND ERROR missing exception in begin unwind\n"); 234 208 abort(); 235 209 } 210 236 211 237 212 // Call stdlibc to raise the exception … … 245 220 // the whole stack. 246 221 247 if ( ret == _URC_END_OF_STACK ) {222 if( ret == _URC_END_OF_STACK ) { 248 223 // No proper handler was found. This can be handled in many ways, C++ calls std::terminate. 249 224 // Here we force unwind the stack, basically raising a cancellation. … … 260 235 } 261 236 262 void __cfaehm_throw_terminate( exception_t * val ) { 263 __cfadbg_print_safe(exception, "Throwing termination exception\n"); 264 265 __cfaehm_allocate_exception( val ); 266 __cfaehm_begin_unwind(); 267 } 268 269 void __cfaehm_rethrow_terminate(void) { 270 __cfadbg_print_safe(exception, "Rethrowing termination exception\n"); 271 272 __cfaehm_begin_unwind(); 273 } 237 void __cfaabi_ehm__throw_terminate( exception_t * val ) { 238 __cfaabi_dbg_print_safe("Throwing termination exception\n"); 239 240 __cfaabi_ehm__allocate_exception( val ); 241 __cfaabi_ehm__begin_unwind(); 242 } 243 244 void __cfaabi_ehm__rethrow_terminate(void) { 245 __cfaabi_dbg_print_safe("Rethrowing termination exception\n"); 246 247 __cfaabi_ehm__begin_unwind(); 248 } 249 250 #pragma GCC push_options 251 #pragma GCC optimize("O0") 274 252 275 253 // This is our personality routine. For every stack frame annotated with 276 254 // ".cfi_personality 0x3,__gcfa_personality_v0" this function will be called twice when unwinding. 277 255 // Once in the search phase and once in the cleanup phase. 278 _Unwind_Reason_Code __gcfa_personality_v0( 279 int version, 280 _Unwind_Action actions, 281 unsigned long long exception_class, 282 struct _Unwind_Exception * unwind_exception, 283 struct _Unwind_Context * unwind_context) 256 _Unwind_Reason_Code __gcfa_personality_v0 ( 257 int version, _Unwind_Action actions, unsigned long long exceptionClass, 258 struct _Unwind_Exception* unwind_exception, 259 struct _Unwind_Context* context) 284 260 { 285 261 286 //__cfadbg_print_safe(exception, "CFA: 0x%lx\n", _Unwind_GetCFA(context)); 287 __cfadbg_print_safe(exception, "Personality function (%d, %x, %llu, %p, %p):", 288 version, actions, exception_class, unwind_exception, unwind_context); 289 290 // Verify that actions follow the rules we expect. 291 // This function should never be called at the end of the stack. 292 verify(!(actions & _UA_END_OF_STACK)); 293 // Either only the search phase flag is set or... 262 //__cfaabi_dbg_print_safe("CFA: 0x%lx\n", _Unwind_GetCFA(context)); 263 __cfaabi_dbg_print_safe("Personality function (%d, %x, %llu, %p, %p):", 264 version, actions, exceptionClass, unwind_exception, context); 265 266 // If we've reached the end of the stack then there is nothing much we can do... 267 if( actions & _UA_END_OF_STACK ) return _URC_END_OF_STACK; 268 294 269 if (actions & _UA_SEARCH_PHASE) { 295 verify(actions == _UA_SEARCH_PHASE); 296 __cfadbg_print_safe(exception, " lookup phase"); 297 // ... we are in clean-up phase. 298 } else { 299 verify(actions & _UA_CLEANUP_PHASE); 300 __cfadbg_print_safe(exception, " cleanup phase"); 301 // We shouldn't be the handler frame during forced unwind. 302 if (actions & _UA_HANDLER_FRAME) { 303 verify(!(actions & _UA_FORCE_UNWIND)); 304 __cfadbg_print_safe(exception, " (handler frame)"); 305 } else if (actions & _UA_FORCE_UNWIND) { 306 __cfadbg_print_safe(exception, " (force unwind)"); 307 } 270 __cfaabi_dbg_print_safe(" lookup phase"); 271 } 272 else if (actions & _UA_CLEANUP_PHASE) { 273 __cfaabi_dbg_print_safe(" cleanup phase"); 274 } 275 // Just in case, probably can't actually happen 276 else { 277 printf(" error\n"); 278 return _URC_FATAL_PHASE1_ERROR; 308 279 } 309 280 310 281 // Get a pointer to the language specific data from which we will read what we need 311 const unsigned char * lsd = _Unwind_GetLanguageSpecificData( unwind_context );312 313 if ( !lsd ) { //Nothing to do, keep unwinding282 const unsigned char * lsd = (const unsigned char*) _Unwind_GetLanguageSpecificData( context ); 283 284 if( !lsd ) { //Nothing to do, keep unwinding 314 285 printf(" no LSD"); 315 286 goto UNWIND; … … 318 289 // Get the instuction pointer and a reading pointer into the exception table 319 290 lsda_header_info lsd_info; 320 const unsigned char * cur_ptr = parse_lsda_header(unwind_context, lsd, &lsd_info); 321 _Unwind_Ptr instruction_ptr = _Unwind_GetIP(unwind_context); 322 323 struct exception_context_t * context = this_exception_context(); 291 const unsigned char * cur_ptr = parse_lsda_header(context, lsd, &lsd_info); 292 _Unwind_Ptr instruction_ptr = _Unwind_GetIP( context ); 324 293 325 294 // Linearly search the table for stuff to do 326 while ( cur_ptr < lsd_info.action_table ) {295 while( cur_ptr < lsd_info.action_table ) { 327 296 _Unwind_Ptr callsite_start; 328 297 _Unwind_Ptr callsite_len; … … 337 306 338 307 // Have we reach the correct frame info yet? 339 if ( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) {308 if( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) { 340 309 #ifdef __CFA_DEBUG_PRINT__ 341 310 void * ls = (void*)lsd_info.Start; … … 345 314 void * ep = (void*)lsd_info.Start + callsite_start + callsite_len; 346 315 void * ip = (void*)instruction_ptr; 347 __cfa dbg_print_safe(exception,"\nfound %p - %p (%p, %p, %p), looking for %p\n",316 __cfaabi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n", 348 317 bp, ep, ls, cs, cl, ip); 349 318 #endif // __CFA_DEBUG_PRINT__ … … 352 321 353 322 // Have we gone too far? 354 if ( lsd_info.Start + callsite_start > instruction_ptr ) {323 if( lsd_info.Start + callsite_start > instruction_ptr ) { 355 324 printf(" gone too far"); 356 325 break; 357 326 } 358 327 359 // Check for what we must do: 360 if ( 0 == callsite_landing_pad ) { 361 // Nothing to do, move along 362 __cfadbg_print_safe(exception, " no landing pad"); 363 } else if (actions & _UA_SEARCH_PHASE) { 364 // In search phase, these means we found a potential handler we must check. 365 366 // We have arbitrarily decided that 0 means nothing to do and 1 means there is 367 // a potential handler. This doesn't seem to conflict the gcc default behavior. 368 if (callsite_action != 0) { 369 // Now we want to run some code to see if the handler matches 370 // This is the tricky part where we want to the power to run arbitrary code 371 // However, generating a new exception table entry and try routine every time 372 // is way more expansive than we might like 373 // The information we have is : 374 // - The GR (Series of registers) 375 // GR1=GP Global Pointer of frame ref by context 376 // - The instruction pointer 377 // - The instruction pointer info (???) 378 // - The CFA (Canonical Frame Address) 379 // - The BSP (Probably the base stack pointer) 380 381 // The current apprach uses one exception table entry per try block 382 _uleb128_t imatcher; 383 // Get the relative offset to the {...}? 384 cur_ptr = read_uleb128(cur_ptr, &imatcher); 385 386 # if defined( __x86_64 ) 387 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 8; 388 # elif defined( __i386 ) 389 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 24; 390 # endif 391 int (*matcher)(exception_t *) = *(int(**)(exception_t *))match_pos; 392 393 int index = matcher(context->current_exception); 394 _Unwind_Reason_Code ret = (0 == index) 395 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 396 context->current_handler_index = index; 397 398 // Based on the return value, check if we matched the exception 399 if (ret == _URC_HANDLER_FOUND) { 400 __cfadbg_print_safe(exception, " handler found\n"); 401 } else { 402 __cfadbg_print_safe(exception, " no handler\n"); 328 // Something to do? 329 if( callsite_landing_pad ) { 330 // Which phase are we in 331 if (actions & _UA_SEARCH_PHASE) { 332 // In search phase, these means we found a potential handler we must check. 333 334 // We have arbitrarily decided that 0 means nothing to do and 1 means there is 335 // a potential handler. This doesn't seem to conflict the gcc default behavior. 336 if (callsite_action != 0) { 337 // Now we want to run some code to see if the handler matches 338 // This is the tricky part where we want to the power to run arbitrary code 339 // However, generating a new exception table entry and try routine every time 340 // is way more expansive than we might like 341 // The information we have is : 342 // - The GR (Series of registers) 343 // GR1=GP Global Pointer of frame ref by context 344 // - The instruction pointer 345 // - The instruction pointer info (???) 346 // - The CFA (Canonical Frame Address) 347 // - The BSP (Probably the base stack pointer) 348 349 350 // The current apprach uses one exception table entry per try block 351 _uleb128_t imatcher; 352 // Get the relative offset to the {...}? 353 cur_ptr = read_uleb128(cur_ptr, &imatcher); 354 355 _Unwind_Reason_Code (*matcher)(exception_t *) = 356 MATCHER_FROM_CONTEXT(context); 357 int index = matcher(shared_stack.current_exception); 358 _Unwind_Reason_Code ret = (0 == index) 359 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 360 shared_stack.current_handler_index = index; 361 362 // Based on the return value, check if we matched the exception 363 if( ret == _URC_HANDLER_FOUND) { 364 __cfaabi_dbg_print_safe(" handler found\n"); 365 } else { 366 __cfaabi_dbg_print_safe(" no handler\n"); 367 } 368 return ret; 403 369 } 404 return ret; 370 371 // This is only a cleanup handler, ignore it 372 __cfaabi_dbg_print_safe(" no action"); 405 373 } 406 407 // This is only a cleanup handler, ignore it 408 __cfadbg_print_safe(exception, " no action"); 409 } else { 410 // In clean-up phase, no destructors here but this could be the handler. 411 412 if ( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){ 413 // If this is a potential exception handler 414 // but not the one that matched the exception in the seach phase, 415 // just ignore it 416 goto UNWIND; 374 else if (actions & _UA_CLEANUP_PHASE) { 375 376 if( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){ 377 // If this is a potential exception handler 378 // but not the one that matched the exception in the seach phase, 379 // just ignore it 380 goto UNWIND; 381 } 382 383 // We need to run some clean-up or a handler 384 // These statment do the right thing but I don't know any specifics at all 385 _Unwind_SetGR( context, __builtin_eh_return_data_regno(0), (_Unwind_Ptr) unwind_exception ); 386 _Unwind_SetGR( context, __builtin_eh_return_data_regno(1), 0 ); 387 388 // I assume this sets the instruction pointer to the adress of the landing pad 389 // It doesn't actually set it, it only state the value that needs to be set once we return _URC_INSTALL_CONTEXT 390 _Unwind_SetIP( context, ((lsd_info.LPStart) + (callsite_landing_pad)) ); 391 392 __cfaabi_dbg_print_safe(" action\n"); 393 394 // Return have some action to run 395 return _URC_INSTALL_CONTEXT; 417 396 } 418 419 // We need to run some clean-up or a handler420 // These statment do the right thing but I don't know any specifics at all421 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(0),422 (_Unwind_Ptr)unwind_exception );423 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(1), 0 );424 425 // I assume this sets the instruction pointer to the adress of the landing pad426 // It doesn't actually set it, it only state the value that needs to be set once we427 // return _URC_INSTALL_CONTEXT428 _Unwind_SetIP( unwind_context, ((lsd_info.LPStart) + (callsite_landing_pad)) );429 430 __cfadbg_print_safe(exception, " action\n");431 432 // Return have some action to run433 return _URC_INSTALL_CONTEXT;434 397 } 398 399 // Nothing to do, move along 400 __cfaabi_dbg_print_safe(" no landing pad"); 435 401 } 436 402 // No handling found 437 __cfa dbg_print_safe(exception, " table end reached");403 __cfaabi_dbg_print_safe(" table end reached\n"); 438 404 439 405 UNWIND: 440 __cfa dbg_print_safe(exception," unwind\n");406 __cfaabi_dbg_print_safe(" unwind\n"); 441 407 442 408 // Keep unwinding the stack 443 409 return _URC_CONTINUE_UNWIND; 444 410 } 445 446 #pragma GCC push_options447 #pragma GCC optimize(0)448 411 449 412 // Try statements are hoisted out see comments for details. While this could probably be unique 450 413 // and simply linked from libcfa but there is one problem left, see the exception table for details 451 414 __attribute__((noinline)) 452 void __cfa ehm_try_terminate(void (*try_block)(),415 void __cfaabi_ehm__try_terminate(void (*try_block)(), 453 416 void (*catch_block)(int index, exception_t * except), 454 417 __attribute__((unused)) int (*match_block)(exception_t * except)) { … … 456 419 //! printf("%p %p %p %p\n", &try_block, &catch_block, &match_block, &xy); 457 420 421 // Setup statments: These 2 statments won't actually result in any code, they only setup global tables. 422 // However, they clobber gcc cancellation support from gcc. We can replace the personality routine but 423 // replacing the exception table gcc generates is not really doable, it generates labels based on how the 424 // assembly works. 425 458 426 // Setup the personality routine and exception table. 459 // Unforturnately these clobber gcc cancellation support which means we can't get access to460 // the attribute cleanup tables at the same time. We would have to inspect the assembly to461 // create a new set ourselves.462 427 #ifdef __PIC__ 463 428 asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0"); … … 484 449 // Label which defines the end of the area for which the handler is setup. 485 450 asm volatile (".TRYEND:"); 486 // Label which defines the start of the exception landing pad. Basically what is called when487 // the exception is caught. Note, if multiple handlers are given, the multiplexing should be488 // done by the generated code, not theexception runtime.451 // Label which defines the start of the exception landing pad. Basically what is called when the exception is 452 // caught. Note, if multiple handlers are given, the multiplexing should be done by the generated code, not the 453 // exception runtime. 489 454 asm volatile (".CATCH:"); 490 455 491 456 // Exception handler 492 // Note: Saving the exception context on the stack breaks termination exceptions. 493 catch_block( this_exception_context()->current_handler_index, 494 this_exception_context()->current_exception ); 457 catch_block( shared_stack.current_handler_index, 458 shared_stack.current_exception ); 495 459 } 496 460 … … 500 464 501 465 #ifdef __PIC__ 466 #if defined( __i386 ) || defined( __x86_64 ) 502 467 asm ( 503 468 // HEADER … … 516 481 // handler landing pad offset and 1 (action code, gcc seems to use 0). 517 482 ".LLSDACSBCFA2:\n" 518 " .uleb128 .TRYSTART-__cfa ehm_try_terminate\n"483 " .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n" 519 484 " .uleb128 .TRYEND-.TRYSTART\n" 520 " .uleb128 .CATCH-__cfa ehm_try_terminate\n"485 " .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n" 521 486 " .uleb128 1\n" 522 487 ".LLSDACSECFA2:\n" 523 488 // TABLE FOOTER 524 489 " .text\n" 525 " .size __cfa ehm_try_terminate, .-__cfaehm_try_terminate\n"490 " .size __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n" 526 491 ); 527 492 … … 542 507 " .quad __gcfa_personality_v0\n" 543 508 #else // then __i386 544 " .long __gcfa_personality_v0\n"509 " .long __gcfa_personality_v0\n" 545 510 #endif 546 511 ); 512 #else 513 #error Exception Handling: unknown architecture for position independent code. 514 #endif // __i386 || __x86_64 547 515 #else // __PIC__ 516 #if defined( __i386 ) || defined( __x86_64 ) 548 517 asm ( 549 518 // HEADER … … 560 529 ".LLSDACSBCFA2:\n" 561 530 // Handled area start (relative to start of function) 562 " .uleb128 .TRYSTART-__cfa ehm_try_terminate\n"531 " .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n" 563 532 // Handled area length 564 533 " .uleb128 .TRYEND-.TRYSTART\n" 565 534 // Handler landing pad address (relative to start of function) 566 " .uleb128 .CATCH-__cfa ehm_try_terminate\n"535 " .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n" 567 536 // Action code, gcc seems to always use 0. 568 537 " .uleb128 1\n" … … 570 539 ".LLSDACSECFA2:\n" 571 540 " .text\n" 572 " .size __cfa ehm_try_terminate, .-__cfaehm_try_terminate\n"541 " .size __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n" 573 542 " .ident \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n" 574 543 " .section .note.GNU-stack,\"x\",@progbits\n" 575 544 ); 545 #else 546 #error Exception Handling: unknown architecture for position dependent code. 547 #endif // __i386 || __x86_64 576 548 #endif // __PIC__ 577 549
Note:
See TracChangeset
for help on using the changeset viewer.