dlls/ntdll/signal_x86_64.c
/**********************************************************************
 *           call_stack_handlers
 *
 * Call the stack handlers chain.
 */
call_stack_handlers
Call the stack handlers chain.
call_stack_handlers Call the stack handlers chain .
static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{
    EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
    UNWIND_HISTORY_TABLE table;
    DISPATCHER_CONTEXT dispatch;
    CONTEXT context, new_context;
    LDR_MODULE *module;
    DWORD size;
    NTSTATUS status;
    context = *orig_context;
    dispatch.TargetIp      = 0;
    dispatch.ContextRecord = &context;
    dispatch.HistoryTable  = &table;
    dispatch.ScopeIndex    = 0; 
    for (;;)
    {
        new_context = context;
        module = NULL;
        dispatch.ImageBase = 0;
        if (!LdrFindEntryForAddress( (void *)context.Rip, &module ))
        {
            RUNTIME_FUNCTION *dir;
            dispatch.ImageBase = (ULONG64)module->BaseAddress;
            if ((dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE,
                                                     IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size )))
            {
                if ((dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress,
                                                                  dir, size )))
                {
                    dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, dispatch.ImageBase,
                                                                 context.Rip, dispatch.FunctionEntry,
                                                                 &new_context, &dispatch.HandlerData,
                                                                 &dispatch.EstablisherFrame, NULL );
                    goto unwind_done;
                }
            }
            else if (!(module->Flags & LDR_WINE_INTERNAL))
                WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) );
        }
        if (!module || (module->Flags & LDR_WINE_INTERNAL))
        {
            struct dwarf_eh_bases bases;
            const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context.Rip - 1), &bases );
            if (fde)
            {
                status = dwarf_virtual_unwind( context.Rip, &dispatch.EstablisherFrame, &new_context,
                                               fde, &bases, &dispatch.LanguageHandler, &dispatch.HandlerData );
                if (status != STATUS_SUCCESS) return status;
                dispatch.FunctionEntry = NULL;
                if (dispatch.LanguageHandler && !module)
                {
                    FIXME( "calling personality routine in system library not supported yet\n" );
                    dispatch.LanguageHandler = NULL;
                }
                goto unwind_done;
            }
        }
        new_context.Rip = *(ULONG64 *)context.Rsp;
        new_context.Rsp = context.Rsp + sizeof(ULONG64);
        dispatch.EstablisherFrame = new_context.Rsp;
        dispatch.LanguageHandler = NULL;
    unwind_done:
        if (!dispatch.EstablisherFrame) break;
        if ((dispatch.EstablisherFrame & 7) ||
            dispatch.EstablisherFrame < (ULONG64)NtCurrentTeb()->Tib.StackLimit ||
            dispatch.EstablisherFrame > (ULONG64)NtCurrentTeb()->Tib.StackBase)
        {
            ERR( "invalid frame %lx (%p-%p)\n", dispatch.EstablisherFrame,
                 NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
            rec->ExceptionFlags |= EH_STACK_INVALID;
            break;
        }
        if (dispatch.LanguageHandler)
        {
            status = call_handler( rec, &dispatch, orig_context );
            if (status != STATUS_UNHANDLED_EXCEPTION) return status;
        }
        else while ((ULONG64)teb_frame < new_context.Rsp)
        {
            TRACE( "found wine frame %p rsp %lx handler %p\n",
                   teb_frame, new_context.Rsp, teb_frame->Handler );
            dispatch.EstablisherFrame = (ULONG64)teb_frame;
            context = *orig_context;
            status = call_teb_handler( rec, &dispatch, teb_frame, orig_context );
            if (status != STATUS_UNHANDLED_EXCEPTION) return status;
            teb_frame = teb_frame->Prev;
        }
        if (new_context.Rsp == (ULONG64)NtCurrentTeb()->Tib.StackBase) break;
        context = new_context;
    }
    return STATUS_UNHANDLED_EXCEPTION;
}
static NTSTATUS call_stack_handlers ( EXCEPTION_RECORD * rec , CONTEXT * orig_context ) { EXCEPTION_REGISTRATION_RECORD * teb_frame = NtCurrentTeb ( ) -> Tib . ExceptionList ; UNWIND_HISTORY_TABLE table ; DISPATCHER_CONTEXT dispatch ; CONTEXT context , new_context ; LDR_MODULE * module ; DWORD size ; NTSTATUS status ; context = * orig_context ; dispatch . TargetIp = 0 ; dispatch . ContextRecord = & context ; dispatch . HistoryTable = & table ; dispatch . ScopeIndex = 0 ; for ( ; ; ) { new_context = context ; module = NULL ; dispatch . ImageBase = 0 ; if ( ! LdrFindEntryForAddress ( ( void * ) context . Rip , & module ) ) { RUNTIME_FUNCTION * dir ; dispatch . ImageBase = ( ULONG64 ) module -> BaseAddress ; if ( ( dir = RtlImageDirectoryEntryToData ( module -> BaseAddress , TRUE , IMAGE_DIRECTORY_ENTRY_EXCEPTION , & size ) ) ) { if ( ( dispatch . FunctionEntry = find_function_info ( context . Rip , module -> BaseAddress , dir , size ) ) ) { dispatch . LanguageHandler = RtlVirtualUnwind ( UNW_FLAG_EHANDLER , dispatch . ImageBase , context . Rip , dispatch . FunctionEntry , & new_context , & dispatch . HandlerData , & dispatch . EstablisherFrame , NULL ) ; goto unwind_done ; } } else if ( ! ( module -> Flags & LDR_WINE_INTERNAL ) ) WARN ( " \n " , debugstr_w ( module -> BaseDllName . Buffer ) ) ; } if ( ! module || ( module -> Flags & LDR_WINE_INTERNAL ) ) { struct dwarf_eh_bases bases ; const struct dwarf_fde * fde = _Unwind_Find_FDE ( ( void * ) ( context . Rip - 1 ) , & bases ) ; if ( fde ) { status = dwarf_virtual_unwind ( context . Rip , & dispatch . EstablisherFrame , & new_context , fde , & bases , & dispatch . LanguageHandler , & dispatch . HandlerData ) ; if ( status != STATUS_SUCCESS ) return status ; dispatch . FunctionEntry = NULL ; if ( dispatch . LanguageHandler && ! module ) { FIXME ( " \n " ) ; dispatch . LanguageHandler = NULL ; } goto unwind_done ; } } new_context . Rip = * ( ULONG64 * ) context . Rsp ; new_context . Rsp = context . Rsp + sizeof ( ULONG64 ) ; dispatch . EstablisherFrame = new_context . Rsp ; dispatch . LanguageHandler = NULL ; unwind_done : if ( ! dispatch . EstablisherFrame ) break ; if ( ( dispatch . EstablisherFrame & 7 ) || dispatch . EstablisherFrame < ( ULONG64 ) NtCurrentTeb ( ) -> Tib . StackLimit || dispatch . EstablisherFrame > ( ULONG64 ) NtCurrentTeb ( ) -> Tib . StackBase ) { ERR ( " \n " , dispatch . EstablisherFrame , NtCurrentTeb ( ) -> Tib . StackLimit , NtCurrentTeb ( ) -> Tib . StackBase ) ; rec -> ExceptionFlags |= EH_STACK_INVALID ; break ; } if ( dispatch . LanguageHandler ) { status = call_handler ( rec , & dispatch , orig_context ) ; if ( status != STATUS_UNHANDLED_EXCEPTION ) return status ; } else while ( ( ULONG64 ) teb_frame < new_context . Rsp ) { TRACE ( " \n " , teb_frame , new_context . Rsp , teb_frame -> Handler ) ; dispatch . EstablisherFrame = ( ULONG64 ) teb_frame ; context = * orig_context ; status = call_teb_handler ( rec , & dispatch , teb_frame , orig_context ) ; if ( status != STATUS_UNHANDLED_EXCEPTION ) return status ; teb_frame = teb_frame -> Prev ; } if ( new_context . Rsp == ( ULONG64 ) NtCurrentTeb ( ) -> Tib . StackBase ) break ; context = new_context ; } return STATUS_UNHANDLED_EXCEPTION ; }
call_stack_handlers
 Call the stack handlers chain.
call_stack_handlers Call the stack handlers chain .
/* FIXME */ /* FIXME: should use the history table to make things faster */ /* first look for PE exception information */ /* then look for host system exception information */ /* no exception information, treat as a leaf function */ /* hack: call wine handlers registered in the tib list */