X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=tests%2Fwin32-stack-unwind.c;h=fd93aa2a2b3932b781867dbf2b23bae3a1a08bb2;hb=d7875c296a4988e9f27e2776237884deb1984c62;hp=4ed4aa80b05bc447507f3386667714a13095c120;hpb=45b5a21316381ecab98a0e5a5296294e044170e8;p=sbcl.git 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()) {