From: David Lichteblau Date: Fri, 5 Oct 2012 17:56:45 +0000 (+0200) Subject: Do not trash registers in tests/win32-stack-unwind.c X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=e6d83d25e4cc19a43498703e2262ff1f60939f85;p=sbcl.git Do not trash registers in tests/win32-stack-unwind.c --- diff --git a/tests/win32-stack-unwind.c b/tests/win32-stack-unwind.c index 4ed4aa8..fd93aa2 100755 --- a/tests/win32-stack-unwind.c +++ b/tests/win32-stack-unwind.c @@ -34,6 +34,7 @@ #include #include +#include /* The "public" API */ @@ -83,7 +84,9 @@ EXCEPTION_DISPOSITION handle_exception(EXCEPTION_RECORD *exception_record, return ExceptionContinueSearch; } -static void invoke_callback(callback_ptr callback, DWORD *unwind_token); +static void + __attribute__((returns_twice)) + invoke_callback(callback_ptr callback, DWORD *unwind_token); asm("_invoke_callback:" "pushl %ebp; movl %esp, %ebp;" @@ -109,6 +112,22 @@ void establish_return_frame(callback_ptr callback) exception_frame[1] = handle_exception; set_seh_frame(exception_frame); + /* Do a setjmp just to explicitly spill callee-saved registers, i.e. + * the portable equivalent of: + * asm("" : : : "%esi", "%edi", "%ebx"); + * which is needed because otherwise those registers would be trashed + * following the stack unwind, and leave us with a likely crash upon + * return to call_into_c. + * + * The returns_twice attribute on invoke_callback should take care + * of this already, but does not seem to take effect, at least with + * the version of gcc I am using. + * + * Note: __builtin_setjmp, not setjmp, because only the former has + * the desired effect on the immediate call site. */ + jmp_buf env; + __builtin_setjmp(env); + invoke_callback(callback, &saved_ebp); if (exception_frame != get_seh_frame()) {