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

AltStyle によって変換されたページ (->オリジナル) /