2

I am working on some code that parses IL byte arrays as returned by MethodBody.GetILAsByteArray.

Lets say I want to read a metadata token or a 32-bit integer constant from such an IL byte stream. At first I thought using BitConverter.ToInt32(byteArray, offset) would make this easy. However I'm now worried that this won't work on big-endian machines.

As far as I know, IL always uses little-endian encoding for multi-byte values:

"All argument numbers are encoded least-significant-byte-at-smallest-address (a pattern commonly termed 'little-endian')."The Common Language Infrastructure Annotated Standard, Partition III, ch. 1.2 (p. 482).

Since BitConverter's conversion methods honour the computer architecture's endianness (which can be discovered through BitConverter.IsLittleEndian), I conclude that BitConverter should not be used to extract multi-byte values from an IL byte stream, because this would give wrong results on big-endian machines.

Is this conclusion correct?

  • If yes: Is there any way to tell BitConverter which endianness to use for conversions, or is there any other class in the BCL that offers this functionality, or do I have to write my own conversion code?

  • If no: Where am I wrong? What is the proper way of extracting e.g. a Int32 operand value from an IL byte array?

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268

1 Answers1

1

You should always do this on a little endian array before passing it:

// Array is little. Are we on big?
if (!BitConverter.IsLittleEndian)
{
    // Then flip it
    Array.Reverse(array);
}
int val = BitConverter.ToInt32(...);

However as you mention an IL stream. The bytecode is this (AFAIK):

(OPCODE:(1|2):little) (VARIABLES:x:little)

So I would read a byte, check its opcode, then read the appropriate bytes and flip the array if necessary using the above code. Can I ask what you are doing?

Cole Tobin
  • 9,206
  • 15
  • 49
  • 74
  • So to extract an `Int32`, and if I don't want to modify the original IL array, I would possibly have to do this on a big-endian machine: `var fragment = new byte[4]; Array.Copy(il, offset, fragment, 0, length: 4); Array.Reverse(fragment); int value = BitConverter.ToInt32(fragment, 0);`. -- Is there any predefined class or method in the BCL that would do the same? – stakx - no longer contributing Aug 12 '12 at 11:42
  • 1
    Not that I know of. Getting this may help you a lot: http://www.ecma-international.org/publications/standards/Ecma-335.htm – Cole Tobin Aug 12 '12 at 11:42
  • Endianness comes into play even for the op-code if you want to compare it against [`OpCode.Value`](http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcode.value.aspx "MSDN reference page"), which is defined not as `byte[]` but as `short`. – stakx - no longer contributing Aug 12 '12 at 12:19
  • @stakx actually, they are one or two byte sequences, not a short – Cole Tobin Aug 22 '12 at 19:01