Программно разобрать CIL - PullRequest
       21

Программно разобрать CIL

11 голосов
/ 13 февраля 2012

Я могу скомпилировать инструкции для байт-кода и даже выполнить их легко, но единственная найденная мной функция для извлечения CIL - это GetILAsByteArray, и, как следует из названия, она просто возвращает байты, а не инструкции CIL.

Так как же программно разобрать CIL в .NET?

Обратите внимание, что мне не нужен результат в удобочитаемой форме. Я хочу написать метапрограммы для управления CIL, сгенерированным из других программ.

Ответы [ 4 ]

9 голосов
/ 13 февраля 2012

Библиотека Mono Cecil - http://www.mono -project.com / Cecil должна делать то, что вам нужно, я знаю, что она используется хотя бы в одном .Net profiler

8 голосов
/ 13 февраля 2012

Вы можете добиться значительных успехов, просто используя байтовый массив из метода GetILAsByteArray, но вам нужно будет самостоятельно выполнить разбор байтов (если вы не хотите полагаться на стороннюю библиотеку).

Структура массива такова, что существует один или два байта, идентифицирующие инструкцию, сопровождаемую операндами для инструкции (которая является либо ничем, некоторым 4-байтовым токеном или 8-байтовым числом).коды, вы можете посмотреть на OpCodes структуру ( MSDN ) из System.Reflection.Emit.Если вы перечислите все поля, вы можете легко построить таблицу поиска для чтения байтов:

// Iterate over all byte codes to build lookup table
for fld in typeof<OpCodes>.GetFields() do
  let code = fld.GetValue(null) :?> OpCode
  printfn "%A (%d + %A)" code.Name code.Size code.OperandType

Свойство code.Value дает вам значение кода byte или int16,Свойство code.Size указывает, является ли это 1 или 2-байтовым кодом, а свойство OperandType указывает, какие аргументы следуют за кодом (количество байтов и значение объяснено в MSDN ).Я не помню, как именно вам нужно обрабатывать такие вещи, как токены, которые относятся к MethodInfo, но я думаю, вы сможете это понять!

5 голосов
/ 13 февраля 2012

Одной из интересных альтернатив использованию Сесила было бы воскресение проекта AbsIL .Сесил хорошо написан и хорошо используется, но, вероятно, это не то, как вы подходите к проблеме, если бы писали ее на F #.AbsIL был проектом, запущенным в то же время, что и F #, чтобы позволить OCaml и F # читать и записывать IL, с тех пор он был перенят как проект F # и теперь является лишь бэкендом для компилятора F #.Однако код для чтения и записи IL все еще существует и теоретически может быть отделен от компилятора F # и превращен в удобную для использования библиотеку.Отделение кода AbsIL от остальной части компилятора F # не совсем тривиально, но должно быть возможно, если у вас есть немного свободного времени и определенная решимость.Если вы чувствуете себя действительно смелым, вы также можете посмотреть на кросс-компиляцию для OCaml.

2 голосов
/ 13 февраля 2012

Я сделал некоторые манипуляции с IL в проекте Mono Cecil . Это довольно простой API.

...