protected void ForEach(ILGenerator il, Action <ILBuffer> action)
        {
            IReadOnlyList <ILBuffer> buffers = m_buffers;

            for (int x = 0, max = buffers.Count - 1; x < max; x++)
            {
                ILBuffer buf = buffers[x];
                switch (buf.code.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    FindILBuffer(buffers, (int)buf.operand).label = new PublicLabel(il.DefineLabel());
                    break;

                case OperandType.InlineSwitch:
                    foreach (int i in (int[])buf.operand)
                    {
                        FindILBuffer(buffers, i).label = new PublicLabel(il.DefineLabel());
                    }
                    break;

                default:
                    break;
                }

                action.Invoke(buf);
            }
        }
        protected virtual void ModifyDefault(ILGenerator il, ILBuffer current, List <ILBuffer> final_code, ref Label retlabel, ref bool need_defineRetLabel, bool hasReturn, int argFixOffset)
        {
            // ret -> jump
            OpCode code = current.code;

            if (code == OpCodes.Ret)
            {
                if (hasReturn)
                {
                    current.code = OpCodes.Stloc_0;
                    final_code.Add(current);
                }

                // define label
                if (need_defineRetLabel)
                {
                    retlabel            = il.DefineLabel();
                    need_defineRetLabel = false;
                }

                // use label
                final_code.Add(new ILBuffer
                {
                    code    = OpCodes.Br,
                    operand = retlabel
                });
            }
            // add
            else
            {
                FixupILCode(current, code, argFixOffset, hasReturn);
                final_code.Add(current);
            }
        }
Example #3
0
        internal static ILBuffer FindILBuffer(IReadOnlyList <ILBuffer> buffers, int offset)
        {
            int lastIdx = buffers.Count - 1;

#if DEBUG
            if (offset < 0 || offset > buffers[lastIdx].offset)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
#endif
            int min = 0, max = lastIdx;
            while (min <= max)
            {
                int      mid     = min + (max - min) / 2;
                ILBuffer current = buffers[mid];

                if (current.offset == offset)
                {
                    return(current);
                }

                if (offset < current.offset)
                {
                    max = mid - 1;
                }
                else
                {
                    min = mid + 1;
                }
            }
#if DEBUG
            IEnumerator <ILBuffer> iter = buffers.GetEnumerator();
            while (iter.MoveNext())
            {
                ILBuffer buf = iter.Current;
                if (buf.offset == offset)
                {
                    Console.WriteLine("[WARN] 'm_buffers' is not sorted!");
                    System.Diagnostics.Debug.WriteLine("Not Sorted!!");

                    iter.Dispose();
                    return(buf);
                }
            }

            iter.Dispose();
            System.Diagnostics.Debug.Fail("Missing ILBuffer");
#endif
            return(null);
        }
Example #4
0
        // internal static Action ToDelegate(MethodInfo meth) => (Action)Delegate.CreateDelegate(typeof(Action), meth);

        internal static ILBuffer FindILBuffer(IReadOnlyList <ILBuffer> buffers, int offset)
        {
            int lastIdx = buffers.Count - 1;

#if DEBUG
            if (offset < 0 || offset > buffers[lastIdx].offset)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
#endif

            int min = 0, max = lastIdx;
            while (min <= max)
            {
                int      mid     = min + (max - min) / 2;
                ILBuffer current = buffers[mid];

                if (current.offset == offset)
                {
                    return(current);
                }

                if (offset < current.offset)
                {
                    max = mid - 1;
                }
                else
                {
                    min = mid + 1;
                }
            }
#if DEBUG
            foreach (ILBuffer buf in buffers)
            {
                if (buf.offset == offset)
                {
                    Console.WriteLine("[WARN] 'm_buffers' is not sorted!");
                    System.Diagnostics.Debug.WriteLine("Not Sorted!!");
                    return(buf);
                }
            }
            throw new Exception("Missing ILBuffer!");
#else
            return(null);
#endif
        }
        protected virtual void ParseIL()
        {
            Module mod = module ?? method.Module;

            byte[] il = method.GetMethodBody().GetILAsByteArray();
            fixed(byte *ptr = il)
            for (int pos = 0, max = il.Length; pos < max; )
            {
                ILBuffer buf = new ILBuffer
                {
                    offset = pos
                };

                OpCode code;
                byte   temp = Read <byte>(ptr, ref pos);

                if (temp == 0xFE)
                {
                    code = OpCodeConverter.GetCode_sz2(Read <byte>(ptr, ref pos));
                }
                else
                {
                    code = OpCodeConverter.GetCode_sz1(temp);
                }

                buf.code = code;

                switch (code.OperandType)
                {
                case OperandType.InlineBrTarget:
                    buf.operand = Read <int>(ptr, ref pos) + pos;
                    break;

                case OperandType.InlineField:
                    buf.operand = mod.ResolveField(Read <int>(ptr, ref pos));
                    break;

                case OperandType.InlineMethod:
                {
                    int token = Read <int>(ptr, ref pos);
                    try
                    {
                        buf.operand = mod.ResolveMethod(token);
                    }
#pragma warning disable CA1031 // Do not catch general exception types
                    catch
                    {
                        buf.operand = mod.ResolveMember(token);
                    }
#pragma warning restore CA1031
                }
                break;

                case OperandType.InlineSig:
                    // 사용하지 않음
                    // buf.operand = mod.ResolveSignature(Read<int>(ptr, ref pos));
                    buf.operand = Read <int>(ptr, ref pos);
                    break;

                case OperandType.InlineTok:
                {
                    int token = Read <int>(ptr, ref pos);
                    try
                    {
                        buf.operand = mod.ResolveType(token);
                    }
#pragma warning disable CA1031 // Do not catch general exception types
                    catch
                    {
                        buf.operand = token;
                    }
#pragma warning restore CA1031
                }
                break;

                case OperandType.InlineType:
                    buf.operand = mod.ResolveType(Read <int>(ptr, ref pos), method.DeclaringType?.GetGenericArguments(), method.GetGenericArguments());
                    break;

                case OperandType.InlineI:
                    buf.operand = Read <int>(ptr, ref pos);
                    break;

                case OperandType.InlineI8:
                    buf.operand = Read <long>(ptr, ref pos);
                    break;

                case OperandType.InlineR:
                    buf.operand = Read <double>(ptr, ref pos);
                    break;

                case OperandType.InlineString:
                    buf.operand = mod.ResolveString(Read <int>(ptr, ref pos));
                    break;

                case OperandType.InlineSwitch:
                {
                    int   count       = Read <int>(ptr, ref pos);
                    int   base_offset = pos + 4 * count;
                    int[] cases       = new int[count];
                    for (int x = 0; x < count; x++)
                    {
                        cases[x] = Read <int>(ptr, ref pos) + base_offset;
                    }
                    buf.operand = cases;
                }
                break;

                case OperandType.InlineVar:
                    buf.operand = Read <short>(ptr, ref pos);
                    break;

                case OperandType.ShortInlineBrTarget:
                    buf.operand = Read <byte>(ptr, ref pos) + pos;
                    break;

                case OperandType.ShortInlineI:
                    buf.operand = Read <byte>(ptr, ref pos);
                    break;

                case OperandType.ShortInlineR:
                    buf.operand = Read <float>(ptr, ref pos);
                    break;

                case OperandType.ShortInlineVar:
                    buf.operand = Read <byte>(ptr, ref pos);
                    break;

                case OperandType.InlineNone:
                    break;

                default:
#if DEBUG
                    System.Diagnostics.Debug.WriteLine("Unknown operand type: " + code.OperandType);
#endif
                    break;
                }

                m_buffers.Add(buf);
            }
        }
Example #6
0
        public static string IL2String(IReadOnlyList <ILBuffer> buffers)
        {
            StringBuilder strb = new StringBuilder(1024);

            IEnumerator <ILBuffer> iter = buffers.GetEnumerator();

            while (iter.MoveNext())
            {
                ILBuffer il = iter.Current;

                OpCode code = il.code;
                strb.Append($"IL_{il.offset:X4}: {code}");
                switch (code.OperandType)
                {
                case OperandType.InlineBrTarget:
                case OperandType.ShortInlineBrTarget:
                    strb.Append($" IL_{FindILBuffer(buffers, NativeClass.ReadMemoryValue_unsafe<int>(il.operand, 0)).offset:X4}");
                    break;

                case OperandType.InlineField:
                {
                    FieldInfo info = (FieldInfo)il.operand;
                    strb.Append($" {info.FieldType.Name.ToLower()} {info.DeclaringType.Name}::{info.Name}");
                }
                break;

                case OperandType.InlineMethod:
                {
                    if (il.operand is MethodInfo temp)
                    {
                        if (temp.IsStatic == false)
                        {
                            strb.Append($" instance");
                        }
                        strb.Append($" {temp.ReturnType.Name.ToLower()} {temp.DeclaringType.Name}::{temp.Name}()");
                    }
                    else
                    {
                        ConstructorInfo info = (ConstructorInfo)il.operand;
                        if (info.IsStatic == false)
                        {
                            strb.Append($" instance");
                        }
                        strb.Append($" void {info.DeclaringType.Name}::.ctor()");
                    }
                }
                break;

                case OperandType.InlineSig:
                {
                    if (il.operand is SignatureHelper temp)
                    {
                        strb.Append($" {temp}");
                    }
                    else
                    {
                        strb.Append($" meta_{(int)il.operand:X4}");
                    }
                }
                break;

                case OperandType.InlineString:
                    strb.Append($" \"{(string)il.operand}\"");
                    break;

                case OperandType.InlineSwitch:
                    strb.Append($" <inlineSwitch>");
                    break;

                case OperandType.InlineTok:
                {
                    if (il.operand is Type temp)
                    {
                        strb.Append($" {temp.FullName}");
                    }
                    else
                    {
                        strb.Append($" 0x{(int)il.operand:X4}");
                    }
                }
                break;

                case OperandType.InlineType:
                    strb.Append($" {((Type)il.operand).FullName}");
                    break;

                case OperandType.InlineI:
                case OperandType.InlineI8:
                case OperandType.InlineR:
                case OperandType.InlineVar:
                case OperandType.ShortInlineI:
                case OperandType.ShortInlineR:
                case OperandType.ShortInlineVar:
                    strb.Append($" {il.operand}");
                    break;

                default:
                    break;
                }
                strb.AppendLine();
            }
            iter.Dispose();

            return(strb.ToString());
        }
        protected virtual void FixupILCode(ILBuffer current, OpCode qcode, int argFixOffset, bool hasReturn)
        {
            // ldarg.s -> stloc.s
            // 0xE ~ 0x13
            // + FDFB = long version (remove 's')
            WORD v = qcode.Value;

            if (Range(v, 0xE, 0x13))
            {
                v += 0xFD_FB;
                // fix operand size
                current.operand = (short)(byte)current.operand;
            }

            // (only return buffer, instance)
            if (argFixOffset == 2)
            {
                // ldarg_3
                if (v == 5)
                {
                    v = 0xFE_09; // ldarg
                    current.operand = (short)4;
                }
                // ldarg_1 ldarg_2
                else if (v == 3 || v == 4)
                {
                    v++;
                }
                // ldarg ldarga starg
                else if (Range(v, 0xFE_09, 0xFE_0B))
                {
                    current.operand = (short)((short)current.operand + 1);
                }
            }
            if (hasReturn)
            {
                // ldloc_3
                if (v == 9)
                {
                    v = 0xFE_0C; // ldloc
                    current.operand = (short)4;
                }
                // stloc_3
                else if (v == 0xD)
                {
                    v = 0xFE_0E;
                    current.operand = (short)4;
                }
                // ldloc_0 ldloc_1 ldloc_2 stloc_0 stloc_1 stloc_2
                else if (Range(v, 6, 8) || Range(v, 0xA, 0xD))
                {
                    v++;
                }
                // ldloc ldloca stloc
                else if (Range(v, 0xFE_0C, 0xFE_0E))
                {
                    current.operand = (short)((short)current.operand + 1);
                }
            }

            // br.s -> blt.un.s
            if (Range(v, 0x2B, 0x37))
            {
                v += 0xD;
            }
            else if (v == 0xDE) // leave.s
            {
                v = 0xDD;
            }

            if (v != qcode.Value)
            {
                current.code = OpCodeConverter.GetCode(v.unsigned);
            }
        }
 protected virtual void ModifyDefault(ILGenerator il, ILBuffer current, List <ILBuffer> final_code, ref Label retlabel, ref bool need_defineRetLabel, bool hasReturn, int argFixOffset)
 {
     // ret -> jump
     ref OpCode code = ref current.opCode;