Changeset b7d6a36 for libcfa/src/exception.c
- Timestamp:
- Feb 20, 2020, 4:15:51 PM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 6a490b2
- Parents:
- dca5802 (diff), 2cbfe92 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/exception.c
rdca5802 rb7d6a36 69 69 70 70 71 // This macro should be the only thing that needs to change across machines. Used in the personality function, way down72 // in termination.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 73 // struct _Unwind_Context * -> _Unwind_Reason_Code(*)(exception_t *) 74 74 #define MATCHER_FROM_CONTEXT(ptr_to_context) \ … … 102 102 } 103 103 104 // Do we control where exceptions get thrown even with concurency? If not these are not quite thread safe, the cleanup 105 // hook has to be added after the node is built but before it is made the top node. 104 // Do we control where exceptions get thrown even with concurency? 105 // If not these are not quite thread safe, the cleanup hook has to 106 // be added after the node is built but before it is made the top node. 106 107 107 108 void __cfaabi_ehm__try_resume_setup(struct __cfaabi_ehm__try_resume_node * node, … … 212 213 _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage ); 213 214 214 // If we reach here it means something happened. For resumption to work we need to find a way to return back to 215 // here. Most of them will probably boil down to setting a global flag and making the phase 1 either stop or 216 // fail. Causing an error on purpose may help avoiding unnecessary work but it might have some weird side 217 // effects. If we just pretend no handler was found that would work but may be expensive for no reason since we 218 // will always search the whole stack. 215 // If we reach here it means something happened. For resumption to work we need to find a way 216 // to return back to here. Most of them will probably boil down to setting a global flag and 217 // making the phase 1 either stop or fail. Causing an error on purpose may help avoiding 218 // unnecessary work but it might have some weird side effects. If we just pretend no handler 219 // was found that would work but may be expensive for no reason since we will always search 220 // the whole stack. 219 221 220 222 if( ret == _URC_END_OF_STACK ) { 221 // No proper handler was found. This can be handled in several way. C++ calls std::terminate Here we222 // force unwind the stack, basically raising a cancellation.223 // No proper handler was found. This can be handled in many ways, C++ calls std::terminate. 224 // Here we force unwind the stack, basically raising a cancellation. 223 225 printf("Uncaught exception %p\n", &this_exception_storage); 224 226 … … 228 230 } 229 231 230 // We did not simply reach the end of the stack without finding a handler. Something wen't wrong232 // We did not simply reach the end of the stack without finding a handler. This is an error. 231 233 printf("UNWIND ERROR %d after raise exception\n", ret); 232 234 abort(); … … 246 248 } 247 249 248 #if defined(PIC) 249 #warning Exceptions not yet supported when using Position-Independent Code 250 __attribute__((noinline)) 251 void __cfaabi_ehm__try_terminate(void (*try_block)(), 252 void (*catch_block)(int index, exception_t * except), 253 __attribute__((unused)) int (*match_block)(exception_t * except)) { 254 abort(); 255 } 256 #else 257 // This is our personality routine. For every stack frame anotated with ".cfi_personality 0x3,__gcfa_personality_v0". 258 // This function will be called twice when unwinding. Once in the search phased and once in the cleanup phase. 250 #pragma GCC push_options 251 #pragma GCC optimize("O0") 252 253 // This is our personality routine. For every stack frame annotated with 254 // ".cfi_personality 0x3,__gcfa_personality_v0" this function will be called twice when unwinding. 255 // Once in the search phase and once in the cleanup phase. 259 256 _Unwind_Reason_Code __gcfa_personality_v0 ( 260 257 int version, _Unwind_Action actions, unsigned long long exceptionClass, … … 264 261 265 262 //__cfaabi_dbg_print_safe("CFA: 0x%lx\n", _Unwind_GetCFA(context)); 266 __cfaabi_dbg_print_safe("Personality function (%d, %x, %llu, %p, %p):", version, actions, exceptionClass, unwind_exception, context); 263 __cfaabi_dbg_print_safe("Personality function (%d, %x, %llu, %p, %p):", 264 version, actions, exceptionClass, unwind_exception, context); 267 265 268 266 // If we've reached the end of the stack then there is nothing much we can do... … … 291 289 // Get the instuction pointer and a reading pointer into the exception table 292 290 lsda_header_info lsd_info; 293 const unsigned char * cur_ptr = parse_lsda_header( 291 const unsigned char * cur_ptr = parse_lsda_header(context, lsd, &lsd_info); 294 292 _Unwind_Ptr instruction_ptr = _Unwind_GetIP( context ); 295 293 … … 302 300 303 301 // Decode the common stuff we have in here 304 cur_ptr = read_encoded_value 305 cur_ptr = read_encoded_value 306 cur_ptr = read_encoded_value 307 cur_ptr = read_uleb128 302 cur_ptr = read_encoded_value(0, lsd_info.call_site_encoding, cur_ptr, &callsite_start); 303 cur_ptr = read_encoded_value(0, lsd_info.call_site_encoding, cur_ptr, &callsite_len); 304 cur_ptr = read_encoded_value(0, lsd_info.call_site_encoding, cur_ptr, &callsite_landing_pad); 305 cur_ptr = read_uleb128(cur_ptr, &callsite_action); 308 306 309 307 // Have we reach the correct frame info yet? … … 316 314 void * ep = (void*)lsd_info.Start + callsite_start + callsite_len; 317 315 void * ip = (void*)instruction_ptr; 318 __cfaabi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n", bp, ep, ls, cs, cl, ip); 316 __cfaabi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n", 317 bp, ep, ls, cs, cl, ip); 319 318 #endif // __CFA_DEBUG_PRINT__ 320 319 continue; 321 320 } 322 321 323 // Have we gone too far 322 // Have we gone too far? 324 323 if( lsd_info.Start + callsite_start > instruction_ptr ) { 325 324 printf(" gone too far"); … … 331 330 // Which phase are we in 332 331 if (actions & _UA_SEARCH_PHASE) { 333 // Search phase, this means we probably found a potential handler and must check if it is a match334 335 // If we have arbitrarily decided that 0 means nothing to do and 1 means there is a potential handler336 // This doesn't seem to conflict the gcc default behavior332 // 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. 337 336 if (callsite_action != 0) { 338 337 // Now we want to run some code to see if the handler matches … … 351 350 // The current apprach uses one exception table entry per try block 352 351 _uleb128_t imatcher; 353 // Get the relative offset to the 354 cur_ptr = read_uleb128 (cur_ptr, &imatcher); 355 356 // Get a function pointer from the relative offset and call it 357 // _Unwind_Reason_Code (*matcher)() = (_Unwind_Reason_Code (*)())lsd_info.LPStart + imatcher; 352 // Get the relative offset to the {...}? 353 cur_ptr = read_uleb128(cur_ptr, &imatcher); 358 354 359 355 _Unwind_Reason_Code (*matcher)(exception_t *) = … … 414 410 } 415 411 416 // Try statements are hoisted out see comments for details. With this could probably be unique and simply linked from417 // libcfa but there is one problem left, see the exception table for details412 // Try statements are hoisted out see comments for details. While this could probably be unique 413 // and simply linked from libcfa but there is one problem left, see the exception table for details 418 414 __attribute__((noinline)) 419 415 void __cfaabi_ehm__try_terminate(void (*try_block)(), … … 428 424 // assembly works. 429 425 430 // Setup the personality routine 426 // Setup the personality routine and exception table. 427 #ifdef __PIC__ 428 asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0"); 429 asm volatile (".cfi_lsda 0x1b, .LLSDACFA2"); 430 #else 431 431 asm volatile (".cfi_personality 0x3,__gcfa_personality_v0"); 432 // Setup the exception table433 432 asm volatile (".cfi_lsda 0x3, .LLSDACFA2"); 433 #endif 434 434 435 435 // Label which defines the start of the area for which the handler is setup. … … 442 442 asm volatile goto ("" : : : : CATCH ); 443 443 444 // Normal return 444 // Normal return for when there is no throw. 445 445 return; 446 446 … … 459 459 } 460 460 461 // Exception table data we need to generate. While this is almost generic, the custom data refers to foo_try_match try 462 // match, which is no way generic. Some more works need to be done if we want to have a single call to the try routine. 463 461 // Exception table data we need to generate. While this is almost generic, the custom data refers 462 // to {*}try_terminate, which is no way generic. Some more works need to be done if we want to 463 // have a single call to the try routine. 464 465 #ifdef __PIC__ 464 466 #if defined( __i386 ) || defined( __x86_64 ) 465 467 asm ( 466 // HEADER468 // HEADER 467 469 ".LFECFA1:\n" 468 470 " .globl __gcfa_personality_v0\n" 469 471 " .section .gcc_except_table,\"a\",@progbits\n" 470 ".LLSDACFA2:\n" //TABLE header 472 // TABLE HEADER (important field is the BODY length at the end) 473 ".LLSDACFA2:\n" 471 474 " .byte 0xff\n" 472 475 " .byte 0xff\n" 473 476 " .byte 0x1\n" 474 " .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n" // BODY length 475 // Body uses language specific data and therefore could be modified arbitrarily 476 ".LLSDACSBCFA2:\n" // BODY start 477 " .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n" // Handled area start (relative to start of function) 478 " .uleb128 .TRYEND-.TRYSTART\n" // Handled area length 479 " .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n" // Hanlder landing pad adress (relative to start of function) 480 " .uleb128 1\n" // Action code, gcc seems to use always 0 481 ".LLSDACSECFA2:\n" // BODY end 482 " .text\n" // TABLE footer 477 " .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n" 478 // BODY (language specific data) 479 // This uses language specific data and can be modified arbitrarily 480 // We use handled area offset, handled area length, 481 // handler landing pad offset and 1 (action code, gcc seems to use 0). 482 ".LLSDACSBCFA2:\n" 483 " .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n" 484 " .uleb128 .TRYEND-.TRYSTART\n" 485 " .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n" 486 " .uleb128 1\n" 487 ".LLSDACSECFA2:\n" 488 // TABLE FOOTER 489 " .text\n" 490 " .size __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n" 491 ); 492 493 // Somehow this piece of helps with the resolution of debug symbols. 494 __attribute__((unused)) static const int dummy = 0; 495 496 asm ( 497 // Add a hidden symbol which points at the function. 498 " .hidden CFA.ref.__gcfa_personality_v0\n" 499 " .weak CFA.ref.__gcfa_personality_v0\n" 500 // No clue what this does specifically 501 " .section .data.rel.local.CFA.ref.__gcfa_personality_v0,\"awG\",@progbits,CFA.ref.__gcfa_personality_v0,comdat\n" 502 " .align 8\n" 503 " .type CFA.ref.__gcfa_personality_v0, @object\n" 504 " .size CFA.ref.__gcfa_personality_v0, 8\n" 505 "CFA.ref.__gcfa_personality_v0:\n" 506 #if defined( __x86_64 ) 507 " .quad __gcfa_personality_v0\n" 508 #else // then __i386 509 " .long __gcfa_personality_v0\n" 510 #endif 511 ); 512 #else 513 #error Exception Handling: unknown architecture for position independent code. 514 #endif // __i386 || __x86_64 515 #else // __PIC__ 516 #if defined( __i386 ) || defined( __x86_64 ) 517 asm ( 518 // HEADER 519 ".LFECFA1:\n" 520 " .globl __gcfa_personality_v0\n" 521 " .section .gcc_except_table,\"a\",@progbits\n" 522 // TABLE HEADER (important field is the BODY length at the end) 523 ".LLSDACFA2:\n" 524 " .byte 0xff\n" 525 " .byte 0xff\n" 526 " .byte 0x1\n" 527 " .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n" 528 // BODY (language specific data) 529 ".LLSDACSBCFA2:\n" 530 // Handled area start (relative to start of function) 531 " .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n" 532 // Handled area length 533 " .uleb128 .TRYEND-.TRYSTART\n" 534 // Handler landing pad address (relative to start of function) 535 " .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n" 536 // Action code, gcc seems to always use 0. 537 " .uleb128 1\n" 538 // TABLE FOOTER 539 ".LLSDACSECFA2:\n" 540 " .text\n" 483 541 " .size __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n" 484 542 " .ident \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n" 485 //" .section .note.GNU-stack,\"x\",@progbits\n"543 " .section .note.GNU-stack,\"x\",@progbits\n" 486 544 ); 545 #else 546 #error Exception Handling: unknown architecture for position dependent code. 487 547 #endif // __i386 || __x86_64 488 #endif //PIC 548 #endif // __PIC__ 549 550 #pragma GCC pop_options
Note:
See TracChangeset
for help on using the changeset viewer.