Search code examples
c++clrinternal

CLR have fat or small exception frame?


How detect IMAGE_COR_ILMETHOD_SECT_EH must use Small or Fat? Also me instrest other internal CLR structure/opcode details. Answer below answers this and many other questions.

/*RVA:0*/ typedef union IMAGE_COR_ILMETHOD{
IMAGE_COR_ILMETHOD_TINY       Tiny;
IMAGE_COR_ILMETHOD_FAT        Fat;} IMAGE_COR_ILMETHOD;
/*PC = RVA + sizeof( IMAGE_COR_ILMETHOD) = 12 or 4 byte*/ ... Code
/*EH = PC+CodeSize */typedef union IMAGE_COR_ILMETHOD_SECT_EH{
    IMAGE_COR_ILMETHOD_SECT_EH_SMALL Small;
    IMAGE_COR_ILMETHOD_SECT_EH_FAT Fat;
} IMAGE_COR_ILMETHOD_SECT_EH;

https://github.com/dotnet/coreclr/blob/master/src/inc/corhdr.h

for example

public static Main(string args[]){
   int i=0;
   try{
     Console.Write("OK");
   } catch(Exception){
   i++
   }
0000 4D 5A 90 00 MZ-header 
0250 2A 02 17 8C 06 00 00 01 51 2a 00 
RVA: 1B 30 02 00  // IMAGE_COR_ILMETHOD_FAT
     1D 00 00 00  CodeSize= 29 
     01 00 00 11  Locals  = 11000001
PC0: 00 16 0A              i=0 
PC3  00 72 01 00 00 70     try{
     28 04 00 00 0A     call Console.Write
     00 00 DE 09 
PC12:26 00 06 17 58 0A  00 DE 00 00 2A  (2A is ret command)     

     00 00 00 01 10 00   // IMAGE_COR_ILMETHOD_SECT_EH  ??? 1=count

     00 00        CorExceptionFlag Flags 
     03 00        TryOffset 
     0F           TryLength 
     12 00        HandlerOffset 
     09           HandlerLength 
     08 00 00 01  ClassToken

In this case we have small EH-frame. How detect we have small or fat frame?

   struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL{
       CorExceptionFlag    Flags         : 16;
       unsigned            TryOffset     : 16;
       unsigned            TryLength     : 8;  // relative to start of try block
       unsigned            HandlerOffset : 16;
       unsigned            HandlerLength : 8;  // relative to start of  handler
       union {
         DWORD       ClassToken;
         DWORD       FilterOffset;
       };
    } IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL;

typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT
{
  CorExceptionFlag    Flags;
  DWORD               TryOffset;
  DWORD               TryLength;      // relative to start of try block
  DWORD               HandlerOffset;
  DWORD               HandlerLength;  // relative to start of handler
  union {
    DWORD           ClassToken;     // use for type-based exception handlers
    DWORD           FilterOffset;   // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set)
};
} IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT;

Solution

  • This is covered in partition II section 25.4.5 of ECMA-335.

    If CorILMethod_Sect_FatFormat bit (0x40) is set in the Kind field (the first byte of the structure) then you should use fat, otherwise small. The Kind field can be accessed via Small.SectSmall.Kind or Fat.SectFat.Kind, either should work.