If you do a little disassembly, and see how your compiler deals with functions then you can manually do some things in inline assembler. My copy of GCC (and I'd assume therefore other versions, too) surrounds functions with:
Code: Select all
push EBP
mov EBP, ESP
; Code to allocate space for local variables on stack
; Function code
leave
ret
So it should theoretically be possible to write an exception handler with pure C by doing:
Code: Select all
void MyHandler()
{
asm volatile("pushad")
unsigned long MyExampleVar = 0;
/*
Your handler code
*/
asm volatile("popad; leave; iret")
}
Which would assemble to
Code: Select all
push EBP
mov EBP, ESP
sub ESP, 4
pushad
pushf
; Your handler code
popad
leave
iret
leave ; This line and the next are left in the binary but
ret ; are never executed - a waste of two bytes
This is a fairly ugly way of doing it and would, I suspect, be frowned upon. You'll note also that even this 'pure C' method (as I described it) still requires some assembler - this is because C doesn't support things such as directly modifying the registers, etc. It should also be noted that the above code doesn't do anything handy like get the segment values, EIP or anything at all from the erroring function - all of which are pushed by the CPU on an exception. In addition, were you to want to do a stack dump then you would need to use an ASM stub to call a C function - as you need the value of the erroring process' EBP - which is pushed and replaced with an EBP for the current function by the C compiler.
So yes, while it is possible to do it this way, it's better to have an ASM 'stub' which calls your C function (you might want to look up C calling conventions).
EDIT: A little tidying of typos
EDIT2: A few notes on constraints of this