Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.c

    r3b9c674 rd43ed2c  
    6969
    7070
    71 // This macro should be the only thing that needs to change across machines.
    72 // Used in the personality function, way down in termination.
     71// This macro should be the only thing that needs to change across machines.  Used in the personality function, way down
     72// in termination.
    7373// struct _Unwind_Context * -> _Unwind_Reason_Code(*)(exception_t *)
    7474#define MATCHER_FROM_CONTEXT(ptr_to_context) \
     
    102102}
    103103
    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.
     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.
    107106
    108107void __cfaabi_ehm__try_resume_setup(struct __cfaabi_ehm__try_resume_node * node,
     
    213212        _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage );
    214213
    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.
     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.
    221219
    222220        if( ret == _URC_END_OF_STACK ) {
    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.
     221                // No proper handler was found.  This can be handled in several way.  C++ calls std::terminate Here we
     222                // force unwind the stack, basically raising a cancellation.
    225223                printf("Uncaught exception %p\n", &this_exception_storage);
    226224
     
    230228        }
    231229
    232         // We did not simply reach the end of the stack without finding a handler. This is an error.
     230        // We did not simply reach the end of the stack without finding a handler.  Something wen't wrong
    233231        printf("UNWIND ERROR %d after raise exception\n", ret);
    234232        abort();
     
    248246}
    249247
    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.
     248#if defined(PIC)
     249#warning Exceptions not yet supported when using Position-Independent Code
     250__attribute__((noinline))
     251void __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.
    256259_Unwind_Reason_Code __gcfa_personality_v0 (
    257260                int version, _Unwind_Action actions, unsigned long long exceptionClass,
     
    261264
    262265        //__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);
     266        __cfaabi_dbg_print_safe("Personality function (%d, %x, %llu, %p, %p):", version, actions, exceptionClass, unwind_exception, context);
    265267
    266268        // If we've reached the end of the stack then there is nothing much we can do...
     
    289291        // Get the instuction pointer and a reading pointer into the exception table
    290292        lsda_header_info lsd_info;
    291         const unsigned char * cur_ptr = parse_lsda_header(context, lsd, &lsd_info);
     293        const unsigned char * cur_ptr = parse_lsda_header( context, lsd, &lsd_info);
    292294        _Unwind_Ptr instruction_ptr = _Unwind_GetIP( context );
    293295
     
    300302
    301303                // Decode the common stuff we have in here
    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);
     304                cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_start);
     305                cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_len);
     306                cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_landing_pad);
     307                cur_ptr = read_uleb128 (cur_ptr, &callsite_action);
    306308
    307309                // Have we reach the correct frame info yet?
     
    314316                        void * ep = (void*)lsd_info.Start + callsite_start + callsite_len;
    315317                        void * ip = (void*)instruction_ptr;
    316                         __cfaabi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n",
    317                                         bp, ep, ls, cs, cl, ip);
     318                        __cfaabi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n", bp, ep, ls, cs, cl, ip);
    318319#endif // __CFA_DEBUG_PRINT__
    319320                        continue;
    320321                }
    321322
    322                 // Have we gone too far?
     323                // Have we gone too far
    323324                if( lsd_info.Start + callsite_start > instruction_ptr ) {
    324325                        printf(" gone too far");
     
    330331                        // Which phase are we in
    331332                        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.
     333                                // Search phase, this means we probably found a potential handler and must check if it is a match
     334
     335                                // If we have arbitrarily decided that 0 means nothing to do and 1 means there is a potential handler
     336                                // This doesn't seem to conflict the gcc default behavior
    336337                                if (callsite_action != 0) {
    337338                                        // Now we want to run some code to see if the handler matches
     
    350351                                        // The current apprach uses one exception table entry per try block
    351352                                        _uleb128_t imatcher;
    352                                         // Get the relative offset to the {...}?
    353                                         cur_ptr = read_uleb128(cur_ptr, &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;
    354358
    355359                                        _Unwind_Reason_Code (*matcher)(exception_t *) =
     
    410414}
    411415
    412 // 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
     416// Try statements are hoisted out see comments for details.  With this could probably be unique and simply linked from
     417// libcfa but there is one problem left, see the exception table for details
    414418__attribute__((noinline))
    415419void __cfaabi_ehm__try_terminate(void (*try_block)(),
     
    424428        // assembly works.
    425429
    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
     430        // Setup the personality routine
    431431        asm volatile (".cfi_personality 0x3,__gcfa_personality_v0");
     432        // Setup the exception table
    432433        asm volatile (".cfi_lsda 0x3, .LLSDACFA2");
    433 #endif
    434434
    435435        // Label which defines the start of the area for which the handler is setup.
     
    442442        asm volatile goto ("" : : : : CATCH );
    443443
    444         // Normal return for when there is no throw.
     444        // Normal return
    445445        return;
    446446
     
    459459}
    460460
    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__
     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
    466464#if defined( __i386 ) || defined( __x86_64 )
    467465asm (
    468         // HEADER
     466        //HEADER
    469467        ".LFECFA1:\n"
    470468        "       .globl  __gcfa_personality_v0\n"
    471469        "       .section        .gcc_except_table,\"a\",@progbits\n"
    472         // TABLE HEADER (important field is the BODY length at the end)
    473         ".LLSDACFA2:\n"
     470        ".LLSDACFA2:\n"                                                 //TABLE header
    474471        "       .byte   0xff\n"
    475472        "       .byte   0xff\n"
    476473        "       .byte   0x1\n"
    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"
     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
    541483        "       .size   __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n"
    542484        "       .ident  \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n"
    543         "       .section        .note.GNU-stack,\"x\",@progbits\n"
     485//      "       .section        .note.GNU-stack,\"x\",@progbits\n"
    544486);
    545 #else
    546 #error Exception Handling: unknown architecture for position dependent code.
    547487#endif // __i386 || __x86_64
    548 #endif // __PIC__
    549 
    550 #pragma GCC pop_options
     488#endif //PIC
Note: See TracChangeset for help on using the changeset viewer.