Commit 5c984129 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Also copy non-volatile regs on collided unwind.

parent 6f55a131
...@@ -164,15 +164,18 @@ EXCEPTION_DISPOSITION WINAPI unwind_exception_handler( EXCEPTION_RECORD *record, ...@@ -164,15 +164,18 @@ EXCEPTION_DISPOSITION WINAPI unwind_exception_handler( EXCEPTION_RECORD *record,
DISPATCHER_CONTEXT *orig_dispatch = ((DISPATCHER_CONTEXT **)frame)[-2]; DISPATCHER_CONTEXT *orig_dispatch = ((DISPATCHER_CONTEXT **)frame)[-2];
/* copy the original dispatcher into the current one, except for the TargetIp */ /* copy the original dispatcher into the current one, except for the TargetIp */
dispatch->ControlPc = orig_dispatch->ControlPc; dispatch->ControlPc = orig_dispatch->ControlPc;
dispatch->ImageBase = orig_dispatch->ImageBase; dispatch->ImageBase = orig_dispatch->ImageBase;
dispatch->FunctionEntry = orig_dispatch->FunctionEntry; dispatch->FunctionEntry = orig_dispatch->FunctionEntry;
dispatch->EstablisherFrame = orig_dispatch->EstablisherFrame; dispatch->EstablisherFrame = orig_dispatch->EstablisherFrame;
dispatch->ContextRecord = orig_dispatch->ContextRecord; dispatch->LanguageHandler = orig_dispatch->LanguageHandler;
dispatch->LanguageHandler = orig_dispatch->LanguageHandler; dispatch->HandlerData = orig_dispatch->HandlerData;
dispatch->HandlerData = orig_dispatch->HandlerData; dispatch->HistoryTable = orig_dispatch->HistoryTable;
dispatch->HistoryTable = orig_dispatch->HistoryTable; dispatch->ScopeIndex = orig_dispatch->ScopeIndex;
dispatch->ScopeIndex = orig_dispatch->ScopeIndex; dispatch->ControlPcIsUnwound = orig_dispatch->ControlPcIsUnwound;
*dispatch->ContextRecord = *orig_dispatch->ContextRecord;
memcpy( dispatch->NonVolatileRegisters, orig_dispatch->NonVolatileRegisters,
sizeof(DISPATCHER_CONTEXT_NONVOLREG_ARM) );
TRACE( "detected collided unwind\n" ); TRACE( "detected collided unwind\n" );
return ExceptionCollidedUnwind; return ExceptionCollidedUnwind;
} }
...@@ -319,6 +322,7 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) ...@@ -319,6 +322,7 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
DISPATCHER_CONTEXT dispatch; DISPATCHER_CONTEXT dispatch;
CONTEXT context; CONTEXT context;
NTSTATUS status; NTSTATUS status;
ULONG_PTR frame;
context = *orig_context; context = *orig_context;
dispatch.TargetPc = 0; dispatch.TargetPc = 0;
...@@ -355,16 +359,11 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) ...@@ -355,16 +359,11 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
rec->ExceptionFlags |= EXCEPTION_NESTED_CALL; rec->ExceptionFlags |= EXCEPTION_NESTED_CALL;
TRACE( "nested exception\n" ); TRACE( "nested exception\n" );
break; break;
case ExceptionCollidedUnwind: { case ExceptionCollidedUnwind:
ULONG_PTR frame;
context = *dispatch.ContextRecord;
dispatch.ContextRecord = &context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&context, (PVOID *)&dispatch.HandlerData, &frame, NULL ); &context, (PVOID *)&dispatch.HandlerData, &frame, NULL );
goto unwind_done; goto unwind_done;
}
default: default:
return STATUS_INVALID_DISPOSITION; return STATUS_INVALID_DISPOSITION;
} }
...@@ -386,17 +385,12 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) ...@@ -386,17 +385,12 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
rec->ExceptionFlags |= EXCEPTION_NESTED_CALL; rec->ExceptionFlags |= EXCEPTION_NESTED_CALL;
TRACE( "nested exception\n" ); TRACE( "nested exception\n" );
break; break;
case ExceptionCollidedUnwind: { case ExceptionCollidedUnwind:
ULONG_PTR frame;
context = *dispatch.ContextRecord;
dispatch.ContextRecord = &context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&context, (PVOID *)&dispatch.HandlerData, &frame, NULL ); &context, (PVOID *)&dispatch.HandlerData, &frame, NULL );
teb_frame = teb_frame->Prev; teb_frame = teb_frame->Prev;
goto unwind_done; goto unwind_done;
}
default: default:
return STATUS_INVALID_DISPOSITION; return STATUS_INVALID_DISPOSITION;
} }
...@@ -562,6 +556,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec ...@@ -562,6 +556,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
DISPATCHER_CONTEXT dispatch; DISPATCHER_CONTEXT dispatch;
CONTEXT new_context; CONTEXT new_context;
NTSTATUS status; NTSTATUS status;
ULONG_PTR frame;
DWORD i; DWORD i;
RtlCaptureContext( context ); RtlCaptureContext( context );
...@@ -617,10 +612,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec ...@@ -617,10 +612,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
if (dispatch.EstablisherFrame == (DWORD)end_frame) rec->ExceptionFlags |= EXCEPTION_TARGET_UNWIND; if (dispatch.EstablisherFrame == (DWORD)end_frame) rec->ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
if (call_unwind_handler( rec, &dispatch ) == ExceptionCollidedUnwind) if (call_unwind_handler( rec, &dispatch ) == ExceptionCollidedUnwind)
{ {
ULONG_PTR frame; new_context = *context;
*context = new_context = *dispatch.ContextRecord;
dispatch.ContextRecord = context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&new_context, &dispatch.HandlerData, &frame, &new_context, &dispatch.HandlerData, &frame,
...@@ -641,12 +633,8 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec ...@@ -641,12 +633,8 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
dispatch.EstablisherFrame = (DWORD)teb_frame; dispatch.EstablisherFrame = (DWORD)teb_frame;
if (call_teb_unwind_handler( rec, &dispatch, teb_frame ) == ExceptionCollidedUnwind) if (call_teb_unwind_handler( rec, &dispatch, teb_frame ) == ExceptionCollidedUnwind)
{ {
ULONG_PTR frame;
teb_frame = __wine_pop_frame( teb_frame ); teb_frame = __wine_pop_frame( teb_frame );
new_context = *context;
*context = new_context = *dispatch.ContextRecord;
dispatch.ContextRecord = context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&new_context, &dispatch.HandlerData, &new_context, &dispatch.HandlerData,
......
...@@ -184,15 +184,18 @@ EXCEPTION_DISPOSITION WINAPI unwind_exception_handler( EXCEPTION_RECORD *record, ...@@ -184,15 +184,18 @@ EXCEPTION_DISPOSITION WINAPI unwind_exception_handler( EXCEPTION_RECORD *record,
DISPATCHER_CONTEXT *orig_dispatch = ((DISPATCHER_CONTEXT **)frame)[-2]; DISPATCHER_CONTEXT *orig_dispatch = ((DISPATCHER_CONTEXT **)frame)[-2];
/* copy the original dispatcher into the current one, except for the TargetPc */ /* copy the original dispatcher into the current one, except for the TargetPc */
dispatch->ControlPc = orig_dispatch->ControlPc; dispatch->ControlPc = orig_dispatch->ControlPc;
dispatch->ImageBase = orig_dispatch->ImageBase; dispatch->ImageBase = orig_dispatch->ImageBase;
dispatch->FunctionEntry = orig_dispatch->FunctionEntry; dispatch->FunctionEntry = orig_dispatch->FunctionEntry;
dispatch->EstablisherFrame = orig_dispatch->EstablisherFrame; dispatch->EstablisherFrame = orig_dispatch->EstablisherFrame;
dispatch->ContextRecord = orig_dispatch->ContextRecord; dispatch->LanguageHandler = orig_dispatch->LanguageHandler;
dispatch->LanguageHandler = orig_dispatch->LanguageHandler; dispatch->HandlerData = orig_dispatch->HandlerData;
dispatch->HandlerData = orig_dispatch->HandlerData; dispatch->HistoryTable = orig_dispatch->HistoryTable;
dispatch->HistoryTable = orig_dispatch->HistoryTable; dispatch->ScopeIndex = orig_dispatch->ScopeIndex;
dispatch->ScopeIndex = orig_dispatch->ScopeIndex; dispatch->ControlPcIsUnwound = orig_dispatch->ControlPcIsUnwound;
*dispatch->ContextRecord = *orig_dispatch->ContextRecord;
memcpy( dispatch->NonVolatileRegisters, orig_dispatch->NonVolatileRegisters,
sizeof(DISPATCHER_CONTEXT_NONVOLREG_ARM64) );
TRACE( "detected collided unwind\n" ); TRACE( "detected collided unwind\n" );
return ExceptionCollidedUnwind; return ExceptionCollidedUnwind;
} }
...@@ -345,6 +348,7 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) ...@@ -345,6 +348,7 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
DISPATCHER_CONTEXT dispatch; DISPATCHER_CONTEXT dispatch;
CONTEXT context; CONTEXT context;
NTSTATUS status; NTSTATUS status;
ULONG_PTR frame;
context = *orig_context; context = *orig_context;
dispatch.TargetPc = 0; dispatch.TargetPc = 0;
...@@ -381,16 +385,11 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) ...@@ -381,16 +385,11 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
rec->ExceptionFlags |= EXCEPTION_NESTED_CALL; rec->ExceptionFlags |= EXCEPTION_NESTED_CALL;
TRACE( "nested exception\n" ); TRACE( "nested exception\n" );
break; break;
case ExceptionCollidedUnwind: { case ExceptionCollidedUnwind:
ULONG64 frame;
context = *dispatch.ContextRecord;
dispatch.ContextRecord = &context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&context, &dispatch.HandlerData, &frame, NULL ); &context, &dispatch.HandlerData, &frame, NULL );
goto unwind_done; goto unwind_done;
}
default: default:
return STATUS_INVALID_DISPOSITION; return STATUS_INVALID_DISPOSITION;
} }
...@@ -412,17 +411,12 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) ...@@ -412,17 +411,12 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
rec->ExceptionFlags |= EXCEPTION_NESTED_CALL; rec->ExceptionFlags |= EXCEPTION_NESTED_CALL;
TRACE( "nested exception\n" ); TRACE( "nested exception\n" );
break; break;
case ExceptionCollidedUnwind: { case ExceptionCollidedUnwind:
ULONG64 frame;
context = *dispatch.ContextRecord;
dispatch.ContextRecord = &context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&context, &dispatch.HandlerData, &frame, NULL ); &context, &dispatch.HandlerData, &frame, NULL );
teb_frame = teb_frame->Prev; teb_frame = teb_frame->Prev;
goto unwind_done; goto unwind_done;
}
default: default:
return STATUS_INVALID_DISPOSITION; return STATUS_INVALID_DISPOSITION;
} }
...@@ -638,6 +632,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec ...@@ -638,6 +632,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
DISPATCHER_CONTEXT dispatch; DISPATCHER_CONTEXT dispatch;
CONTEXT new_context; CONTEXT new_context;
NTSTATUS status; NTSTATUS status;
ULONG_PTR frame;
DWORD i; DWORD i;
RtlCaptureContext( context ); RtlCaptureContext( context );
...@@ -693,10 +688,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec ...@@ -693,10 +688,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
if (dispatch.EstablisherFrame == (ULONG64)end_frame) rec->ExceptionFlags |= EXCEPTION_TARGET_UNWIND; if (dispatch.EstablisherFrame == (ULONG64)end_frame) rec->ExceptionFlags |= EXCEPTION_TARGET_UNWIND;
if (call_unwind_handler( rec, &dispatch ) == ExceptionCollidedUnwind) if (call_unwind_handler( rec, &dispatch ) == ExceptionCollidedUnwind)
{ {
ULONG64 frame; new_context = *context;
*context = new_context = *dispatch.ContextRecord;
dispatch.ContextRecord = context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&new_context, &dispatch.HandlerData, &frame, &new_context, &dispatch.HandlerData, &frame,
...@@ -717,12 +709,8 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec ...@@ -717,12 +709,8 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
dispatch.EstablisherFrame = (ULONG64)teb_frame; dispatch.EstablisherFrame = (ULONG64)teb_frame;
if (call_teb_unwind_handler( rec, &dispatch, teb_frame ) == ExceptionCollidedUnwind) if (call_teb_unwind_handler( rec, &dispatch, teb_frame ) == ExceptionCollidedUnwind)
{ {
ULONG64 frame;
teb_frame = __wine_pop_frame( teb_frame ); teb_frame = __wine_pop_frame( teb_frame );
new_context = *context;
*context = new_context = *dispatch.ContextRecord;
dispatch.ContextRecord = context;
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
dispatch.ControlPc, dispatch.FunctionEntry, dispatch.ControlPc, dispatch.FunctionEntry,
&new_context, &dispatch.HandlerData, &new_context, &dispatch.HandlerData,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment