我可以将指令编译成字节码,甚至可以轻松地执行它们,但我发现提取CIL的唯一函数是GetILAsByteArray
,顾名思义,它只返回字节而不是CIL指令。
那么如何以编程方式在.NET上反汇编CIL?
请注意,我不希望结果以人类可读的形式出现。我想编写元程序来操纵从其他程序生成的CIL。
答案 0 :(得分:9)
Mono Cecil库 - http://www.mono-project.com/Cecil应该做你需要的,我知道它至少用于一个.Net profiler
答案 1 :(得分:8)
你可以使用GetILAsByteArray
方法中的字节数组得到合理的结果,但是你需要自己编写字节的解析(如果你不想依赖第三方库)。
数组的结构是有一个或两个字节标识指令操作数后面的指令(无论是什么,4字节标记或8字节数)。
要获取代码,您可以查看OpCodes
中的System.Reflection.Emit
结构(MSDN)。如果枚举所有字段,则可以非常轻松地构建查找表以读取字节:
// 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
属性为您提供代码的{{1}}或byte
值。 int16
属性告诉您这是1字节还是2字节代码,code.Size
属性指定代码后面的参数(字节数和含义explained on MSDN)。我不记得你究竟需要处理像引用OperandType
的标记这样的东西,但我想你能够弄明白这一点!
答案 2 :(得分:5)
使用Cecil的一个有趣的替代方案是恢复AbsIL项目。塞西尔写得很好,使用得很好,但如果你用F#编写它,可能不是你如何解决问题。 Absil是一个与F#同时启动的项目,允许OCaml和F#读写IL,它自从被F#项目过后,现在只是F#编译器的后端。然而,读取和写入IL的代码仍然存在,并且理论上可以与F#编译器分离并且可以自己制作成可用的库。将Absil代码与F#编译器的其余部分分开并不是完全无足轻重的,但如果您有一些空闲时间和一定的决心,则应该可以实现。如果你真的很勇敢,你可能也想看看交叉编译到OCaml。
答案 3 :(得分:2)
我用Mono Cecil项目进行了一些IL操作。它非常简单。