SEH exceptions for GCC
Écrit par Vincent Richomme   
16-01-2009

Nom: mingw-seh
License
:LGPL
Plateforme : windows CE (ARM)
Téléchargement:
Code Source : in progress
Discussions
: #mingw-seh on irc://irc.freenode.net


This project aimed at implementing "table-based" SEH exception handling inside GCC(4.1.2) compiler. In a first step  we will focus  on the simplest plateform (ARM) to implement it. To understand how it works on arm platforms you can have a detailed article here .To give a general idea seh exceptions rely on two important keywords __try and __except as shown below :


int _tmain(int argc, _TCHAR* argv[])
{
       __try
      {
         INS_TRY;
      }
      __except(INS_FILTER)
      {
        INS_EXCEPT;
      }
      INS_AFTER_EXCEPT;
}

Please  note that __except( ) can hold either an expression like this :


       __try
      {
      }
      __except( puts("in filter"), EXCEPTION_EXECUTE_HANDLER )
      {
      }

or directly a filter function :

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
    puts("in filter.");
    if (code == EXCEPTION_ACCESS_VIOLATION) {
        puts("caught AV as expected.");
        return EXCEPTION_EXECUTE_HANDLER;
    }
    else {
        puts("didn't catch AV, unexpected.");
        return EXCEPTION_CONTINUE_SEARCH;
    };
}


      __try
      {
      }
      __except( filter(GetExceptionCode(), GetExceptionInformation())  )
      {
      }




Basically SEH implementation will consist in a few steps :

1) Parse __try __except or __try __finally keywords
2) Mark block holding code for __try and __except
3) if except filter is an expression, put its statements into an anonymous function
4) Generate labels corresponding to __try, __except and filter begin and end to be able to generate SCOPETABLE.


Step1 : Add support for parsing __try __except


We first need to add enum for our new keywords __try , __except and __finally

Index: gcc/gcc/c-common.h
===================================================================
--- gcc/gcc/c-common.h  (revision 183)
+++ gcc/gcc/c-common.h  (working copy)
@@ -72,6 +72,7 @@
   RID_ASM,       RID_TYPEOF,   RID_ALIGNOF,  RID_ATTRIBUTE,  RID_VA_ARG,
   RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL,      RID_CHOOSE_EXPR,
   RID_TYPES_COMPATIBLE_P,
+  RID_SEH_TRY,   RID_SEH_EXCEPT, RID_SEH_FINALLY,

   /* Too many ways of getting the name of a function as a string */
   RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME,


and then the intersting part for us seems to be done in gcc/gcc/c-parser.c in function c_parser_statement_after_labels where we could add RID_SEH_TRY case :

/* Parse a statement, other than a labeled statement.  */

static void
c_parser_statement_after_labels (c_parser *parser)
{
...
    case RID_SEH_TRY:
      c_parser_seh_try_catch_statement (parser);
      break;
    case RID_ASM:
      stmt = c_parser_asm_statement (parser);
      break;
...
}

/* Parse a SEH exception statement.

   seh-statement:
     __try statement __except (expression) statement
     __try statement __finally statement
*/


static void
c_parser_seh_try_catch_statement (c_parser *parser)
{
   // fprintf(stderr, "c_parser_seh_try_catch_statement()\n");
  
   location_t loc;
   tree stmt;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_SEH_TRY));
   c_parser_consume_token (parser);
   loc = c_parser_peek_token (parser)->location;
   ...
}
















 
< Précédent   Suivant >