From 372a32b53ecae0f1e9d0843f3b33bc7201f7154f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Hentschel?= Date: Fri, 15 Apr 2011 19:37:58 +0200 Subject: [PATCH] ntdll: Implement call_stack_handlers on ARM. --- dlls/ntdll/signal_arm.c | 57 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index eb2a1b1a874..c87bb1c2f10 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -93,6 +93,16 @@ static inline int dispatch_signal(unsigned int sig) return handlers[sig](sig); } +/******************************************************************* + * is_valid_frame + */ +static inline BOOL is_valid_frame( void *frame ) +{ + if ((ULONG_PTR)frame & 3) return FALSE; + return (frame >= NtCurrentTeb()->Tib.StackLimit && + (void **)frame < (void **)NtCurrentTeb()->Tib.StackBase - 1); +} + /*********************************************************************** * save_context * @@ -305,14 +315,49 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) */ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) { - EXCEPTION_POINTERS ptrs; + EXCEPTION_REGISTRATION_RECORD *frame, *dispatch, *nested_frame; + DWORD res; - FIXME( "not implemented on ARM, exceptioncode: %x\n", rec->ExceptionCode ); + frame = NtCurrentTeb()->Tib.ExceptionList; + nested_frame = NULL; + while (frame != (EXCEPTION_REGISTRATION_RECORD*)~0UL) + { + /* Check frame address */ + if (!is_valid_frame( frame )) + { + rec->ExceptionFlags |= EH_STACK_INVALID; + break; + } - /* hack: call unhandled exception filter directly */ - ptrs.ExceptionRecord = rec; - ptrs.ContextRecord = context; - unhandled_exception_filter( &ptrs ); + /* Call handler */ + TRACE( "calling handler at %p code=%x flags=%x\n", + frame->Handler, rec->ExceptionCode, rec->ExceptionFlags ); + res = frame->Handler( rec, frame, context, &dispatch ); + TRACE( "handler at %p returned %x\n", frame->Handler, res ); + + if (frame == nested_frame) + { + /* no longer nested */ + nested_frame = NULL; + rec->ExceptionFlags &= ~EH_NESTED_CALL; + } + + switch(res) + { + case ExceptionContinueExecution: + if (!(rec->ExceptionFlags & EH_NONCONTINUABLE)) return STATUS_SUCCESS; + return STATUS_NONCONTINUABLE_EXCEPTION; + case ExceptionContinueSearch: + break; + case ExceptionNestedException: + if (nested_frame < dispatch) nested_frame = dispatch; + rec->ExceptionFlags |= EH_NESTED_CALL; + break; + default: + return STATUS_INVALID_DISPOSITION; + } + frame = frame->Prev; + } return STATUS_UNHANDLED_EXCEPTION; }