On Wed, 01 Apr 2009 11:22:22 -0700, Ian Lance Taylor <i...@google.com>
wrote:
> "Vincent R." <foru...@smartmobili.com> writes:
> 
>>> gcc will do the right thing if you put statements in an exception
>>> region.
>>
>> Hum how gcc can do that kind of things, is it some kind of voodoo ?
>> __except is not implemented yet and is more than a language construct
>> because it's an
>> OS thing. 
>> So maybe I need to say it once again, instructions inside __except needs
>> to
>> be 
>> put inside a function by the compiler .
> 
> Can you explain why that is?  I don't know how SEH works; how does the
> OS get involved?
> 
Yes I can but I will talk only about table-based SEH available on RISC(ARM,
SH, MIPS) and x64 architecture
Mechanism is different on x86.

Usually with C++ exceptions you cannot catch for instance NULL pointer
exception ie 
if you write something like that :

DWORD* ptr = NULL;
try
{
   *ptr = 0X42; // access violation
}
catch(...)
{

}

it will segfault.

With SEH you can catch that kind of errors and that's why it's so
interesting in embedded world
To be able to do it, it means OS is involved.
When OS is initialized it registers exception table and when an exception
is raised it will look
what is Program Counter of the current process.
Then he will look inside a specific PE section that list address and length
of each function
available in the binary and check if the function has SEH.
If it has SEH it will look inside another table that will tell him to jump
to the associated filter function. 

So when you declare this :

int _tmain(int argc, _TCHAR* argv[])
{
      DWORD* ptr = NULL;   // NULL pointer

      __try
      {
            puts("in try");
            *ptr = 0x4242;    // causes an access violation exception;
      }
      __except(puts("in filter"), EXCEPTION_EXECUTE_HANDLER){
            puts("in except");
      }
      puts("world");
      return 0;
}

you will get the generated code as if you had written like that

.text
------------------------------------------
int wmain(int argc, _TCHAR* argv[])
{
      DWORD* ptr = NULL;   // NULL pointer

BEGINTRY:   {

            puts("in try");
            *ptr = 0x4242;    // causes an access violation exception;
ENDTRY:     }
          goto AEB;
JMPTGT:   puts("in except");
AEB:  
      puts("world");
      return 0;
}
int filter_func(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
   puts("in filter_func");
   return EXCEPTION_EXECUTE_HANDLER;
}

.xdata (or .pdata on wince)
----------------------------------------
FuncStart  PrologLen FuncLen  ThirtyTwoBit  ExceptionFlag  Comment 
00011008      0x4       0x15        1             1         wmain
0001105c      0x1       0x9         1             0         


So from this table we know that wmain starts at address 00011008 and finish
at address 00011008 + 0x15 = 0001101D

So when access violation is raised OS kernel looks Program Counter, in the
above case
it happens at 0001102C and he knows that problem is in wmain and that this
function has an associated SEH.
Then kernel looks inside another table that will tell him to jump to
filter_func().
The filter_func return a value to indicate if it want to handle this
exception and if yes
it will jump to Jump target address (JMPTGT label).
So code inside __except braces will be executed.

Hope you understand better.



Reply via email to