Continuing with the decoding of method signatures, these notes cover non generic methods, generic methods and vararg methods.
Constraint Flags
(from CorGenericParamAttr, CorHdr.h lin 710)
| VarianceMask | 0x0003 |
| NonVaraint | 0x0000 |
| Covariant | 0x0001 |
| Contravariant | 0x0002 |
| SpecialConstraintMask | 0x001c |
| NoSpecialConstraint | 0x0000 |
| ReferenceTypeConstraint | 0x0004 |
| NotNullableValueTypeConstraint | 0x0008 |
| DefaultConstructorConstraint | 0x0010 |
Example 29: Decoding a method signature with 1 parameter with a return type of int
C# Code:
private int method1ParamIntRet(int number)
{
return number;
}
Method information from ILDasm:
0x20 = IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS (HasThis) and IMAGE_CEE_CS_CALLCONV_DEFAULT (Default)
0x01 = Parameter count of 1
0x08 = Return type = ELEMENT_TYPE_I4
0x08 = Parameter type = ELEMENT_TYPE_I4
This tells us the method is an instance method that takes 1 parameter of type int and returns an int.
NOTE: the return type comes after the parameter count (MethodDefSig)
Example 30: Decoding a method signature with 1 parameter with a return type of a class declared in current assembly
C# Code:
private TestClass method1ParamObjectRet(TestClass tc)
{
return tc;
}
Method information from ILDasm:
0x20 = IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS (HasThis) and IMAGE_CEE_CS_CALLCONV_DEFAULT (Default)
0x01 = parameter count = 1
0x12 = ELEMENT_TYPE_CLASS (return type)
0x08 = TypeDefOrRefEncoded Token
0x08 is a compressed integer of 8 - which is the same compressed or uncompressed
The TypeDefOrRefEncoded token is a TypeDef and a RID of 2, which is the record SignatureUtility.TestClass in the TypeDef table
0x12 = ELEMENT_TYPE_CLASS (parameter type)
0x08 = TypeDefOrRefEncoded Token - which is the same as above for the return type
This tells us it is an instance method that takes 1 parameter of type SignatureUtility.TestClass and has a return type of SignatureUtility.TestClass
Example 31: Decoding a method signature with 1 Generic Parameter and return type of void
C# Code:
private void methodGeneric0ParamVoidRet<T>()
{ }
Method information from ILDasm:
0x30 = IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS (HasThis) and IMAGE_CEE_CS_CALLCONV_GENERIC (Generic)
0x01 = GenParamCount = 1
0x00 = Parameter Count = 0
0x01 = ELEMENT_TYPE_VOID
If you look at the contents of the GenericParam table, you will see there is a record (RID=2) that has an Owner value of 06000004 which is the current method's token (table type=06 and RID of 000004).
This tells us the method is an instance method that takes 1 Generic Parameter, has no method parameters and returns void. By looking at the GenericParam table, we can see that the generic parameter's name is T (have to look in the string heap at index 0xc8 for the name 'T').
Example 32: Decoding a method signature with 1 Generic Parameter (with a constraint), 1 parameter and a return type of a type declared in the assembly
C# Code:
private TestClass methodGenericConstraint1ParamObjectRet<T>(int number)
where T : TestClass, new()
{
return new TestClass();
}
Method information from ILDasm:
0x30 = IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS (HasThis) and IMAGE_CEE_CS_CALLCONV_GENERIC (Generic)
0x01 = GenParamCount = 1
0x01 = Parameter Count = 1
0x12 = ELEMENT_TYPE_CLASS (return type)
0x08 = TypeDefOrRefEncoded Token
0x08 is a compressed integer of 8 - which is the same compressed or uncompressed
The TypeDefOrRefEncoded token is a TypeDef and a RID of 2, which is the record SignatureUtility.TestClass in the TypeDef table
0x08 = Parameter type = ELEMENT_TYPE_I4
If you look at the contents of the GenericParam table, you will see there is a record (RID=3) that has an Owner value of 06000005 which is the current method's token (table type=06 and RID of 000005). This generic parameter also has a constraint flags value of 0x0010 (DefaultConstructorConstraint).
If you look at the contents of the GenericParamConstraint table, you will see there is a record (RID=1) that has an Owner value of 2a000003 which is the constraint mentioned above and a Constraint TypeDefOrRef of 02 000002 (the TypeDef table entry for SignatureUtility.TestClass).
This tells us the method is an instance method that takes 1 Generic Parameter (with the name T), has 1 method parameter (of type int), has a return type of SignatureUtility.TestClass, with a Generic Constraint stating that T must be a SignatureUtility.TestClass type and must have a default constructor.
Example 33: Decoding a method signature with variable arguments and a void return type
I don't think I've ever used this but since it is possible to do, here it is ...
C# Code:
public void VariableArguments(__arglist)
{ }
Method information from ILDasm:
0x25 = IMAGE_CEE_CS_CALLCONV_HASTHIS (0x20) and IMAGE_CEE_CS_CALLCONV_VARARG (0x5)
0x00 = ParamCount
0x01 = ReturnType of 0x1 (ELEMENT_TYPE_VOID)
This tells us the method is an instance method that has varargs (variable arguments) method and has a return type of void.
Example 34: Decoding a method signature with a params string array parameter and a void return type
This is the recommended way to create a variable arguments method in .Net - notice how the 'params' keyword compiles to an attribute of type System.ParamArrayAttribute (which is actually attached to the parameter not the method).
C# Code:
public void VariableArguments(params string[] wordList)
{ }
Method information from ILDasm:
0x20 = IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS (HasThis) and IMAGE_CEE_CS_CALLCONV_DEFAULT (Default)
0x01 = ParamCount = 1
0x01 = ReturnType of 0x1 (ELEMENT_TYPE_VOID)
Parameter Type information:
0x1d = ELEMENT_TYPE_SZARRAY
0x0e = ELEMENT_TYPE_STRING
This tells us the method is an instance method with 1 parameter that is a string array and a return type of void.
Notes to be provided soon:
- Some examples of call site signatures (for MethodRefSig)
- PropertySig
- LocalVarSig
- More detail on the Param decoding
- More detail on the CustomMod decoding
- More detail on ReturnType decoding
- StandAloneMethodSig
Then I'll probably move on to decoding CustomAttributes