From 2c63d1d7dddfd1126e0650bc3257acb646bec57f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 22 May 2009 12:00:43 +0200 Subject: [PATCH] ntdll: Implement __C_specific_handler for x86_64. --- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/signal_x86_64.c | 78 +++++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 4b5dfecf869..484ae8e32da 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1231,6 +1231,7 @@ @ cdecl -private _CIpow() NTDLL__CIpow # @ stub _CIsin # @ stub _CIsqrt +@ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) # @ stub __isascii # @ stub __iscsym # @ stub __iscsymf diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index c9db2fea762..673c2ec5fd3 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -54,6 +54,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh); struct _DISPATCHER_CONTEXT; +typedef LONG (WINAPI *PC_LANGUAGE_EXCEPTION_HANDLER)( EXCEPTION_POINTERS *ptrs, ULONG64 frame ); typedef EXCEPTION_DISPOSITION (WINAPI *PEXCEPTION_ROUTINE)( EXCEPTION_RECORD *rec, ULONG64 frame, CONTEXT *context, @@ -73,6 +74,18 @@ typedef struct _DISPATCHER_CONTEXT ULONG ScopeIndex; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; +typedef struct _SCOPE_TABLE +{ + ULONG Count; + struct + { + ULONG BeginAddress; + ULONG EndAddress; + ULONG HandlerAddress; + ULONG JumpTarget; + } ScopeRecord[1]; +} SCOPE_TABLE, *PSCOPE_TABLE; + /*********************************************************************** * signal context platform-specific definitions @@ -322,6 +335,19 @@ static void dump_unwind_info( ULONG64 base, RUNTIME_FUNCTION *function ) } } +static void dump_scope_table( ULONG64 base, const SCOPE_TABLE *table ) +{ + unsigned int i; + + TRACE( "scope table at %p\n", table ); + for (i = 0; i < table->Count; i++) + TRACE( " %u: %lx-%lx handler %lx target %lx\n", i, + base + table->ScopeRecord[i].BeginAddress, + base + table->ScopeRecord[i].EndAddress, + base + table->ScopeRecord[i].HandlerAddress, + base + table->ScopeRecord[i].JumpTarget ); +} + /*********************************************************************** * dispatch_signal */ @@ -1455,7 +1481,6 @@ void WINAPI RtlUnwindEx( ULONG64 frame, ULONG64 target_ip, EXCEPTION_RECORD *rec rec->ExceptionFlags |= EH_UNWINDING | (frame ? 0 : EH_EXIT_UNWIND); FIXME( "code=%x flags=%x not implemented on x86_64\n", rec->ExceptionCode, rec->ExceptionFlags ); - NtTerminateProcess( GetCurrentProcess(), 1 ); } @@ -1470,6 +1495,57 @@ void WINAPI __regs_RtlUnwind( ULONG64 frame, ULONG64 target_ip, EXCEPTION_RECORD DEFINE_REGS_ENTRYPOINT( RtlUnwind, 4 ) +/******************************************************************* + * __C_specific_handler (NTDLL.@) + */ +EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, + ULONG64 frame, + CONTEXT *context, + struct _DISPATCHER_CONTEXT *dispatch ) +{ + SCOPE_TABLE *table = dispatch->HandlerData; + ULONG i; + + TRACE( "%p %lx %p %p\n", rec, frame, context, dispatch ); + if (TRACE_ON(seh)) dump_scope_table( dispatch->ImageBase, table ); + + if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) /* FIXME */ + return ExceptionContinueSearch; + + for (i = 0; i < table->Count; i++) + { + if (context->Rip >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress && + context->Rip < dispatch->ImageBase + table->ScopeRecord[i].EndAddress) + { + if (!table->ScopeRecord[i].JumpTarget) continue; + if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER) + { + EXCEPTION_POINTERS ptrs; + PC_LANGUAGE_EXCEPTION_HANDLER filter; + + filter = (PC_LANGUAGE_EXCEPTION_HANDLER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress); + ptrs.ExceptionRecord = rec; + ptrs.ContextRecord = context; + TRACE( "calling filter %p ptrs %p frame %lx\n", filter, &ptrs, frame ); + switch (filter( &ptrs, frame )) + { + case EXCEPTION_EXECUTE_HANDLER: + break; + case EXCEPTION_CONTINUE_SEARCH: + continue; + case EXCEPTION_CONTINUE_EXECUTION: + return ExceptionContinueExecution; + } + } + TRACE( "unwinding to target %lx\n", dispatch->ImageBase + table->ScopeRecord[i].JumpTarget ); + RtlUnwindEx( frame, dispatch->ImageBase + table->ScopeRecord[i].JumpTarget, + rec, 0, context, dispatch->HistoryTable ); + } + } + return ExceptionContinueSearch; +} + + /******************************************************************* * NtRaiseException (NTDLL.@) */