CoreCLR since .NET 6 (https://github.com/dotnet/runtime/pull/65490) started using `CopyContext` on x86 in it's [RestoreContextSimulated](https://github.com/dotnet/runtime/blob/55fb7ef977e7d120dc12f0960edcff0739d7e...), which broke wine support. I'm not completely sure why, but I don't think its worth fixing as it's just a workaround anyways.
Instead we can just use the fact that coreclr will [load](https://github.com/dotnet/runtime/blob/55fb7ef977e7d120dc12f0960edcff0739d7e...) the undocumented and not included in any headers x86 RtlRestoreContext.
I implemented it as a simple `NtContinue` which works good enough for coreclr. The function is not used by MSVC (presumably to keep [compatibility with windows 7](https://github.com/dotnet/runtime/pull/65490#issuecomment-1043560394)) like x64/arm variants are so it shouldn't need anything else.
From: Jakub Staro�� kubastaron@hotmail.com
--- dlls/kernel32/kernel32.spec | 2 +- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/signal_i386.c | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 556156686f2..a5fa757da9f 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -1313,7 +1313,7 @@ @ stdcall RtlMoveMemory(ptr ptr long) NTDLL.RtlMoveMemory @ stdcall RtlPcToFileHeader(ptr ptr) NTDLL.RtlPcToFileHeader @ stdcall -arch=arm,arm64,x86_64 -norelay RtlRaiseException(ptr) NTDLL.RtlRaiseException -@ cdecl -arch=arm,arm64,x86_64 -import RtlRestoreContext(ptr ptr) +@ cdecl -import RtlRestoreContext(ptr ptr) @ stdcall RtlUnwind(ptr ptr ptr long) NTDLL.RtlUnwind @ stdcall -arch=arm,arm64,x86_64 RtlUnwindEx(long long ptr long ptr) NTDLL.RtlUnwindEx @ stdcall -arch=arm,arm64,x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr) NTDLL.RtlVirtualUnwind diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 299d2195800..c294490d544 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -952,7 +952,7 @@ @ stdcall RtlRemoveVectoredContinueHandler(ptr) @ stdcall RtlRemoveVectoredExceptionHandler(ptr) @ stdcall RtlResetRtlTranslations(ptr) -@ cdecl -arch=arm,arm64,x86_64 RtlRestoreContext(ptr ptr) +@ cdecl RtlRestoreContext(ptr ptr) @ stdcall RtlRestoreLastWin32Error(long) RtlSetLastWin32Error @ stub RtlRevertMemoryStream @ stub RtlRunDecodeUnicodeString diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index ae065f8c37b..8978e33e2d8 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -359,6 +359,16 @@ __ASM_STDCALL_FUNC( RtlCaptureContext, 4, __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") "ret $4" )
+/******************************************************************* + * RtlRestoreContext (NTDLL.@) + */ +void CDECL RtlRestoreContext( CONTEXT *context, EXCEPTION_RECORD *rec ) +{ + FIXME("(%p, %p): semi-stub\n", context, rec); + + TRACE( "returning to %p stack %p\n", (void *)context->Eip, (void *)context->Esp ); + NtContinue( context, FALSE ); +}
/******************************************************************* * RtlUnwind (NTDLL.@)
This probably deserves a test?
What happens to TIB exception handlers when the context is to be restored with RtlRestoreContext()? Is application supposed to pop them itself if using this function?
On 8/19/22 01:46, Jakub Staroń wrote:
From: Jakub Staroń kubastaron@hotmail.com
dlls/kernel32/kernel32.spec | 2 +- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/signal_i386.c | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 556156686f2..a5fa757da9f 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -1313,7 +1313,7 @@ @ stdcall RtlMoveMemory(ptr ptr long) NTDLL.RtlMoveMemory @ stdcall RtlPcToFileHeader(ptr ptr) NTDLL.RtlPcToFileHeader @ stdcall -arch=arm,arm64,x86_64 -norelay RtlRaiseException(ptr) NTDLL.RtlRaiseException -@ cdecl -arch=arm,arm64,x86_64 -import RtlRestoreContext(ptr ptr) +@ cdecl -import RtlRestoreContext(ptr ptr) @ stdcall RtlUnwind(ptr ptr ptr long) NTDLL.RtlUnwind @ stdcall -arch=arm,arm64,x86_64 RtlUnwindEx(long long ptr long ptr) NTDLL.RtlUnwindEx @ stdcall -arch=arm,arm64,x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr) NTDLL.RtlVirtualUnwind diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 299d2195800..c294490d544 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -952,7 +952,7 @@ @ stdcall RtlRemoveVectoredContinueHandler(ptr) @ stdcall RtlRemoveVectoredExceptionHandler(ptr) @ stdcall RtlResetRtlTranslations(ptr) -@ cdecl -arch=arm,arm64,x86_64 RtlRestoreContext(ptr ptr) +@ cdecl RtlRestoreContext(ptr ptr) @ stdcall RtlRestoreLastWin32Error(long) RtlSetLastWin32Error @ stub RtlRevertMemoryStream @ stub RtlRunDecodeUnicodeString diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index ae065f8c37b..8978e33e2d8 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -359,6 +359,16 @@ __ASM_STDCALL_FUNC( RtlCaptureContext, 4, __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") "ret $4" )
+/*******************************************************************
RtlRestoreContext (NTDLL.@)
- */
+void CDECL RtlRestoreContext( CONTEXT *context, EXCEPTION_RECORD *rec ) +{
- FIXME("(%p, %p): semi-stub\n", context, rec);
- TRACE( "returning to %p stack %p\n", (void *)context->Eip, (void *)context->Esp );
- NtContinue( context, FALSE );
+}
/*******************************************************************
RtlUnwind (NTDLL.@)
On 8/19/22 01:46, Jakub Staroń wrote:
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 556156686f2..a5fa757da9f 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -1313,7 +1313,7 @@ @ stdcall RtlMoveMemory(ptr ptr long) NTDLL.RtlMoveMemory @ stdcall RtlPcToFileHeader(ptr ptr) NTDLL.RtlPcToFileHeader @ stdcall -arch=arm,arm64,x86_64 -norelay RtlRaiseException(ptr) NTDLL.RtlRaiseException -@ cdecl -arch=arm,arm64,x86_64 -import RtlRestoreContext(ptr ptr) +@ cdecl -import RtlRestoreContext(ptr ptr) @ stdcall RtlUnwind(ptr ptr ptr long) NTDLL.RtlUnwind @ stdcall -arch=arm,arm64,x86_64 RtlUnwindEx(long long ptr long ptr) NTDLL.RtlUnwindEx @ stdcall -arch=arm,arm64,x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr) NTDLL.RtlVirtualUnwind diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 299d2195800..c294490d544 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -952,7 +952,7 @@ @ stdcall RtlRemoveVectoredContinueHandler(ptr) @ stdcall RtlRemoveVectoredExceptionHandler(ptr) @ stdcall RtlResetRtlTranslations(ptr) -@ cdecl -arch=arm,arm64,x86_64 RtlRestoreContext(ptr ptr) +@ cdecl RtlRestoreContext(ptr ptr) @ stdcall RtlRestoreLastWin32Error(long) RtlSetLastWin32Error @ stub RtlRevertMemoryStream @ stub RtlRunDecodeUnicodeString
This was already committed, but is this really correct? I'm not seeing RtlRestoreContext exported from i386 kernel32 or ntdll on my Windows 10 machine. (Maybe it's out of date, though? I have Windows 10 version 21H2, build 19044.1826.)
On 8/19/22 01:46, Jakub Staroń (@js6pak) wrote:
CoreCLR since .NET 6 (https://github.com/dotnet/runtime/pull/65490) started using `CopyContext` on x86 in it's [RestoreContextSimulated](https://github.com/dotnet/runtime/blob/55fb7ef977e7d120dc12f0960edcff0739d7e...), which broke wine support. I'm not completely sure why, but I don't think its worth fixing as it's just a workaround anyways.
It is interesting what's wrong with CopyContext. Is there any app which reproduces the issue?
It is interesting what's wrong with CopyContext.
It returns early here https://gitlab.winehq.org/wine/wine/-/blob/a34a403723661a3bf9c958c2431d58cce... and causes coreclr to failfast.
Is there any app which reproduces the issue?
I'd assume all x86 .NET 6.0 apps that use threading in anyway. I wasn't able to get a very minimal repro so I just copied over code that was causing issues for me here: https://github.com/js6pak/CoreclrWineCrash
On 8/19/22 11:57, Jakub Staroń (@js6pak) wrote:
It is interesting what's wrong with CopyContext.
It returns early here https://gitlab.winehq.org/wine/wine/-/blob/a34a403723661a3bf9c958c2431d58cce... and causes coreclr to failfast.
Is there any app which reproduces the issue?
I'd assume all x86 .NET 6.0 apps that use threading in anyway. I wasn't able to get a very minimal repro so I just copied over code that was causing issues for me here: https://github.com/js6pak/CoreclrWineCrash
Thanks.
Sorry, I don't have dot net core building toolchains in hands, is it possible to download a binary version of reproducer from somewhere? I guess it is most interesting to fix CopyContext at the first place, even if that is not used on the main path in .Net core.
Is application supposed to pop them itself if using this function?
CoreCLR's workaround [pops them](https://github.com/dotnet/runtime/blob/55fb7ef977e7d120dc12f0960edcff0739d7e...) so I guess we should aswell.
Would this work? Is there even a proper way to test this? ```c while ((DWORD)teb_frame < context->Esp) { TRACE_(seh)( "removing TEB frame: %p\n", teb_frame ); teb_frame = __wine_pop_frame( teb_frame ); } ```
This probably deserves a test?
Maybe, I don't think I'd be able to write one though.
On Fri Aug 19 17:31:41 2022 +0000, **** wrote:
Paul Gofman replied on the mailing list:
On 8/19/22 11:57, Jakub Staro�� (@js6pak) wrote: >> It is interesting what's wrong with CopyContext. > It returns early here https://gitlab.winehq.org/wine/wine/-/blob/a34a403723661a3bf9c958c2431d58cce6c392bf/dlls/ntdll/exception.c#L1001 and causes coreclr to failfast. > >> Is there any app which reproduces the issue? > I'd assume all x86 .NET 6.0 apps that use threading in anyway. > I wasn't able to get a very minimal repro so I just copied over code that was causing issues for me here: https://github.com/js6pak/CoreclrWineCrash > Thanks. Sorry, I don't have dot net core building toolchains in hands, is it possible to download a binary version of reproducer from somewhere? I guess it is most interesting to fix CopyContext at the first place, even if that is not used on the main path in .Net core. _______________________________________________ wine-gitlab mailing list -- wine-gitlab@winehq.org To unsubscribe send an email to wine-gitlab-leave@winehq.org
https://github.com/js6pak/CoreclrWineCrash/actions/runs/2891163269
Thanks, I had a brief look and I think I see what is the issue with contexts here. Current version of the .Net code calls CopyContext with extended source context (which it initialized itself previously) to the context in exception record, using source context flags. The last part changed recently and that fails now (previously it was using flag from destination context and that should've worked). Our CopyContext() behaviour is correct here, we have a test for that: if destination context is not extended context and the source context is then CopyContext should fail. The problem is that RaiseException() provides extended context in exception record (at least on current Win10 where I checked that), while our RaiseException() currently doesn't.
On 8/19/22 12:55, Jakub Staroń (@js6pak) wrote:
On Fri Aug 19 17:31:41 2022 +0000, **** wrote:
Paul Gofman replied on the mailing list:
On 8/19/22 11:57, Jakub Staroń (@js6pak) wrote: >> It is interesting what's wrong with CopyContext. > It returns early here https://gitlab.winehq.org/wine/wine/-/blob/a34a403723661a3bf9c958c2431d58cce6c392bf/dlls/ntdll/exception.c#L1001 and causes coreclr to failfast. >> Is there any app which reproduces the issue? > I'd assume all x86 .NET 6.0 apps that use threading in anyway. > I wasn't able to get a very minimal repro so I just copied over code that was causing issues for me here: https://github.com/js6pak/CoreclrWineCrash Thanks. Sorry, I don't have dot net core building toolchains in hands, is it possible to download a binary version of reproducer from somewhere? I guess it is most interesting to fix CopyContext at the first place, even if that is not used on the main path in .Net core. _______________________________________________ wine-gitlab mailing list -- wine-gitlab@winehq.org To unsubscribe send an email to wine-gitlab-leave@winehq.org
https://github.com/js6pak/CoreclrWineCrash/actions/runs/2891163269