Alexandre Julliard : ntdll: Initial support for dispatching exceptions to stack handlers on x86_64.
Alexandre Julliard
julliard at winehq.org
Fri May 22 08:25:34 CDT 2009
Module: wine
Branch: master
Commit: ad7b2824395fe10038bbfc47f66b5e50ddd5b7c1
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ad7b2824395fe10038bbfc47f66b5e50ddd5b7c1
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri May 22 11:52:13 2009 +0200
ntdll: Initial support for dispatching exceptions to stack handlers on x86_64.
---
dlls/ntdll/signal_x86_64.c | 109 +++++++++++++++++++++++++++++++++++++++++--
1 files changed, 103 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index cc65dc8..c9db2fe 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -52,6 +52,27 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh);
+struct _DISPATCHER_CONTEXT;
+
+typedef EXCEPTION_DISPOSITION (WINAPI *PEXCEPTION_ROUTINE)( EXCEPTION_RECORD *rec,
+ ULONG64 frame,
+ CONTEXT *context,
+ struct _DISPATCHER_CONTEXT *dispatch );
+
+typedef struct _DISPATCHER_CONTEXT
+{
+ ULONG64 ControlPc;
+ ULONG64 ImageBase;
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG64 EstablisherFrame;
+ ULONG64 TargetIp;
+ PCONTEXT ContextRecord;
+ PEXCEPTION_ROUTINE LanguageHandler;
+ PVOID HandlerData;
+ PUNWIND_HISTORY_TABLE HistoryTable;
+ ULONG ScopeIndex;
+} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
+
/***********************************************************************
* signal context platform-specific definitions
@@ -649,15 +670,92 @@ static RUNTIME_FUNCTION *find_function_info( ULONG64 pc, HMODULE module,
*
* Call the stack handlers chain.
*/
-static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
+static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{
EXCEPTION_POINTERS ptrs;
+ UNWIND_HISTORY_TABLE table;
+ ULONG64 frame;
+ RUNTIME_FUNCTION *dir, *info;
+ PEXCEPTION_ROUTINE handler;
+ DISPATCHER_CONTEXT dispatch;
+ CONTEXT context, new_context;
+ LDR_MODULE *module;
+ DWORD size;
+
+ context = *orig_context;
+ for (;;)
+ {
+ /* FIXME: should use the history table to make things faster */
+
+ if (LdrFindEntryForAddress( (void *)context.Rip, &module ))
+ {
+ ERR( "no module found for rip %p, can't dispatch exception\n", (void *)context.Rip );
+ break;
+ }
+ if (!(dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size )))
+ {
+ ERR( "module %s doesn't contain exception data, can't dispatch exception\n",
+ debugstr_w(module->BaseDllName.Buffer) );
+ break;
+ }
+ if (!(info = find_function_info( context.Rip, module->BaseAddress, dir, size )))
+ {
+ /* leaf function */
+ context.Rip = *(ULONG64 *)context.Rsp;
+ context.Rsp += sizeof(ULONG64);
+ continue;
+ }
+
+ new_context = context;
- FIXME( "not implemented on x86_64\n" );
+ handler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, (ULONG64)module->BaseAddress, context.Rip,
+ info, &new_context, &dispatch.HandlerData, &frame, NULL );
+
+ if ((frame & 7) ||
+ frame < (ULONG64)NtCurrentTeb()->Tib.StackLimit ||
+ frame >= (ULONG64)NtCurrentTeb()->Tib.StackBase)
+ {
+ ERR( "invalid frame %lx\n", frame );
+ rec->ExceptionFlags |= EH_STACK_INVALID;
+ break;
+ }
+
+ if (handler)
+ {
+ dispatch.ControlPc = context.Rip;
+ dispatch.ImageBase = (ULONG64)module->BaseAddress;
+ dispatch.FunctionEntry = info;
+ dispatch.EstablisherFrame = frame;
+ dispatch.TargetIp = 0; /* FIXME */
+ dispatch.ContextRecord = &context;
+ dispatch.LanguageHandler = handler;
+ dispatch.HistoryTable = &table;
+ dispatch.ScopeIndex = 0; /* FIXME */
+
+ TRACE( "calling handler %p (rec=%p, frame=%lx context=%p, dispatch=%p)\n",
+ handler, rec, frame, &context, &dispatch );
+
+ switch( handler( rec, frame, &context, &dispatch ))
+ {
+ case ExceptionContinueExecution:
+ if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION;
+ *orig_context = context;
+ return STATUS_SUCCESS;
+ case ExceptionContinueSearch:
+ break;
+ case ExceptionNestedException:
+ break;
+ default:
+ return STATUS_INVALID_DISPOSITION;
+ }
+ }
+ context = new_context;
+ }
/* hack: call unhandled exception filter directly */
ptrs.ExceptionRecord = rec;
- ptrs.ContextRecord = context;
+ ptrs.ContextRecord = orig_context;
unhandled_exception_filter( &ptrs );
return STATUS_UNHANDLED_EXCEPTION;
}
@@ -679,7 +777,7 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
TRACE( "code=%x flags=%x addr=%p ip=%lx tid=%04x\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
context->Rip, GetCurrentThreadId() );
- for (c = 0; c < rec->NumberParameters; c++)
+ for (c = 0; c < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); c++)
TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
{
@@ -1241,8 +1339,7 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
unsigned int i, prolog_offset;
TRACE( "type %x rip %lx rsp %lx\n", type, pc, context->Rsp );
-
- dump_unwind_info( base, function );
+ if (TRACE_ON(seh)) dump_unwind_info( base, function );
frame = *frame_ret = context->Rsp;
for (;;)
More information about the wine-cvs
mailing list