Beispiel #1
0
// never return
_RTARCTOR::_RTARCTOR            // COPY CTOR FOR R/T AR-CTOR
    ( _RTARCTOR const & )
    : _count( 0 )
    , _sig( 0 )
    , _array( 0 )
{
    GOOF_EXC( "Attempt to copy RTARCTOR" );
    // never return
}
Beispiel #2
0
static void getProcInfo         // GET EXCEPTION INFO FOR PROCEDURE
    ( __EXC_INFO* inf           // - exception info
    , PD_DISP_CTX* dctx )       // - dispatcher context for procedure
{
    void* frame;                // - frame ptr.

    PData* pd = dctx->pdata;
    inf->pd = pd;
    inf->ro = (RO_DTREG*)pd->exc_data;
    frame = getProcFrame( pd, dctx );
    inf->rw = (RW_DTREG*)( (char*)frame + inf->ro->fun.rw_offset );
    if( inf->rw->base.ro != inf->ro ) {
        GOOF_EXC( "getProcInfo: rw->ro != ro" );
    }
}
Beispiel #3
0
static void* getProcFrame       // GET PROCEDURE FRAME
    ( PData* pdata              // - procedure descriptor
    , PD_DISP_CTX* dctx )       // - dispatch context
{
    void* frame;                // - frame ptr.

#if 0
    if( procSetsFP( pdata ) ) {
        frame = (void*)dctx->fp_actual;
    } else {
        frame = (void*)dctx->sp_actual;
    }
#else
    if( dctx->pdata != pdata ) {
        GOOF_EXC( "getProcFram: dctx->pdata != pdata" );
    }
    // AFS: this function seems to change a lot and it very brittle;
    // is it possible to use 'sp' from the handler?
    frame = dctx->fp_alternate;
#endif
    return frame;
}
Beispiel #4
0
static DISPATCHABLE dispatchable( // DETERMINE WHERE CATCHABLE WITHIN FUNCTION
    DISPATCH_EXC *dispatch,     // - dispatch information
    RW_DTREG *rw )              // - current read/write
{
    _RTCTL rt_ctl               // - R/T control
        ( dispatch->rtc->thr );
    STAB_TRAVERSE traverse;     // - traversal control
    RO_STATE* state;            // - current state entry
    DISPATCHABLE retn;          // - return: dispatchability
    DTOR_CMD* cmd;              // - command pointer
    ACTIVE_EXC *exc;            // - active exception
    rboolean rethrow;           // - true ==> re-throw from top block

    if( dispatch->rethrow ) {
        exc = dispatch->exc;
        if( exc == NULL ) {
            GOOF_EXC( "dispatchable: missing caught exception" );
        }
        dispatch->ro = exc->throw_ro;
        dispatch->zero = exc->zero_thrown;
        rethrow = true;
    } else {
        rethrow = false;
    }
    rt_ctl.setRwRo( rw );
    CPPLIB( stab_trav_init )( &traverse, &rt_ctl );
    for( ; ; CPPLIB( stab_trav_next )( &traverse ) ) {
        state = CPPLIB( stab_trav_move )( &traverse );
        if( state == NULL ) {
            retn = DISPATCHABLE_NONE;
            break;
        }
        if( state->dtor != NULL ) continue;
        cmd = state->u.cmd_addr;
        switch( cmd->base.code ) {
          case DTC_CATCH :
            if( rethrow ) {
                if( exc->cat_try == TryFromCatch( cmd ) ) {
                    dispatch->popped = true;
                }
                rethrow = false;
            }
            continue;
          case DTC_FN_EXC :
            if( dispatchableFnExc( dispatch, cmd ) ) {
                // exception violates fn-exc spec.
                retn = DISPATCHABLE_FNEXC;
                break;
            }
            continue;
          case DTC_TRY :
            if( dispatchableCatch( dispatch, cmd ) ) {
                retn = DISPATCHABLE_CATCH;
                break;
            }
            continue;
          default :
            continue;
        }
        dispatch->state_var = traverse.state_var;
        break;
    }
    return retn;
}
Beispiel #5
0
ACTIVE_EXC *CPPLIB( alloc_exc )(// ALLOCATE AN EXCEPTION
    void *object,               // - address of object
    THROW_RO *throw_ro,         // - throw R/O block
    _RTCTL* rtc )               // - R/T control
{
    FREE_AREA *fr;              // - a freed area
    FREE_AREA **owner;          // - previous freed area
    FREE_AREA *next;            // - next freed area
    RT_TYPE_SIG sig;            // - type signature of thrown item
    ACTIVE_EXC *active;         // - active exception
    unsigned size;              // - size required
    THREAD_CTL *thr;            // - thread control

    #ifdef __MT__
        __EXC_AREA.semaphore.p();
    #endif
    if( __EXC_AREA.freed == NULL ) {
        fr = (FREE_AREA*)((char*)&__EXC_AREA + sizeof( EXC_AREA )); // initial free list entry
        fr->next = NULL;
        fr->size = __EXC_AREA.size - sizeof( EXC_AREA );
        __EXC_AREA.freed = fr;
#ifndef NDEBUG
        memset( (char*)fr + sizeof(FREE_AREA)
              , 0xEF
              , fr->size - sizeof(FREE_AREA) );
#endif
    }
    sig = CPPLIB( ts_refed )( throw_ro->cnvs[0].signature );
    size = CPPLIB( ts_size )( sig ) + SIZEOF_HDR + sizeof( size_t );
    if( size < sizeof( FREE_AREA ) ) {
        size = sizeof( FREE_AREA );
    }
    size = ( size + 3 ) & -4;
    for( owner = &__EXC_AREA.freed; ; owner = &fr->next ) {
        fr = *owner;
        if( fr == NULL ) {
            CPPLIB(fatal_runtime_error)( RTMSG_EXC_NO_SPACE, 1 );
        }
        for( ;; ) { // coalesce
            next = fr->next;
            if( (FREE_AREA*)((char*)fr + fr->size) != next ) break;
            fr->size += next->size;
            fr->next = next->next;
        }
        if( fr->size == size ) {
            *owner = fr->next;
            active = (ACTIVE_EXC*)fr;
            break;
        } else if( fr->size > ( size + SIZEOF_SPLIT ) ) {
            fr->size -= size;
            active = (ACTIVE_EXC*)( (char*)fr + fr->size );
            break;
        }
    }
    #ifdef __MT__
        __EXC_AREA.semaphore.v();
    #endif
    *(size_t*)active = size;
    active = (ACTIVE_EXC*)( (char*)active + sizeof( size_t ) );
    active->exc_area = &__EXC_AREA;
    thr = rtc->thr;
    active->prev = thr->excepts;
    thr->excepts = active;
    active->sig = throw_ro->cnvs[0].signature;
    active->throw_ro = throw_ro;
    active->state = EXCSTATE_CTOR;
    active->zero_thrown = false;
    active->dispatch = NULL;
    active->rw = NULL;
    switch( sig->hdr.type ) {
      case THROBJ_SCALAR :
      case THROBJ_PTR_FUN :
        memcpy( active->data, object, sig->scalar.size );
        break;
      case THROBJ_CLASS :
      { _EXC_PR_FREE marker( rtc, 0, EXCSTATE_CTOR, active );
        (*sig->clss.copyctor)( active->data, object );
        marker._exc = 0;
      } break;
      case THROBJ_CLASS_VIRT :
      { _EXC_PR_FREE marker( rtc, 0, EXCSTATE_CTOR, active );
        (*sig->clss_v.copyctor)( active->data, CTOR_NULL, object );
        marker._exc = 0;
      } break;
      case THROBJ_PTR_CLASS :
      case THROBJ_PTR_SCALAR :
      case THROBJ_VOID_STAR :
        memcpy( active->data, object, sizeof( void* ) );
        size = sizeof( void* );
        break;
      default :
        GOOF_EXC( "ALLOCEXC: unexpected type signature" );
    }
    return active;
}
Beispiel #6
0
static void processThrow(       // PROCESS A THROW
    void *object,               // - address of object
    THROW_RO *throw_ro,         // - thrown R/O block
    rboolean is_zero )          // - true ==> thrown object is zero constant
{
    _RTCTL rt_ctl;              // - R/T control
    DISPATCH_EXC dispatch;      // - dispatch control
    auto FsExcRec excrec;       // - system exception record
    volatile rboolean unwound;
    void *force_this_routine_to_have_an_EBP_frame;

//  CPPLIB( DbgRtDumpAutoDtor )();

#if 0
//
// Check for throws under bad circumstances
//
    ACTIVE_EXC *exc = rt_ctl.thr->excepts;
    if( exc == NULL ) {
        if( rt_ctl.thr->flags.terminated ) {
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_TERMIN, 1 );
        }
    } else {
        switch( exc->state ) {
          case EXCSTATE_DISPATCH :
          case EXCSTATE_UNEXPECTED :
          case EXCSTATE_BAD_EXC :
            break;
          case EXCSTATE_UNWIND :
          { CPPLIB( free_exc )( &rt_ctl, exc );
            _EXC_PR marker( &rt_ctl, 0, EXCSTATE_TERMINATE );
            CPPLIB( call_terminate )( RTMSG_THROW_DTOR, rt_ctl.thr );
          }
          case EXCSTATE_TERMINATE :
            CPPLIB( free_exc )( &rt_ctl, exc );
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_TERMIN, 1 );
          case EXCSTATE_CTOR :
            CPPLIB( free_exc )( &rt_ctl, exc );
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_CTOR, 1 );
          case EXCSTATE_DTOR :
            CPPLIB( free_exc )( &rt_ctl, exc );
            CPPLIB( fatal_runtime_error )( RTMSG_EXC_DTOR, 1 );
          default:
            GOOF_EXC( "getActiveExc: unexpected exception state" );
        }
    }
#endif
//
// Setup for dispatch
//
    rt_ctl.thr->abort_msg = NULL;
    CPPLIB( exc_setup )( &dispatch
                       , throw_ro
                       , is_zero
                       , &rt_ctl
                       , object
                       , &excrec );
    force_this_routine_to_have_an_EBP_frame = alloca(16);
    unwound = false;
//
// raising exception locates the catch/fn-exception to be dispatched
// also fills in excrec.addr
//
    if( 0 == dispatch.fs_last ) {
        // no search when no R/W blocks
        dispatch.type = DISPATCHABLE_NO_CATCH;
    } else {
        FS_RAISE_EXCEPTION( &excrec );
    }
//
// comes here twice, unless an error situation:
//  unwound == 0 : after catch located, before unwinding
//  unwound == 1 : after unwinding
//
    switch( dispatch.type ) {
      case DISPATCHABLE_STOP :
        if( NULL == dispatch.srch_ctl ) {
            GOOF_EXC( "DISPATCHABLE_STOP: no srch_ctl" );
        }
        switch( dispatch.srch_ctl->_state ) {
          case EXCSTATE_UNWIND :
          { _EXC_PR_FREE marker( &rt_ctl
                               , 0
                               , EXCSTATE_TERMINATE
                               , dispatch.rethrow ? 0 : rt_ctl.thr->excepts );
            CPPLIB( call_terminate )( RTMSG_THROW_DTOR, rt_ctl.thr );
          }
          case EXCSTATE_TERMINATE :
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_TERMIN, 1 );
          case EXCSTATE_CTOR :
            CPPLIB( fatal_runtime_error )( RTMSG_THROW_CTOR, 1 );
          case EXCSTATE_DTOR :
            CPPLIB( fatal_runtime_error )( RTMSG_EXC_DTOR, 1 );
          default:
            GOOF_EXC( "DISPATCHABLE_STOP: unexpected exception state" );
        }
      case DISPATCHABLE_FNEXC :
      case DISPATCHABLE_CATCH :
        if( ! unwound ) {
            ACTIVE_EXC *active; // - saved exception
            unwound = true;
            if( dispatch.rethrow ) {
// do we still need fnexc_state ?
                dispatch.exc->fnexc_state = dispatch.exc->state;
                if( dispatch.popped ) {
                    active = dispatch.exc;
                    active->cat_try = dispatch.try_cmd;
                    active->rw = dispatch.rw;
                }
            } else {
                active = CPPLIB( alloc_exc )( object
                                            , dispatch.ro
                                            , &rt_ctl );
                dispatch.exc = active;
                active->cat_try = dispatch.try_cmd;
                active->rw = dispatch.rw;
            }
            if( dispatch.type == DISPATCHABLE_FNEXC ) {
                if( dispatch.rethrow ) {
                    dispatch.exc->state = dispatch.exc->fnexc_state;
                }
                break;
            }
            dispatch.exc->state = EXCSTATE_UNWIND;
#ifdef RW_REGISTRATION
            FS_UNWIND_GLOBAL( dispatch.rw, excrec.addr, &excrec );
#endif
#ifdef PD_REGISTRATION
            CPPLIB( PdUnwind )( &excrec );
#endif
        }
        // NT returns here instead of after RAISE_EXCEPTION if
        // there are no blocks to pop
        // nb. need to execute same code as after RAISE_EXCEPTION
        CPPLIB( destruct_internal )( dispatch.state_var, dispatch.rw );
        break;
    }
//
// dispatch the exception
//
    switch( dispatch.type ) {
      case DISPATCHABLE_FNEXC :
        fneDispatch( &dispatch );
      case DISPATCHABLE_CATCH :
        catchDispatch( &dispatch );
      case DISPATCHABLE_NO_CATCH :
        if( dispatch.rethrow ) {
            CPPLIB( fatal_runtime_error )( RTMSG_RETHROW, 1 );
        } else {
          { _EXC_PR marker( &rt_ctl, 0, EXCSTATE_TERMINATE );
            CPPLIB( call_terminate )( RTMSG_NO_HANDLER, rt_ctl.thr );
          }
        }
#if 0 // not now
      case DISPATCHABLE_SYS_EXC :
      {
        char buffer[ sizeof( RTMSG_SYS_EXC ) ];
        ::memcpy( buffer, RTMSG_SYS_EXC, sizeof( buffer ) );
        ltoa( dispatch.system_exc, buffer + sizeof( buffer) - 9, 16 );
        CPPLIB( fatal_runtime_error )( buffer, 1 );
      }
#endif
      default :
        GOOF_EXC( "throw: invalid DISPATCHABLE" );
    }
}
Beispiel #7
0
static void catchDispatch(      // DISPATCH A CATCH BLOCK
    DISPATCH_EXC *dispatch )    // - dispatch control
{
    RW_DTREG* blk;              // - function block for dispatch
    DTOR_CMD* cmd;              // - try command
    jmp_buf *env;               // - addr[ jmp_buf ]
    ACTIVE_EXC *active;         // - active exception
    void *tgt;                  // - target try variable
    void *src;                  // - source address
    RT_TYPE_SIG sig;            // - signature for catch
    unsigned cnv_offset;        // - conversion offset

    blk = dispatch->rw;
    cmd = dispatch->try_cmd;
    active = dispatch->exc;
    active->state = EXCSTATE_DISPATCH;
    env = (jmp_buf*)( (char*)blk + cmd->try_cmd.jmp_buf );
    sig = cmd->try_cmd.sigs[ dispatch->catch_no ];
    if( sig != NULL ) {
        cnv_offset = dispatch->cnv_try->offset;
        src = cnv_offset + (char*)active->data;
        tgt = (char*)blk + cmd->try_cmd.offset;
        switch( sig->hdr.type ) {
          case THROBJ_PTR_CLASS :
            if( dispatch->zero ) {
                *(void**)tgt = NULL;
            } else {
                *(void**)tgt = *(char**)active->data + cnv_offset;
            }
            break;
          case THROBJ_VOID_STAR :
          case THROBJ_PTR_SCALAR :
          case THROBJ_PTR_FUN :
            if( dispatch->zero ) {
                memset( tgt, 0, sig->scalar.size );
                break;
            }
          case THROBJ_SCALAR :
            memcpy( tgt, src, sig->scalar.size );
            break;
          case THROBJ_CLASS :
            sig = throwCnvSig( dispatch );
            (*sig->clss.copyctor)( tgt, src );
            break;
          case THROBJ_CLASS_VIRT :
            sig = throwCnvSig( dispatch );
            (*sig->clss_v.copyctor)( tgt, CTOR_NULL, src );
            break;
          case THROBJ_REFERENCE :
            sig = CPPLIB( ts_refed )( sig );
            switch( sig->hdr.type ) {
              case THROBJ_PTR_CLASS :
                if( dispatch->zero ) {
                    active->extra_object = NULL;
                } else {
                    active->extra_object = *(char**)active->data + cnv_offset;
                }
                *(void**)tgt = &active->extra_object;
                break;
              case THROBJ_PTR_SCALAR :
              case THROBJ_PTR_FUN :
              case THROBJ_VOID_STAR :
                if( dispatch->zero ) {
                    active->extra_object = NULL;
                    src = &active->extra_object;
                }
              case THROBJ_SCALAR :
              case THROBJ_CLASS :
              case THROBJ_CLASS_VIRT :
                *(void**)tgt = src;
                break;
            }
            break;
          default :
            GOOF_EXC( "unexpected exception type" );
        }
    }
    longjmp( *env, dispatch->catch_no + 1 );
}