Disassembling .Net Notes: Field Signatures Part 5

by Jason Haley 12. October 2008 17:06

Vectors and Arrays

In .Net there are two flavors of arrays: vectors (ELEMENT_TYPE_SZARRAY) and arrays (ELEMENT_TYPE_ARRAY).

Vectors: single-dimensional arrays with a zero lower bound.

Arrays (or MDArray): Multidimensional arrays (arrays that may have multiple dimensions or may have a non-zero lower bounds).

An interesting note on arrays (from page 149 of Serge Lidin's book):

Both array types are constructed types, so neither of them has an associated .NET Framework type.  All vectors and arrays are objects (class instances ) derived from the abstract class [mscorlib]System.Array.

CLR via C#, Chapter 13 is also a good reference to the details of Arrays.  According to Richter (page 297):

Vectors give the best performance because you can use specific IL instructions - such as newarr, ldelem, ldelema, ldlen, and stelem - to manipulate them. ... Zero-based, single-dimensional jagged arrays have the same performance as normal vectors.  However, accessing the elements of a jagged array means that two or more array accesses must occur.

Example of a single dimensional array (vector or szarray):

private string[] stringVector = new string[10];
 
Example of multi-dimensional array (mdarray):
private string[,] stringMDArray = new string[10,10];
 
Example of single-dimensional jagged array:
private string[][] stringJaggedArray = new string[10][];
 

Signatures

Vectors are encoded in the following format: ELEMENT_TYPE_SZARRAY
 
NOTE: The size is not part of the encoding (like you might expect it to be) - this is because when the newarr IL instruction creates the instance of the array the size is provided at that time.
 
[Multidimensional] Arrays are encoded in the following format (taken from Serge Lidin's book on page 149)
ELEMENT_TYPE_ARRAY......
 
where the following is true:
 
cannot be void
is the number of array dimensions (K>0)
is the number of specified sizes for dimensions (N <= K)
is an unsigned integer specifying the size (n = 1, ..., N)
is the number of specified lower bounds (M <= K)
is a signed integer specifying the lower bound (m = 1, ..., M)
 
The following diagram is taken from the Ecma 335 spec, Partition III, page 161:
 
image
A nice note under the ArrayShape in the spec is "Note: definitions can nest, since the Type can itself be an array"
 

Example 22: Decoding a field signature of a string array (vector)

C# Code:

private string[] szarray1;

Field Information from ILDasm:

image

0x06 = IMAGE_CEE_CS_CALLCONV_FIELD

0x1d = ELEMENT_TYPE_SZARRAY

0x0e = ELEMENT_TYPE_STRING

This tells us the field is an string single dimensional array.

 

Example 23: Decoding a field signature of an int array (vector)

C# Code:

private int[] szarray2;

Field Information from ILDasm:

image 

0x06 = IMAGE_CEE_CS_CALLCONV_FIELD

0x1d = ELEMENT_TYPE_SZARRAY

0x08 = ELEMENT_TYPE_I4

This tells us the field is an int single dimensional array.

 

Example 24: Decoding a field signature of an array of objects declared in current assembly (vector)

C# Code:

private TestClass[] szarray3;

Field Information from ILDasm:

image

0x06 = IMAGE_CEE_CS_CALLCONV_FIELD

0x1d = ELEMENT_TYPE_SZARRAY

0x12 = ELEMENT_TYPE_CLASS

0x08 TypeDefRefEncoded token

image

0x08 is also compressed, but is the same either compressed or not

image

Determine the table the type is in:

Neither of the last 2 bits or on (00 = TypeDef)

Get the index of the record:

Bit shift to the left by 2 and you get 2 (0x02) - which is the index in the TypeDef table for the SignatureUtility.TestClass record.

image

This tells us the field is a single dimensional array of type SignatureUtility.TestClass

 

Example 25:  Decoding  a field signature of an multi-dimensional array of strings

C# Code:

private string[,] etarray1;

Field Information from ILDasm:

image

0x06 = IMAGE_CEE_CS_CALLCONV_FIELD

0x14 = ELEMENT_TYPE_ARRAY

0x0e = ELEMENT_TYPE_STRING (type the array holds = System.String)

0x02 = Rank (compressed, but the same as it being uncompressed) or number of dimensions = 2

0x00 = Number of sizes (also compressed/uncompressed) - no sizes provided in declaration = 0

0x02 = Number of lower bounds (compressed integer) = 2

0x00 = First dimension's lower bound = 0

0x00 = Second dimension's lower bound = 0

This tells us the field is a multidimensional array of type string, that was declared with no sizes and has the lower bounds of 0 for the first dimension and 0 for the second dimension.  Which is what ILDasm shows for this field in its tree view:

image

 

Example 26:  Decoding  a field signature of an multi-dimensional array of integers

C# Code:

private int[,] etarray2;

Field Information from ILDasm:

 image

0x06 = IMAGE_CEE_CS_CALLCONV_FIELD

0x14 = ELEMENT_TYPE_ARRAY

0x08 = ELEMENT_TYPE_I4 (type the array holds = System.Int32)

0x02 = Rank (compressed, but the same as it being uncompressed) or number of dimensions = 2

0x00 = Number of sizes (also compressed/uncompressed) - no sizes provided in declaration = 0

0x02 = Number of lower bounds (compressed integer) = 2

0x00 = First dimension's lower bound = 0

0x00 = Second dimension's lower bound = 0

This tells us the field is a multidimensional array of type int, that was declared with no sizes and has the lower bounds of 0 for the first dimension and 0 for the second dimension.  Which is what ILDasm shows for this field in its tree view:

image

 

Example 27: Decoding  a field signature of an multi-dimensional array of an object declared in the same assembly

C# Code:

private TestClass[,] etarray3;

Field Information from ILDasm:

 image

0x06 = IMAGE_CEE_CS_CALLCONV_FIELD

0x14 = ELEMENT_TYPE_ARRAY

0x12 = ELEMENT_TYPE_CLASS

0x08 TypeDefRefEncoded token

image

0x08 is also compressed, but is the same either compressed or not

image

Determine the table the type is in:

Neither of the last 2 bits or on (00 = TypeDef)

Get the index of the record:

Bit shift to the left by 2 and you get 2 (0x02) - which is the index in the TypeDef table for the SignatureUtility.TestClass record.

image

0x02 = Rank (compressed, but the same as it being uncompressed) or number of dimensions = 2

0x00 = Number of sizes (also compressed/uncompressed) - no sizes provided in declaration = 0

0x02 = Number of lower bounds (compressed integer) = 2

0x00 = First dimension's lower bound = 0

0x00 = Second dimension's lower bound = 0

This tells us the field is a multidimensional array of type SignatureUtility.TestClass (declared in the same assembly), that was declared with no sizes and has the lower bounds of 0 for the first dimension and 0 for the second dimension.  Which is what ILDasm shows for this field in its tree view:

image

Next notes will provide:

  1. Overview of Method Signatures (MethodDefSig, MethodRefSig)
  2. Start out with some easy examples

Comments (0) | Post RSSRSS comment feed |

Categories:
Tags:

Comments are closed