Oops, I misunderstood the purpose of the new frame.
Here's a piece of an article, http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/exception/excep..., figure 14 (KiUserExceptionDispatcher Pseudocode):
int ExecuteHandler( PEXCEPTION_RECORD pExcptRec PEXCEPTION_REGISTRATION pExcptReg CONTEXT * pContext PVOID pDispatcherContext, FARPROC handler ) // Really a ptr to an _except_handler() { // Set up an EXCEPTION_REGISTRATION, where EDX points to the // appropriate handler code shown below PUSH EDX PUSH FS:[0] MOV FS:[0],ESP
// Invoke the exception callback function EAX = handler( pExcptRec, pExcptReg, pContext, pDispatcherContext );
// Remove the minimal EXCEPTION_REGISTRATION frame MOV ESP,DWORD PTR FS:[00000000] POP DWORD PTR FS:[00000000]
return EAX; }
So based on that, I think this is the final code:
// prologue: save esp, ebp and ecx.
push ebp push ecx mov ebp, esp mov ecx, [ebp+1C] // handler
// create a new exception record on the stack // to catch exceptions in the exception handler.
push [ebp+20] // nested_handler push fs:[00000000] // previous frame pointer
// set the new frame to point at that record
mov fs:[00000000], esp
// call the handler
push [ebp+18] // dispatcher push [ebp+14] // context push [ebp+10] // frame push [ebp+0C] // record call ecx // exact instruction required by Shrinker
// eax now contains the return code from the exception handler. // Restore the stack.
mov esp, fs:[00000000] // exact instruction required by Shrinker
// pop off the previous frame to be the current frame.
pop fs:[00000000]
// epilogue: restore esp, ebp and ecx
mov esp, ebp pop ecx pop ebp ret
Sorry for the Intel-speak rather than the GNU-speak, but I was brought up on x86 assembly in DOS :P
That should do it. I'm going to code this up to see if it works and doesn't kill my system! But first I need to brush up on GNU-assembly :)
--Rob