Changeset 9cb89b87


Ignore:
Timestamp:
Mar 26, 2020, 10:56:38 AM (5 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
68887f9
Parents:
2a3b019
Message:

Clean-up in exception.c, follow up from the last one.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.c

    r2a3b019 r9cb89b87  
    5858    exception_t * current_exception;
    5959    int current_handler_index;
    60 } shared_stack = {NULL, NULL, 0, 0};
     60} static shared_stack = {NULL, NULL, NULL, 0};
    6161
    6262// Get the current exception context.
    6363// There can be a single global until multithreading occurs, then each stack
    6464// needs its own. It will have to be updated to handle that.
    65 inline static struct exception_context_t * this_exception_context() {
     65struct exception_context_t * this_exception_context() {
    6666        return &shared_stack;
    6767}
     
    162162                node = EXCEPT_TO_NODE(context->current_exception);
    163163                // It may always be in the first or second position.
    164                 while( to_free != node->next ) {
     164                while ( to_free != node->next ) {
    165165                        node = node->next;
    166166                }
     
    191191                struct _Unwind_Context * unwind_context,
    192192                void * stop_param) {
    193         if( actions & _UA_END_OF_STACK  ) exit(1);
    194         if( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON;
     193        if ( actions & _UA_END_OF_STACK  ) exit(1);
     194        if ( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON;
    195195
    196196        return _URC_FATAL_PHASE2_ERROR;
     
    215215        // the whole stack.
    216216
    217         if( ret == _URC_END_OF_STACK ) {
     217        if ( ret == _URC_END_OF_STACK ) {
    218218                // No proper handler was found. This can be handled in many ways, C++ calls std::terminate.
    219219                // Here we force unwind the stack, basically raising a cancellation.
     
    257257
    258258        // If we've reached the end of the stack then there is nothing much we can do...
    259         if( actions & _UA_END_OF_STACK ) return _URC_END_OF_STACK;
     259        if (actions & _UA_END_OF_STACK) return _URC_END_OF_STACK;
    260260
    261261        if (actions & _UA_SEARCH_PHASE) {
     
    272272
    273273        // Get a pointer to the language specific data from which we will read what we need
    274         const unsigned char * lsd = (const unsigned char*) _Unwind_GetLanguageSpecificData( unwind_context );
    275 
    276         if( !lsd ) {    //Nothing to do, keep unwinding
     274        const unsigned char * lsd = _Unwind_GetLanguageSpecificData( unwind_context );
     275
     276        if ( !lsd ) {   //Nothing to do, keep unwinding
    277277                printf(" no LSD");
    278278                goto UNWIND;
     
    287287
    288288        // Linearly search the table for stuff to do
    289         while( cur_ptr < lsd_info.action_table ) {
     289        while ( cur_ptr < lsd_info.action_table ) {
    290290                _Unwind_Ptr callsite_start;
    291291                _Unwind_Ptr callsite_len;
     
    300300
    301301                // Have we reach the correct frame info yet?
    302                 if( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) {
     302                if ( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) {
    303303#ifdef __CFA_DEBUG_PRINT__
    304304                        void * ls = (void*)lsd_info.Start;
     
    315315
    316316                // Have we gone too far?
    317                 if( lsd_info.Start + callsite_start > instruction_ptr ) {
     317                if ( lsd_info.Start + callsite_start > instruction_ptr ) {
    318318                        printf(" gone too far");
    319319                        break;
    320320                }
    321321
    322                 // Something to do?
     322                // Check for what we must do:
    323323                if ( 0 == callsite_landing_pad ) {
    324324                        // Nothing to do, move along
    325325                        __cfaabi_dbg_print_safe(" no landing pad");
    326                 } else {
    327                         // Which phase are we in
    328                         if (actions & _UA_SEARCH_PHASE) {
    329                                 // In search phase, these means we found a potential handler we must check.
    330 
    331                                 // We have arbitrarily decided that 0 means nothing to do and 1 means there is
    332                                 // a potential handler. This doesn't seem to conflict the gcc default behavior.
    333                                 if (callsite_action != 0) {
    334                                         // Now we want to run some code to see if the handler matches
    335                                         // This is the tricky part where we want to the power to run arbitrary code
    336                                         // However, generating a new exception table entry and try routine every time
    337                                         // is way more expansive than we might like
    338                                         // The information we have is :
    339                                         //  - The GR (Series of registers)
    340                                         //    GR1=GP Global Pointer of frame ref by context
    341                                         //  - The instruction pointer
    342                                         //  - The instruction pointer info (???)
    343                                         //  - The CFA (Canonical Frame Address)
    344                                         //  - The BSP (Probably the base stack pointer)
    345 
    346 
    347                                         // The current apprach uses one exception table entry per try block
    348                                         _uleb128_t imatcher;
    349                                         // Get the relative offset to the {...}?
    350                                         cur_ptr = read_uleb128(cur_ptr, &imatcher);
    351 
    352 #                                       if defined( __x86_64 )
    353                                         _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 8;
    354 #                                       elif defined( __i386 )
    355                                         _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 24;
    356 #                                       endif
    357                                         int (*matcher)(exception_t *) = *(int(**)(exception_t *))match_pos;
    358 
    359                                         int index = matcher(context->current_exception);
    360                                         _Unwind_Reason_Code ret = (0 == index)
    361                                                 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
    362                                         context->current_handler_index = index;
    363 
    364                                         // Based on the return value, check if we matched the exception
    365                                         if( ret == _URC_HANDLER_FOUND) {
    366                                                 __cfaabi_dbg_print_safe(" handler found\n");
    367                                         } else {
    368                                                 __cfaabi_dbg_print_safe(" no handler\n");
    369                                         }
    370                                         return ret;
     326                } else if (actions & _UA_SEARCH_PHASE) {
     327                        // In search phase, these means we found a potential handler we must check.
     328
     329                        // We have arbitrarily decided that 0 means nothing to do and 1 means there is
     330                        // a potential handler. This doesn't seem to conflict the gcc default behavior.
     331                        if (callsite_action != 0) {
     332                                // Now we want to run some code to see if the handler matches
     333                                // This is the tricky part where we want to the power to run arbitrary code
     334                                // However, generating a new exception table entry and try routine every time
     335                                // is way more expansive than we might like
     336                                // The information we have is :
     337                                //  - The GR (Series of registers)
     338                                //    GR1=GP Global Pointer of frame ref by context
     339                                //  - The instruction pointer
     340                                //  - The instruction pointer info (???)
     341                                //  - The CFA (Canonical Frame Address)
     342                                //  - The BSP (Probably the base stack pointer)
     343
     344
     345                                // The current apprach uses one exception table entry per try block
     346                                _uleb128_t imatcher;
     347                                // Get the relative offset to the {...}?
     348                                cur_ptr = read_uleb128(cur_ptr, &imatcher);
     349
     350#                               if defined( __x86_64 )
     351                                _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 8;
     352#                               elif defined( __i386 )
     353                                _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 24;
     354#                               endif
     355                                int (*matcher)(exception_t *) = *(int(**)(exception_t *))match_pos;
     356
     357                                int index = matcher(context->current_exception);
     358                                _Unwind_Reason_Code ret = (0 == index)
     359                                        ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
     360                                context->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");
    371367                                }
    372 
    373                                 // This is only a cleanup handler, ignore it
    374                                 __cfaabi_dbg_print_safe(" no action");
     368                                return ret;
    375369                        }
    376                         else if (actions & _UA_CLEANUP_PHASE) {
    377 
    378                                 if( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){
    379                                         // If this is a potential exception handler
    380                                         // but not the one that matched the exception in the seach phase,
    381                                         // just ignore it
    382                                         goto UNWIND;
    383                                 }
    384 
    385                                 // We need to run some clean-up or a handler
    386                                 // These statment do the right thing but I don't know any specifics at all
    387                                 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(0),
    388                                         (_Unwind_Ptr)unwind_exception );
    389                                 _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(1), 0 );
    390 
    391                                 // I assume this sets the instruction pointer to the adress of the landing pad
    392                                 // It doesn't actually set it, it only state the value that needs to be set once we return _URC_INSTALL_CONTEXT
    393                                 _Unwind_SetIP( unwind_context, ((lsd_info.LPStart) + (callsite_landing_pad)) );
    394 
    395                                 __cfaabi_dbg_print_safe(" action\n");
    396 
    397                                 // Return have some action to run
    398                                 return _URC_INSTALL_CONTEXT;
     370
     371                        // This is only a cleanup handler, ignore it
     372                        __cfaabi_dbg_print_safe(" no action");
     373                } else if (actions & _UA_CLEANUP_PHASE) {
     374                        // In clean-up phase, no destructors here but this could be the handler.
     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;
    399381                        }
     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( unwind_context, __builtin_eh_return_data_regno(0),
     386                                (_Unwind_Ptr)unwind_exception );
     387                        _Unwind_SetGR( unwind_context, __builtin_eh_return_data_regno(1), 0 );
     388
     389                        // I assume this sets the instruction pointer to the adress of the landing pad
     390                        // It doesn't actually set it, it only state the value that needs to be set once we
     391                        // return _URC_INSTALL_CONTEXT
     392                        _Unwind_SetIP( unwind_context, ((lsd_info.LPStart) + (callsite_landing_pad)) );
     393
     394                        __cfaabi_dbg_print_safe(" action\n");
     395
     396                        // Return have some action to run
     397                        return _URC_INSTALL_CONTEXT;
    400398                }
    401399        }
     
    422420        //! printf("%p %p %p %p\n", &try_block, &catch_block, &match_block, &xy);
    423421
    424         // Setup statments: These 2 statments won't actually result in any code, they only setup global tables.
    425         // However, they clobber gcc cancellation support from gcc.  We can replace the personality routine but
    426         // replacing the exception table gcc generates is not really doable, it generates labels based on how the
    427         // assembly works.
    428 
    429422        // Setup the personality routine and exception table.
     423        // Unforturnately these clobber gcc cancellation support which means we can't get access to
     424        // the attribute cleanup tables at the same time. We would have to inspect the assembly to
     425        // create a new set ourselves.
    430426#ifdef __PIC__
    431427        asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0");
     
    452448        // Label which defines the end of the area for which the handler is setup.
    453449        asm volatile (".TRYEND:");
    454         // Label which defines the start of the exception landing pad.  Basically what is called when the exception is
    455         // caught.  Note, if multiple handlers are given, the multiplexing should be done by the generated code, not the
    456         // exception runtime.
     450        // Label which defines the start of the exception landing pad. Basically what is called when
     451        // the exception is caught. Note, if multiple handlers are given, the multiplexing should be
     452        // done by the generated code, not the exception runtime.
    457453        asm volatile (".CATCH:");
    458454
Note: See TracChangeset for help on using the changeset viewer.