感谢大家光临我的博客!一起努力、共同进步 --cc--

cang2012

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

根据方法名获取方法Body Content

  利用 MethodBody类的GetILAsByteArray方法可以获取到返回字节数组的MSIL的body。然后再去解析此字节数组, 可以得到MSIL,然后你再去解析MSIL,你就可以得到你想到source code,这样就可以做小的反....,以下是代码的实现....

   

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

namespace Timwi.ILReaderExample
{
    public class ILReader
    {
        public class Instruction
        {
            public int StartOffset
            {
                get; private set;
            }
            public OpCode OpCode
            {
                get; private set;
            }
            public long? Argument
            {
                get; private set;
            }
            public Instruction(int startOffset, OpCode opCode, long? argument)
            {
                StartOffset = startOffset;
                OpCode = opCode;
                Argument = argument;
            }
            public override string ToString()
            {
                return OpCode.ToString() + (Argument == null ? string.Empty : " " + Argument.Value);
            }
        }

        private Dictionary<short, OpCode> _opCodeList;

        public ILReader()
        {
            _opCodeList = typeof(OpCodes).GetFields().Where(f => f.FieldType == typeof(OpCode)).Select(f => (OpCode)f.GetValue(null)).ToDictionary(o => o.Value);
        }

        public IEnumerable<Instruction> ReadIL(MethodBase method)
        {
            MethodBody body = method.GetMethodBody();
            if (body == null)
                yield break;

            int offset = 0;
            byte[] il = body.GetILAsByteArray();
            while (offset < il.Length)
            {
                int startOffset = offset;
                byte opCodeByte = il[offset];
                short opCodeValue = opCodeByte;
                offset++;

                // If it's an extended opcode then grab the second byte. The 0xFE prefix codes aren't marked as prefix operators though.
                if (opCodeValue == 0xFE || _opCodeList[opCodeValue].OpCodeType == OpCodeType.Prefix)
                {
                    opCodeValue = (short)((opCodeValue << 8) + il[offset]);
                    offset++;
                }

                OpCode code = _opCodeList[opCodeValue];

                Int64? argument = null;

                int argumentSize = 4;
                if (code.OperandType == OperandType.InlineNone)
                    argumentSize = 0;
                else if (code.OperandType == OperandType.ShortInlineBrTarget || code.OperandType == OperandType.ShortInlineI || code.OperandType == OperandType.ShortInlineVar)
                    argumentSize = 1;
                else if (code.OperandType == OperandType.InlineVar)
                    argumentSize = 2;
                else if (code.OperandType == OperandType.InlineI8 || code.OperandType == OperandType.InlineR)
                    argumentSize = 8;
                else if (code.OperandType == OperandType.InlineSwitch)
                {
                    long num = il[offset] + (il[offset + 1] << 8) + (il[offset + 2] << 16) + (il[offset + 3] << 24);
                    argumentSize = (int)(4 * num + 4);
                }

                // This does not currently handle the 'switch' instruction meaningfully.
                if (argumentSize > 0)
                {
                    Int64 arg = 0;
                    for (int i = 0; i < argumentSize; ++i)
                    {
                        Int64 v = il[offset + i];
                        arg += v << (i * 8);
                    }
                    argument = arg;
                    offset += argumentSize;
                }

                yield return new Instruction(startOffset, code, argument);
            }
        }
    }

    public static partial class Program
    {
        public static void Main(string[] args)
        {
            var reader = new ILReader();
            var module = typeof(Program).Module;
            foreach (var instruction in reader.ReadIL(typeof(Program).GetMethod("Main")))
            {
                string arg = instruction.Argument.ToString();
                if (instruction.OpCode == OpCodes.Ldfld || instruction.OpCode == OpCodes.Ldflda || instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldsflda || instruction.OpCode == OpCodes.Stfld)
                    arg = module.ResolveField((int)instruction.Argument).Name;
                else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli || instruction.OpCode == OpCodes.Callvirt)
                    arg = module.ResolveMethod((int)instruction.Argument).Name;
                else if (instruction.OpCode == OpCodes.Newobj)
                    // This displays the type whose constructor is being called, but you can also determine the specific constructor and find out about its parameter types
                    arg = module.ResolveMethod((int)instruction.Argument).DeclaringType.FullName;
                else if (instruction.OpCode == OpCodes.Ldtoken)
                    arg = module.ResolveMember((int)instruction.Argument).Name;
                else if (instruction.OpCode == OpCodes.Ldstr)
                    arg = module.ResolveString((int)instruction.Argument);
                else if (instruction.OpCode == OpCodes.Constrained || instruction.OpCode == OpCodes.Box)
                    arg = module.ResolveType((int)instruction.Argument).FullName;
                else if (instruction.OpCode == OpCodes.Switch)
                    // For the 'switch' instruction, the "instruction.Argument" is meaningless. You'll need extra code to handle this.
                    arg = "?";
                Console.WriteLine(instruction.OpCode + " " + arg);
            }
            Console.ReadLine();
        }
    }
}
复制代码

 

  

 

posted on   C-x-C  阅读(703)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示