Skip to content

Instantly share code, notes, and snippets.

@kazuk
Created August 4, 2012 03:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kazuk/3254129 to your computer and use it in GitHub Desktop.
Save kazuk/3254129 to your computer and use it in GitHub Desktop.
MSIL Scanner
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
namespace Oosaki.Msil
{
public partial class Dissassembler
{
public static Dictionary<short, OpCode> OpeCodes;
static Dissassembler()
{
OpeCodes = typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(field => field.FieldType == typeof(OpCode))
.Select(field => (OpCode)field.GetValue(null))
.ToDictionary(op => op.Value, op => op);
}
public IEnumerable<int> Scan(byte[] ilbytes)
{
ByteArrayStream stream = new ByteArrayStream(ilbytes);
return Scan( new BinaryReader(stream),ilbytes.Length );
}
/// <summary>
/// Scan IL from BinaryReader
/// </summary>
/// <param name="binaryReader"></param>
/// <param name="length"></param>
/// <returns>IL opecode offsets</returns>
public IEnumerable<int> Scan(BinaryReader binaryReader,int length)
{
int offset = 0;
Dictionary< OperandType, Action> operandTaker = new Dictionary<OperandType,Action>() {
{OperandType.InlineBrTarget, ()=> { binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineField, ()=> { binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineI, ()=> { binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineI8, () => { binaryReader.ReadInt64(); offset+=8; } },
{OperandType.InlineMethod, () => {binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineNone, () => {} },
{OperandType.InlinePhi, ()=> { throw new BadImageFormatException( "InlinePhi operand not supported" ); } },
{OperandType.InlineR, ()=> {binaryReader.ReadDouble(); offset+=8; } },
{OperandType.InlineSig, () => {binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineString, () => {binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineSwitch, () => { int cnt=binaryReader.ReadInt32(); offset+=4;
binaryReader.ReadBytes( cnt*4 ); offset+=cnt*4; } },
{OperandType.InlineTok, ()=> { binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineType, ()=> {binaryReader.ReadInt32(); offset+=4; } },
{OperandType.InlineVar, ()=> {binaryReader.ReadInt16(); offset+=2; } },
{OperandType.ShortInlineBrTarget, ()=> {binaryReader.ReadByte(); offset++; } },
{OperandType.ShortInlineI, ()=>{binaryReader.ReadByte(); offset++; } },
{OperandType.ShortInlineR, ()=>{binaryReader.ReadSingle(); offset++; } },
{OperandType.ShortInlineVar, ()=>{binaryReader.ReadByte(); offset++; } }
};
while (offset < length)
{
yield return offset;
byte op1 = binaryReader.ReadByte();
offset++;
OpCode opCode;
if (!OpeCodes.TryGetValue((short)op1, out opCode))
{
byte op2 = binaryReader.ReadByte();
offset++;
short op = (short)((((short)op1) << 8) | op2);
if (!OpeCodes.TryGetValue(op, out opCode))
{
throw new BadImageFormatException(string.Format("{0:x4} is invalid il opecode", op));
}
}
operandTaker[opCode.OperandType]();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment