Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.c

    r5715d43 r67ca73e  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Aug 12 13:55:00 2020
    13 // Update Count     : 21
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Aug 15 07:17:19 2020
     13// Update Count     : 26
    1414//
    1515
     
    2121// Implementation of the secret header is hardware dependent.
    2222#if !( defined( __x86_64 ) || defined( __i386 ) )
    23 #error Exception Handling: No known architecture detected.
     23#elif defined( __ARM_ARCH )
     24#warning FIX ME: check if anything needed for ARM
     25#else
     26#warning Exception Handling: No known architecture detected.
    2427#endif
    2528
     
    2831#include <unwind.h>
    2932#include <bits/debug.hfa>
    30 #include "concurrency/invoke.h"
    3133#include "stdhdr/assert.h"
    3234
     
    5961
    6062
     63// Temperary global exception context. Does not work with concurency.
     64struct exception_context_t {
     65        struct __cfaehm_try_resume_node * top_resume;
     66
     67        exception_t * current_exception;
     68        int current_handler_index;
     69} static shared_stack = {NULL, NULL, 0};
     70
    6171// Get the current exception context.
    6272// There can be a single global until multithreading occurs, then each stack
    63 // needs its own. We get this from libcfathreads (no weak attribute).
    64 __attribute__((weak)) struct exception_context_t * this_exception_context() {
    65         static struct exception_context_t shared_stack = {NULL, NULL};
     73// needs its own. It will have to be updated to handle that.
     74struct exception_context_t * this_exception_context() {
    6675        return &shared_stack;
    6776}
     
    116125
    117126// MEMORY MANAGEMENT =========================================================
    118 
    119 struct __cfaehm_node {
    120         struct _Unwind_Exception unwind_exception;
    121         struct __cfaehm_node * next;
    122         int handler_index;
    123 };
    124 
    125 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
    126 #define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)
    127 #define UNWIND_TO_NODE(unwind) ((struct __cfaehm_node *)(unwind))
    128 #define NULL_MAP(map, ptr) ((ptr) ? (map(ptr)) : NULL)
    129127
    130128// How to clean up an exception in various situations.
     
    142140}
    143141
     142// We need a piece of storage to raise the exception, for now its a single
     143// piece.
     144static struct _Unwind_Exception this_exception_storage;
     145
     146struct __cfaehm_node {
     147        struct __cfaehm_node * next;
     148};
     149
     150#define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
     151#define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)
     152
    144153// Creates a copy of the indicated exception and sets current_exception to it.
    145154static void __cfaehm_allocate_exception( exception_t * except ) {
     
    155164        }
    156165
    157         // Initialize the node:
    158         exception_t * except_store = NODE_TO_EXCEPT(store);
    159         store->unwind_exception.exception_class = __cfaehm_exception_class;
    160         store->unwind_exception.exception_cleanup = __cfaehm_exception_cleanup;
    161         store->handler_index = 0;
    162         except->virtual_table->copy( except_store, except );
    163 
    164166        // Add the node to the list:
    165         store->next = NULL_MAP(EXCEPT_TO_NODE, context->current_exception);
    166         context->current_exception = except_store;
     167        store->next = EXCEPT_TO_NODE(context->current_exception);
     168        context->current_exception = NODE_TO_EXCEPT(store);
     169
     170        // Copy the exception to storage.
     171        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;
    167176}
    168177
     
    179188        if ( context->current_exception == except ) {
    180189                node = to_free->next;
    181                 context->current_exception = NULL_MAP(NODE_TO_EXCEPT, node);
     190                context->current_exception = (node) ? NODE_TO_EXCEPT(node) : 0;
    182191        } else {
    183192                node = EXCEPT_TO_NODE(context->current_exception);
     
    207216        // Verify actions follow the rules we expect.
    208217        verify((actions & _UA_CLEANUP_PHASE) && (actions & _UA_FORCE_UNWIND));
    209         verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME)));
     218        verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDER_FRAME)));
    210219
    211220        if ( actions & _UA_END_OF_STACK ) {
     
    216225}
    217226
    218 static struct _Unwind_Exception cancel_exception_storage;
    219 
    220227// Cancel the current stack, prefroming approprate clean-up and messaging.
    221228void __cfaehm_cancel_stack( exception_t * exception ) {
    222229        // TODO: Detect current stack and pick a particular stop-function.
    223230        _Unwind_Reason_Code ret;
    224         ret = _Unwind_ForcedUnwind( &cancel_exception_storage, _Stop_Fn, (void*)0x22 );
     231        ret = _Unwind_ForcedUnwind( &this_exception_storage, _Stop_Fn, (void*)0x22 );
    225232        printf("UNWIND ERROR %d after force unwind\n", ret);
    226233        abort();
     
    243250static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {
    244251        struct exception_context_t * context = this_exception_context();
     252        struct _Unwind_Exception * storage = &this_exception_storage;
    245253        if ( NULL == context->current_exception ) {
    246254                printf("UNWIND ERROR missing exception in begin unwind\n");
    247255                abort();
    248256        }
    249         struct _Unwind_Exception * storage =
    250                 &EXCEPT_TO_NODE(context->current_exception)->unwind_exception;
    251257
    252258        // Call stdlibc to raise the exception
     
    294300        abort();
    295301}
    296 
     302#if 0
    297303// This is our personality routine. For every stack frame annotated with
    298304// ".cfi_personality 0x3,__gcfa_personality_v0" this function will be called twice when unwinding.
     
    406412                                cur_ptr = read_uleb128(cur_ptr, &imatcher);
    407413
     414                                _Unwind_Word match_pos =
    408415#                               if defined( __x86_64 )
    409                                 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 8;
     416                                    _Unwind_GetCFA(unwind_context) + 8;
    410417#                               elif defined( __i386 )
    411                                 _Unwind_Word match_pos = _Unwind_GetCFA(unwind_context) + 24;
     418                                    _Unwind_GetCFA(unwind_context) + 24;
     419#                               elif defined( __ARM_ARCH )
     420#                                   warning FIX ME: check if anything needed for ARM
     421                                    42;
    412422#                               endif
    413423                                int (*matcher)(exception_t *) = *(int(**)(exception_t *))match_pos;
     
    416426                                _Unwind_Reason_Code ret = (0 == index)
    417427                                        ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
    418                                 UNWIND_TO_NODE(unwind_exception)->handler_index = index;
     428                                context->current_handler_index = index;
    419429
    420430                                // Based on the return value, check if we matched the exception
     
    422432                                        __cfadbg_print_safe(exception, " handler found\n");
    423433                                } else {
    424                                         // TODO: Continue the search if there is more in the table.
    425434                                        __cfadbg_print_safe(exception, " no handler\n");
    426435                                }
     
    514523        // Exception handler
    515524        // Note: Saving the exception context on the stack breaks termination exceptions.
    516         catch_block( EXCEPT_TO_NODE( this_exception_context()->current_exception )->handler_index,
     525        catch_block( this_exception_context()->current_handler_index,
    517526                     this_exception_context()->current_exception );
    518527}
     
    600609
    601610#pragma GCC pop_options
     611#endif // 0
Note: See TracChangeset for help on using the changeset viewer.