У меня есть MSIL в байтовом формате (результат GetMethodBody() от отражения, который я хотел бы немного проанализировать. Я хотел бы найти все классы, созданные с новым оператором в MSIL. Любые идеи о том, как это сделать программно?Проверка MSIL
ответ
В итоге я использовал анализатор MSIL здесь: http://blogs.msdn.com/zelmalki/archive/2008/12/11/msil-parser.aspx, причем источник слегка модифицирован для работы с ConstructorInfo, а также MethodInfo (результаты возвращаются из отражателя).
Он предоставит список операций с опкодом и параметрами. Код операции представляет собой перечисление, основанное на этом значении, параметры могут быть интерпретированы. Параметры находятся в двоичной форме, необходимо использовать MethodInfo.Module.Resolve *() для получения фактических значений параметров.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
namespace AspnetReflection
{
public class MsilReader
{
static readonly Dictionary<short, OpCode> _instructionLookup;
static readonly object _syncObject = new object();
readonly BinaryReader _methodReader;
MsilInstruction _current;
Module _module; // Need to resolve method, type tokens etc
static MsilReader()
{
if (_instructionLookup == null)
{
lock (_syncObject)
{
if (_instructionLookup == null)
{
_instructionLookup = GetLookupTable();
}
}
}
}
public MsilReader(MethodInfo method)
{
if (method == null)
{
throw new ArgumentException("method");
}
_module = method.Module;
_methodReader = new BinaryReader(new MemoryStream(method.GetMethodBody().GetILAsByteArray()));
}
public MsilReader(ConstructorInfo contructor)
{
if (contructor == null)
{
throw new ArgumentException("contructor");
}
_module = contructor.Module;
_methodReader = new BinaryReader(new MemoryStream(contructor.GetMethodBody().GetILAsByteArray()));
}
public MsilInstruction Current
{
get { return _current; }
}
public bool Read()
{
if (_methodReader.BaseStream.Length == _methodReader.BaseStream.Position)
{
return false;
}
int instructionValue;
if (_methodReader.BaseStream.Length - 1 == _methodReader.BaseStream.Position)
{
instructionValue = _methodReader.ReadByte();
}
else
{
instructionValue = _methodReader.ReadUInt16();
if ((instructionValue & OpCodes.Prefix1.Value) != OpCodes.Prefix1.Value)
{
instructionValue &= 0xff;
_methodReader.BaseStream.Position--;
}
else
{
instructionValue = ((0xFF00 & instructionValue) >> 8) |
((0xFF & instructionValue) << 8);
}
}
OpCode code;
if (!_instructionLookup.TryGetValue((short) instructionValue, out code))
{
throw new InvalidProgramException();
}
int dataSize = GetSize(code.OperandType);
var data = new byte[dataSize];
_methodReader.Read(data, 0, dataSize);
_current = new MsilInstruction(code, data);
return true;
}
static int GetSize(OperandType opType)
{
int size = 0;
switch (opType)
{
case OperandType.InlineNone:
return 0;
case OperandType.ShortInlineBrTarget:
case OperandType.ShortInlineI:
case OperandType.ShortInlineVar:
return 1;
case OperandType.InlineVar:
return 2;
case OperandType.InlineBrTarget:
case OperandType.InlineField:
case OperandType.InlineI:
case OperandType.InlineMethod:
case OperandType.InlineSig:
case OperandType.InlineString:
case OperandType.InlineSwitch:
case OperandType.InlineTok:
case OperandType.InlineType:
case OperandType.ShortInlineR:
return 4;
case OperandType.InlineI8:
case OperandType.InlineR:
return 8;
default:
return 0;
}
}
static Dictionary<short, OpCode> GetLookupTable()
{
var lookupTable = new Dictionary<short, OpCode>();
FieldInfo[] fields = typeof (OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public);
foreach (FieldInfo field in fields)
{
var code = (OpCode) field.GetValue(null);
lookupTable.Add(code.Value, code);
}
return lookupTable;
}
}
public struct MsilInstruction
{
public readonly byte[] Data;
public readonly OpCode Instruction;
public MsilInstruction(OpCode code, byte[] data)
{
Instruction = code;
Data = data;
}
public override string ToString()
{
var builder = new StringBuilder();
builder.Append(Instruction.Name + " ");
if (Data != null && Data.Length > 0)
{
builder.Append("0x");
foreach (byte b in Data)
{
builder.Append(b.ToString("x2"));
}
}
return builder.ToString();
}
}
}
Проверить эту статью на CodeProject http://www.codeproject.com/KB/cs/sdilreader.aspx
Используйте исходный код, который даст вам возможность взять байты IL [] в список инструкций. Если вы имеете дело с Generic, вы можете прокручивать сообщения и проверять сообщение, которое я помещал в эту статью (Bug Fix for Generic), в котором исправлены некоторые ошибки, связанные с использованием с Generic (только если вы хотите превратить IL в отображение текста).
После того, как у вас есть все инструкции IL, вам нужно только прокрутить их и увеличить счетчик, когда код операции инструкции (код команды) совпадает с OpCodes.Newobj или Newarr.
Если вы хотите получить больше понимания на внутренней стороне MSIL, я настоятельно рекомендую книгу «Компиляция для .NET CLR» Джона Гоу.
Возможно, это сработало бы так же, как и другой код, который я нашел, Благодарю. –
Я также обнаружил, что код Frank оказался очень полезным, но он имеет одну проблему, код операции переключения обрабатывается неправильно.
От MSDN, код операции сопровождается int32, содержащим количество элементов в таблице перехода, а затем позиции для перехода к. Таким образом, коммутатор с 3 элементами на самом деле имеет 16 байтов данных, а не 4.
Я использую код от от Ziad Elmalki по этому вопросу, который включает метод GetData для идентификации таких объектов, как цель вызова метода.
Я исправил обработку переключателя опкодами путем изменения их обработки в GetData, чтобы выглядеть следующим образом:
case OperandType.InlineSwitch:
{
int numberOfCases = BitConverter.ToInt32(rawData, 0);
int[] caseAddresses = new int[numberOfCases];
byte[] caseData = new byte[4];
for (int i = 0; i < numberOfCases; i++)
{
_methodReader.Read(caseData, 0, caseData.Length);
caseAddresses[i] = BitConverter.ToInt32(caseData, 0);
}
data = caseAddresses;
}
break;
- 1. MSIL ссылки
- 2. C# в сочетании с MSIL - JIT Пропустить Проверка
- 3. MSIL - как вы вызываете частный метод от MSIL?
- 4. Какой код MSIL? Является ли код, созданный ILDASM MSIL?
- 5. NullReferenceException против MSIL
- 6. Confused about MSIL
- 7. Являются ли MSIL атомарными?
- 8. IDE для MSIL
- 9. MSIL Вопрос (Basic)
- 10. Programmatic MSIL инъекции
- 11. MSIL: Избыточная филиал
- 12. Проблема с кодом MSIL
- 13. CIL/MSIL Бокс выпуск?
- 14. MSIL Memory Leaks
- 15. Как предотвратить инъекцию MSIL?
- 16. Как стать профессионалом MSIL?
- 17. Stringbuilder в CIL (MSIL)
- 18. Справочное руководство MSIL
- 19. .NET Отражатель MSIL
- 20. Самомодифицирующийся код C# (MSIL)?
- 21. Получите MSIL от сборки?
- 22. Запуск MSIL внутри Visual Studio
- 23. Отладчики MSIL - Mdbg, Dbgclr, Cordbg
- 24. MSIL Методы, не требующие ret
- 25. IS C++ преобразован в MSIL?
- 26. Какие языки компилировать КСС/MSIL
- 27. MSIL и дизассемблер для отладки
- 28. Каковы ресурсы для обучения MSIL?
- 29. MSIL вопрос о поле ссылки
- 30. C# компиляция в код MSIL
У вас есть доступ к сборке? Если вы это сделаете, вы можете использовать инструмент Reflector. –
Я хочу сделать это программно, так как у меня много кода для прохождения. –
В разделе «Примечания» указано, что вам нужно: http://msdn.microsoft.com/en-us/library/system.reflection.methodbody.getilasbytearray.aspx –