This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Help needed with SEH exception handler (not really Win32 specific)


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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]