Help needed with SEH exception handler (not really Win32 specific)
Ranjit Mathew
rmathew@hotmail.com
Sun Mar 16 17:50:00 GMT 2003
Ranjit Mathew wrote:
>> Hi,
>> I'm stuck with what is essentially the same problem in trying
> to fix the SEH issues in both the GC as well as the libgcj
> win32_exception_handler( ) method, and I hope someone can shed
> some insights into it - how do I restart execution after a fault in
> a robust manner, while still being able to indicate to the OS
> that I have taken care of the error? I'll try to clarify this
I just found out about the "&&" operator that can be
used in GCC to find the address corresponding to a
label and using this I have managed to achieve the
effect needed by at least the GC.
For those curious about it, I'm attaching a simple
program that demonstrates the technique.
BTW, the exception registration works only when
declared with a local variable simply because the
kernel in Windows (9x and NT) does not trust an
exception registration found outside of a thread's
stack bounds!
Ranjit.
----------------------------- 8< -----------------------------
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <excpt.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct _my_exrec
{
EXCEPTION_REGISTRATION ex_reg;
void *hlr_addr;
} MyExRec;
EXCEPTION_DISPOSITION __cdecl
my_handler( struct _EXCEPTION_RECORD *ExceptionRecord,
void *EstablisherFrame,
struct _CONTEXT *ContextRecord,
void *DispatcherContext)
{
MyExRec *xer = (MyExRec *)EstablisherFrame;
/* Unwind from the called function assuming the standard
* function prologue.
*/
ContextRecord->Esp = ContextRecord->Ebp;
ContextRecord->Ebp = *((DWORD *)ContextRecord->Esp);
ContextRecord->Esp = ContextRecord->Esp - 8;
/* Restart execution at the handler within the caller */
ContextRecord->Eip = (DWORD )(xer->hlr_addr);
/* Tell Windows to restart the "faulting" instruction. */
return ExceptionContinueExecution;
}
int inner_foo( int x)
{
if( x == 666)
{
/* We don't like this value - protest by causing a fault! */
*(int *)0 = 0;
}
else
return x*10;
}
int foo( int x)
{
MyExRec er;
int retVal = 0;
/* Install the handler */
er.hlr_addr = &&ex_hlr;
er.ex_reg.handler = my_handler;
asm volatile ("movl %%fs:0, %0" : "=r" (er.ex_reg.prev));
asm volatile ("movl %0, %%fs:0" : : "r" (&er));
retVal = inner_foo( x);
printf( "Normal Execution!\n");
/* Without this redundant check, GCC considers the following code
* unreachable and eliminates it!
*/
if (er.hlr_addr != 0)
goto rm_hlr;
ex_hlr:
printf( "*** Abnormal Execution! ***\n");
retVal = x*10;
/* Fall through... */
rm_hlr:
/* Remove the handler */
asm volatile ("movl %0, %%fs:0" : : "r" (er.ex_reg.prev));
return retVal;
}
int main( int argc, char *argv[])
{
int x = 666;
if( argc > 1)
x = atoi( argv[1]);
printf( "foo( ) returned: %d\n", foo( x));
return 0;
}
----------------------------- 8< -----------------------------
--
Ranjit Mathew Email: rmathew AT hotmail DOT com
Bangalore,
INDIA. Web: http://ranjitmathew.tripod.com/
More information about the Java
mailing list