Alexandre Julliard : ntdll: Add support for calling the TEB exception chain handlers on x86_64.
Alexandre Julliard
julliard at winehq.org
Thu Jun 18 09:11:33 CDT 2009
Module: wine
Branch: master
Commit: 98b8160b7321816649460f9ff831bfb21d321e92
URL: http://source.winehq.org/git/wine.git/?a=commit;h=98b8160b7321816649460f9ff831bfb21d321e92
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Jun 17 19:39:41 2009 +0200
ntdll: Add support for calling the TEB exception chain handlers on x86_64.
---
dlls/ntdll/signal_x86_64.c | 90 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 5e67398..83b84dc 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -1447,12 +1447,47 @@ static NTSTATUS call_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatc
/**********************************************************************
+ * call_teb_handler
+ *
+ * Call a single exception handler from the TEB chain.
+ * FIXME: Handle nested exceptions.
+ */
+static NTSTATUS call_teb_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch,
+ EXCEPTION_REGISTRATION_RECORD *teb_frame, CONTEXT *orig_context )
+{
+ EXCEPTION_REGISTRATION_RECORD *dispatcher;
+ DWORD res;
+
+ TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatcher=%p)\n",
+ teb_frame->Handler, rec, teb_frame, dispatch->ContextRecord, &dispatcher );
+ res = teb_frame->Handler( rec, teb_frame, dispatch->ContextRecord, &dispatcher );
+ TRACE( "handler at %p returned %u\n", teb_frame->Handler, res );
+
+ switch (res)
+ {
+ case ExceptionContinueExecution:
+ if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION;
+ *orig_context = *dispatch->ContextRecord;
+ return STATUS_SUCCESS;
+ case ExceptionContinueSearch:
+ break;
+ case ExceptionNestedException:
+ break;
+ default:
+ return STATUS_INVALID_DISPOSITION;
+ }
+ return STATUS_UNHANDLED_EXCEPTION;
+}
+
+
+/**********************************************************************
* 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;
RUNTIME_FUNCTION *dir;
DISPATCHER_CONTEXT dispatch;
@@ -1542,6 +1577,17 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
status = call_handler( rec, &dispatch, orig_context );
if (status != STATUS_UNHANDLED_EXCEPTION) return status;
}
+ /* hack: call wine handlers registered in the tib list */
+ 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;
@@ -2239,12 +2285,44 @@ static void call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *disp
}
+/**********************************************************************
+ * call_teb_unwind_handler
+ *
+ * Call a single unwind handler from the TEB chain.
+ * FIXME: Handle nested exceptions.
+ */
+static void call_teb_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch,
+ EXCEPTION_REGISTRATION_RECORD *teb_frame )
+{
+ EXCEPTION_REGISTRATION_RECORD *dispatcher;
+ DWORD res;
+
+ TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatcher=%p)\n",
+ teb_frame->Handler, rec, teb_frame, dispatch->ContextRecord, &dispatcher );
+ res = teb_frame->Handler( rec, teb_frame, dispatch->ContextRecord, &dispatcher );
+ TRACE( "handler at %p returned %u\n", teb_frame->Handler, res );
+
+ switch (res)
+ {
+ case ExceptionContinueSearch:
+ break;
+ case ExceptionCollidedUnwind:
+ FIXME( "ExceptionCollidedUnwind not supported yet\n" );
+ break;
+ default:
+ raise_status( STATUS_INVALID_DISPOSITION, rec );
+ break;
+ }
+}
+
+
/*******************************************************************
* RtlUnwindEx (NTDLL.@)
*/
void WINAPI RtlUnwindEx( ULONG64 end_frame, ULONG64 target_ip, EXCEPTION_RECORD *rec,
ULONG64 retval, CONTEXT *orig_context, UNWIND_HISTORY_TABLE *table )
{
+ EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
EXCEPTION_RECORD record;
RUNTIME_FUNCTION *dir;
DISPATCHER_CONTEXT dispatch;
@@ -2364,6 +2442,18 @@ void WINAPI RtlUnwindEx( ULONG64 end_frame, ULONG64 target_ip, EXCEPTION_RECORD
}
call_unwind_handler( rec, &dispatch );
}
+ else /* hack: call builtin handlers registered in the tib list */
+ {
+ while ((ULONG64)teb_frame < new_context.Rsp && (ULONG64)teb_frame < end_frame)
+ {
+ TRACE( "found builtin frame %p handler %p\n", teb_frame, teb_frame->Handler );
+ dispatch.EstablisherFrame = (ULONG64)teb_frame;
+ call_teb_unwind_handler( rec, &dispatch, teb_frame );
+ teb_frame = __wine_pop_frame( teb_frame );
+ }
+ if ((ULONG64)teb_frame == end_frame && end_frame < new_context.Rsp) break;
+ dispatch.EstablisherFrame = new_context.Rsp;
+ }
context = new_context;
}
More information about the wine-cvs
mailing list