Unwinding should stop on access violation. This matches windows behavior.
From: Dylan Donnell dylan.donnell@student.griffith.ie
--- dlls/ntdll/signal_x86_64.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 3d4bd23e8ff..6aa389dacc5 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -866,6 +866,13 @@ BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature ) return feature < PROCESSOR_FEATURE_MAX && user_shared_data->ProcessorFeatures[feature]; }
+static LONG WINAPI walk_frame_chain_handler( EXCEPTION_POINTERS *eptr ) +{ + if (eptr->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) + return EXCEPTION_EXECUTE_HANDLER; + + return EXCEPTION_CONTINUE_SEARCH; +}
/************************************************************************* * RtlWalkFrameChain (NTDLL.@) @@ -882,17 +889,26 @@ ULONG WINAPI RtlWalkFrameChain( void **buffer, ULONG count, ULONG flags )
RtlCaptureContext( &context );
- for (i = 0; i < count; i++) + __TRY { - func = RtlLookupFunctionEntry( context.Rip, &base, &table ); - if (RtlVirtualUnwind2( UNW_FLAG_NHANDLER, base, context.Rip, func, &context, NULL, - &data, &frame, NULL, NULL, NULL, &handler, 0 )) - break; - if (!context.Rip) break; - if (!frame || !is_valid_frame( frame )) break; - if (context.Rsp == (ULONG_PTR)NtCurrentTeb()->Tib.StackBase) break; - if (i >= skip) buffer[num_entries++] = (void *)context.Rip; + for (i = 0; i < count; i++) + { + func = RtlLookupFunctionEntry( context.Rip, &base, &table ); + if (RtlVirtualUnwind2( UNW_FLAG_NHANDLER, base, context.Rip, func, &context, NULL, + &data, &frame, NULL, NULL, NULL, &handler, 0 )) + break; + if (!context.Rip) break; + if (!frame || !is_valid_frame( frame )) break; + if (context.Rsp == (ULONG_PTR)NtCurrentTeb()->Tib.StackBase) break; + if (i >= skip) buffer[num_entries++] = (void *)context.Rip; + } + } + __EXCEPT(walk_frame_chain_handler) + { + TRACE( "access violation when unwinding with context.Rip %p\n", (void *)context.Rip ); } + __ENDTRY + return num_entries; }