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); } }
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); }
// 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); } }
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;