Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.c

    r851fd92 r3b9c674  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr 14 12:01:00 2020
    13 // Update Count     : 18
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Feb 22 18:17:34 2018
     13// Update Count     : 11
    1414//
    1515
    16 // Normally we would get this from the CFA prelude.
    1716#include <stddef.h> // for size_t
    1817
    1918#include "exception.h"
    2019
    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.
    2521
    2622#include <stdlib.h>
     
    2824#include <unwind.h>
    2925#include <bits/debug.hfa>
    30 #include "stdhdr/assert.h"
    3126
    3227// FIX ME: temporary hack to keep ARM build working
    3328#ifndef _URC_FATAL_PHASE1_ERROR
    34 #define _URC_FATAL_PHASE1_ERROR 3
     29#define _URC_FATAL_PHASE1_ERROR 2
    3530#endif // ! _URC_FATAL_PHASE1_ERROR
    3631#ifndef _URC_FATAL_PHASE2_ERROR
     
    4035#include "lsda.h"
    4136
    42 /* The exception class for our exceptions. Because of the vendor component
    43  * its value would not be standard.
    44  * Vendor: UWPL
    45  * Language: CFA\0
    46  */
    47 const _Unwind_Exception_Class __cfaehm_exception_class = 0x4c50575500414643;
    4837
    4938// Base exception vtable is abstract, you should not have base exceptions.
    50 struct __cfaehm_base_exception_t_vtable
    51                 ___cfaehm_base_exception_t_vtable_instance = {
     39struct __cfaabi_ehm__base_exception_t_vtable
     40                ___cfaabi_ehm__base_exception_t_vtable_instance = {
    5241        .parent = NULL,
    5342        .size = 0,
     
    6049// Temperary global exception context. Does not work with concurency.
    6150struct 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};
    6757
    6858// Get the current exception context.
     
    7262        return &shared_stack;
    7363}
     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))
    7476
    7577
    7678// RESUMPTION ================================================================
    7779
    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;
     80void __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;
    9087
    9188        for ( ; current ; current = current->next) {
    92                 context->top_resume = current->next;
     89                shared_stack.current_resume = current;
    9390                if (current->handler(except)) {
     91                        shared_stack.current_resume = original_head;
    9492                        return;
    9593                }
    9694        }
    9795
    98         __cfadbg_print_safe(exception, "Unhandled exception\n");
     96        __cfaabi_dbg_print_safe("Unhandled exception\n");
     97        shared_stack.current_resume = original_head;
    9998
    10099        // Fall back to termination:
    101         __cfaehm_throw_terminate(except);
     100        __cfaabi_ehm__throw_terminate(except);
    102101        // TODO: Default handler for resumption.
    103102}
     
    107106// be added after the node is built but before it is made the top node.
    108107
    109 void __cfaehm_try_resume_setup(struct __cfaehm_try_resume_node * node,
     108void __cfaabi_ehm__try_resume_setup(struct __cfaabi_ehm__try_resume_node * node,
    110109                        _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;
    113111        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
     115void __cfaabi_ehm__try_resume_cleanup(struct __cfaabi_ehm__try_resume_node * node) {
     116        shared_stack.top_resume = node->next;
    120117}
    121118
     
    126123// May have to move to cfa for constructors and destructors (references).
    127124
    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;
     125struct __cfaabi_ehm__node {
     126        struct __cfaabi_ehm__node * next;
    148127};
    149128
    150129#define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
    151 #define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)
     130#define EXCEPT_TO_NODE(except) ((struct __cfaabi_ehm__node *)(except) - 1)
    152131
    153132// Creates a copy of the indicated exception and sets current_exception to it.
    154 static void __cfaehm_allocate_exception( exception_t * except ) {
     133static void __cfaabi_ehm__allocate_exception( exception_t * except ) {
    155134        struct exception_context_t * context = this_exception_context();
    156135
    157136        // Allocate memory for the exception.
    158         struct __cfaehm_node * store = malloc(
    159                 sizeof( struct __cfaehm_node ) + except->virtual_table->size );
     137        struct __cfaabi_ehm__node * store = malloc(
     138                sizeof( struct __cfaabi_ehm__node ) + except->virtual_table->size );
    160139
    161140        if ( ! store ) {
     
    170149        // Copy the exception to storage.
    171150        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;
    176151}
    177152
    178153// Delete the provided exception, unsetting current_exception if relivant.
    179 static void __cfaehm_delete_exception( exception_t * except ) {
     154static void __cfaabi_ehm__delete_exception( exception_t * except ) {
    180155        struct exception_context_t * context = this_exception_context();
    181156
    182         __cfadbg_print_safe(exception, "Deleting Exception\n");
     157        __cfaabi_dbg_print_safe("Deleting Exception\n");
    183158
    184159        // Remove the exception from the list.
    185         struct __cfaehm_node * to_free = EXCEPT_TO_NODE(except);
    186         struct __cfaehm_node * node;
     160        struct __cfaabi_ehm__node * to_free = EXCEPT_TO_NODE(except);
     161        struct __cfaabi_ehm__node * node;
    187162
    188163        if ( context->current_exception == except ) {
     
    192167                node = EXCEPT_TO_NODE(context->current_exception);
    193168                // It may always be in the first or second position.
    194                 while ( to_free != node->next ) {
     169                while( to_free != node->next ) {
    195170                        node = node->next;
    196171                }
     
    204179
    205180// 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 }
     181void __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
     187struct _Unwind_Exception this_exception_storage;
    209188
    210189// Function needed by force unwind
     
    213192                int version,
    214193                _Unwind_Action actions,
    215                 _Unwind_Exception_Class exception_class,
     194                _Unwind_Exception_Class exceptionClass,
    216195                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;
    228202}
    229203
    230204// 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) {
    232206        if ( ! this_exception_context()->current_exception ) {
    233207                printf("UNWIND ERROR missing exception in begin unwind\n");
    234208                abort();
    235209        }
     210
    236211
    237212        // Call stdlibc to raise the exception
     
    245220        // the whole stack.
    246221
    247         if ( ret == _URC_END_OF_STACK ) {
     222        if( ret == _URC_END_OF_STACK ) {
    248223                // No proper handler was found. This can be handled in many ways, C++ calls std::terminate.
    249224                // Here we force unwind the stack, basically raising a cancellation.
     
    260235}
    261236
    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 }
     237void __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
     244void __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")
    274252
    275253// This is our personality routine. For every stack frame annotated with
    276254// ".cfi_personality 0x3,__gcfa_personality_v0" this function will be called twice when unwinding.
    277255//  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)
    284260{
    285261
    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
    294269        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;
    308279        }
    309280
    310281        // 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 unwinding
     282        const unsigned char * lsd = (const unsigned char*) _Unwind_GetLanguageSpecificData( context );
     283
     284        if( !lsd ) {    //Nothing to do, keep unwinding
    314285                printf(" no LSD");
    315286                goto UNWIND;
     
    318289        // Get the instuction pointer and a reading pointer into the exception table
    319290        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 );
    324293
    325294        // Linearly search the table for stuff to do
    326         while ( cur_ptr < lsd_info.action_table ) {
     295        while( cur_ptr < lsd_info.action_table ) {
    327296                _Unwind_Ptr callsite_start;
    328297                _Unwind_Ptr callsite_len;
     
    337306
    338307                // 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 ) {
    340309#ifdef __CFA_DEBUG_PRINT__
    341310                        void * ls = (void*)lsd_info.Start;
     
    345314                        void * ep = (void*)lsd_info.Start + callsite_start + callsite_len;
    346315                        void * ip = (void*)instruction_ptr;
    347                         __cfadbg_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",
    348317                                        bp, ep, ls, cs, cl, ip);
    349318#endif // __CFA_DEBUG_PRINT__
     
    352321
    353322                // Have we gone too far?
    354                 if ( lsd_info.Start + callsite_start > instruction_ptr ) {
     323                if( lsd_info.Start + callsite_start > instruction_ptr ) {
    355324                        printf(" gone too far");
    356325                        break;
    357326                }
    358327
    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;
    403369                                }
    404                                 return ret;
     370
     371                                // This is only a cleanup handler, ignore it
     372                                __cfaabi_dbg_print_safe(" no action");
    405373                        }
    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;
    417396                        }
    418 
    419                         // We need to run some clean-up or a handler
    420                         // These statment do the right thing but I don't know any specifics at all
    421                         _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 pad
    426                         // It doesn't actually set it, it only state the value that needs to be set once we
    427                         // return _URC_INSTALL_CONTEXT
    428                         _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 run
    433                         return _URC_INSTALL_CONTEXT;
    434397                }
     398
     399                // Nothing to do, move along
     400                __cfaabi_dbg_print_safe(" no landing pad");
    435401        }
    436402        // No handling found
    437         __cfadbg_print_safe(exception, " table end reached");
     403        __cfaabi_dbg_print_safe(" table end reached\n");
    438404
    439405        UNWIND:
    440         __cfadbg_print_safe(exception, " unwind\n");
     406        __cfaabi_dbg_print_safe(" unwind\n");
    441407
    442408        // Keep unwinding the stack
    443409        return _URC_CONTINUE_UNWIND;
    444410}
    445 
    446 #pragma GCC push_options
    447 #pragma GCC optimize(0)
    448411
    449412// Try statements are hoisted out see comments for details. While this could probably be unique
    450413// and simply linked from libcfa but there is one problem left, see the exception table for details
    451414__attribute__((noinline))
    452 void __cfaehm_try_terminate(void (*try_block)(),
     415void __cfaabi_ehm__try_terminate(void (*try_block)(),
    453416                void (*catch_block)(int index, exception_t * except),
    454417                __attribute__((unused)) int (*match_block)(exception_t * except)) {
     
    456419        //! printf("%p %p %p %p\n", &try_block, &catch_block, &match_block, &xy);
    457420
     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
    458426        // Setup the personality routine and exception table.
    459         // Unforturnately these clobber gcc cancellation support which means we can't get access to
    460         // the attribute cleanup tables at the same time. We would have to inspect the assembly to
    461         // create a new set ourselves.
    462427#ifdef __PIC__
    463428        asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0");
     
    484449        // Label which defines the end of the area for which the handler is setup.
    485450        asm volatile (".TRYEND:");
    486         // Label which defines the start of the exception landing pad. Basically what is called when
    487         // the exception is caught. Note, if multiple handlers are given, the multiplexing should be
    488         // done by the generated code, not the exception 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.
    489454        asm volatile (".CATCH:");
    490455
    491456        // 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 );
    495459}
    496460
     
    500464
    501465#ifdef __PIC__
     466#if defined( __i386 ) || defined( __x86_64 )
    502467asm (
    503468        // HEADER
     
    516481        // handler landing pad offset and 1 (action code, gcc seems to use 0).
    517482        ".LLSDACSBCFA2:\n"
    518         "       .uleb128 .TRYSTART-__cfaehm_try_terminate\n"
     483        "       .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n"
    519484        "       .uleb128 .TRYEND-.TRYSTART\n"
    520         "       .uleb128 .CATCH-__cfaehm_try_terminate\n"
     485        "       .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n"
    521486        "       .uleb128 1\n"
    522487        ".LLSDACSECFA2:\n"
    523488        // TABLE FOOTER
    524489        "       .text\n"
    525         "       .size   __cfaehm_try_terminate, .-__cfaehm_try_terminate\n"
     490        "       .size   __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n"
    526491);
    527492
     
    542507        "       .quad __gcfa_personality_v0\n"
    543508#else // then __i386
    544         "       .long __gcfa_personality_v0\n"
     509        "   .long __gcfa_personality_v0\n"
    545510#endif
    546511);
     512#else
     513#error Exception Handling: unknown architecture for position independent code.
     514#endif // __i386 || __x86_64
    547515#else // __PIC__
     516#if defined( __i386 ) || defined( __x86_64 )
    548517asm (
    549518        // HEADER
     
    560529        ".LLSDACSBCFA2:\n"
    561530        //      Handled area start (relative to start of function)
    562         "       .uleb128 .TRYSTART-__cfaehm_try_terminate\n"
     531        "       .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n"
    563532        //      Handled area length
    564533        "       .uleb128 .TRYEND-.TRYSTART\n"
    565534        //      Handler landing pad address (relative to start of function)
    566         "       .uleb128 .CATCH-__cfaehm_try_terminate\n"
     535        "       .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n"
    567536        //      Action code, gcc seems to always use 0.
    568537        "       .uleb128 1\n"
     
    570539        ".LLSDACSECFA2:\n"
    571540        "       .text\n"
    572         "       .size   __cfaehm_try_terminate, .-__cfaehm_try_terminate\n"
     541        "       .size   __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n"
    573542        "       .ident  \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n"
    574543        "       .section        .note.GNU-stack,\"x\",@progbits\n"
    575544);
     545#else
     546#error Exception Handling: unknown architecture for position dependent code.
     547#endif // __i386 || __x86_64
    576548#endif // __PIC__
    577549
Note: See TracChangeset for help on using the changeset viewer.