From: Victor Chiletto v@hnn.net.br
This is a small thunk to rewind that preserves the first argument passed. This is needed because on some versions of GCC, rewind's call to _unlock_file is tail-call optimized, which modifies the stack. --- dlls/msvcrt/file.c | 13 +++++++++++++ dlls/ucrtbase/tests/misc.c | 2 +- dlls/ucrtbase/ucrtbase.spec | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index e72784eef41..14018e7cda9 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -45,6 +45,10 @@
#include "wine/debug.h"
+#if defined (__i386__) +#include "wine/asm.h" +#endif + WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
#undef _fstat @@ -1658,6 +1662,15 @@ int CDECL clearerr_s(FILE* file) return 0; }
+#if defined(__i386__) +/* INTERNAL: stack preserving thunk for rewind */ +__ASM_GLOBAL_FUNC(wine_i386_rewind, + "pushl 4(%esp)\n\t" + "call "__ASM_NAME("rewind") "\n\t" + "popl %eax\n\t" + "ret") +#endif + /********************************************************************* * rewind (MSVCRT.@) */ diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c index 17b1dca4fcf..67ba567472b 100644 --- a/dlls/ucrtbase/tests/misc.c +++ b/dlls/ucrtbase/tests/misc.c @@ -1610,7 +1610,7 @@ static void test_rewind_i386_abi(void) } #endif
- todo_wine ok(fp == fp2, "rewind modified the first argument in the stack\n"); + ok(fp == fp2, "rewind modified the first argument in the stack\n");
fclose(fp); } diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index cad6cf1c381..088fafa8494 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2470,7 +2470,8 @@ @ cdecl remquof(float float ptr) @ cdecl remquol(double double ptr) remquo @ cdecl rename(str str) -@ cdecl rewind(ptr) +@ cdecl -arch=i386 rewind(ptr) wine_i386_rewind +@ cdecl -arch=!i386 rewind(ptr) rewind @ cdecl rint(double) MSVCRT_rint @ cdecl rintf(float) @ cdecl rintl(double) MSVCRT_rint