public IMethodReference FindMethod(uint metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { // Lookup the type in the cache List <GenericReference <IMethodReference> > genericMethodReferences; if (_genericTokenMethodMap.TryGetValue(metadataToken, out genericMethodReferences)) { foreach (GenericReference <IMethodReference> r in genericMethodReferences) { if (CompareArrays(r.GenericArgs, genericMethodArguments)) { return(r.Reference); } } } IList <ITypeReference> genericArguments = new List <ITypeReference>(); foreach (Type type in genericTypeArguments) { genericArguments.Add(AssemblyManager.FindType(type, type.GetGenericArguments())); } MethodBase methodBase = _netModule.ResolveMethod((int)metadataToken, genericTypeArguments, genericMethodArguments); IMethodDeclaration methodDeclaration; if (methodBase is ConstructorInfo) { methodDeclaration = new ConstructorDeclaration((ConstructorInfo)methodBase, this, AssemblyManager.FindType(methodBase.DeclaringType, methodBase.DeclaringType.GetGenericArguments())); } else { methodDeclaration = new MethodDeclaration((MethodInfo)methodBase, this, AssemblyManager.FindType(methodBase.DeclaringType, methodBase.DeclaringType.GetGenericArguments())); } if (genericMethodReferences == null) { genericMethodReferences = new List <GenericReference <IMethodReference> >(); _genericTokenMethodMap.Add(metadataToken, genericMethodReferences); } genericMethodReferences.Add(new GenericReference <IMethodReference>(methodDeclaration, genericTypeArguments)); return(methodDeclaration); }
/// <summary> /// Constructs the array of ILInstructions according to the IL byte code. /// </summary> /// <param name="module"></param> private void ConstructInstructions(Module module) { byte[] il = this.il; int position = 0; instructions = new List<ILInstruction>(); while (position < il.Length) { ILInstruction instruction = new ILInstruction(); // get the operation code of the current instruction OpCode code = OpCodes.Nop; ushort value = il[position++]; if (value != 0xfe) { code = Globals.singleByteOpCodes[(int)value]; } else { value = il[position++]; code = Globals.multiByteOpCodes[(int)value]; value = (ushort)(value | 0xfe00); } instruction.Code = code; instruction.Offset = position - 1; int metadataToken = 0; // get the operand of the current operation switch (code.OperandType) { case OperandType.InlineBrTarget: metadataToken = ReadInt32(il, ref position); metadataToken += position; instruction.Operand = metadataToken; break; // patched from comments on CP -hwd case OperandType.InlineField: metadataToken = ReadInt32(il, ref position); if (mi is ConstructorInfo) { instruction.Operand = module.ResolveField(metadataToken, mi.DeclaringType.GetGenericArguments(), null); } else { instruction.Operand = module.ResolveField(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); } break; // patched from comments on CP -hwd case OperandType.InlineMethod: metadataToken = ReadInt32(il, ref position); try { if (mi is ConstructorInfo) { instruction.Operand = module.ResolveMethod(metadataToken, mi.DeclaringType.GetGenericArguments(), null); } else { instruction.Operand = module.ResolveMethod(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); } } catch { if (mi is ConstructorInfo) { instruction.Operand = module.ResolveMember(metadataToken, mi.DeclaringType.GetGenericArguments(), null); } else { instruction.Operand = module.ResolveMember(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); } } break; case OperandType.InlineSig: metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveSignature(metadataToken); break; // patched from comments on CP -hwd case OperandType.InlineTok: metadataToken = ReadInt32(il, ref position); //try //{ if (mi is ConstructorInfo) { instruction.Operand = module.ResolveType(metadataToken, mi.DeclaringType.GetGenericArguments(), null); } else { instruction.Operand = module.ResolveType(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); } //} //catch //{ // int i = 1; //} break; // patched from comments on CP -hwd case OperandType.InlineType: metadataToken = ReadInt32(il, ref position); if (this.mi is MethodInfo) { instruction.Operand = module.ResolveType(metadataToken, this.mi.DeclaringType.GetGenericArguments(), this.mi.GetGenericArguments()); } else if (mi is ConstructorInfo) { instruction.Operand = module.ResolveType(metadataToken, this.mi.DeclaringType.GetGenericArguments(), null); } else { instruction.Operand = module.ResolveType(metadataToken); } break; case OperandType.InlineI: { instruction.Operand = ReadInt32(il, ref position); break; } case OperandType.InlineI8: { instruction.Operand = ReadInt64(il, ref position); break; } case OperandType.InlineNone: { instruction.Operand = null; break; } case OperandType.InlineR: { instruction.Operand = ReadDouble(il, ref position); break; } case OperandType.InlineString: { metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveString(metadataToken); break; } case OperandType.InlineSwitch: { int count = ReadInt32(il, ref position); int[] casesAddresses = new int[count]; for (int i = 0; i < count; i++) { casesAddresses[i] = ReadInt32(il, ref position); } int[] cases = new int[count]; for (int i = 0; i < count; i++) { cases[i] = position + casesAddresses[i]; } break; } case OperandType.InlineVar: { instruction.Operand = ReadUInt16(il, ref position); break; } case OperandType.ShortInlineBrTarget: { instruction.Operand = ReadSByte(il, ref position) + position; break; } case OperandType.ShortInlineI: { instruction.Operand = ReadSByte(il, ref position); break; } case OperandType.ShortInlineR: { instruction.Operand = ReadSingle(il, ref position); break; } case OperandType.ShortInlineVar: { instruction.Operand = ReadByte(il, ref position); break; } default: { throw new Exception("Unknown operand type."); } } instructions.Add(instruction); } }
/// <summary> /// Constructs the array of ILInstructions according to the IL byte code. /// </summary> /// <param name="module"></param> private void ConstructInstructions(Module module) { byte[] il = this.il; int position = 0; instructions = new List<ILInstruction>(); while (position < il.Length) { ILInstruction instruction = new ILInstruction(); // get the operation code of the current instruction OpCode code = OpCodes.Nop; ushort value = il[position++]; if (value != 0xfe) { code = Globals.singleByteOpCodes[(int)value]; } else { value = il[position++]; code = Globals.multiByteOpCodes[(int)value]; value = (ushort)(value | 0xfe00); } instruction.Code = code; instruction.Offset = position - 1; int metadataToken = 0; // get the operand of the current operation switch (code.OperandType) { case OperandType.InlineBrTarget: metadataToken = ReadInt32(il, ref position); metadataToken += position; instruction.Operand = metadataToken; break; case OperandType.InlineField: metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveField(metadataToken); break; case OperandType.InlineMethod: metadataToken = ReadInt32(il, ref position); try { instruction.Operand = module.ResolveMethod(metadataToken); } catch { try { instruction.Operand = module.ResolveMember(metadataToken); } catch (Exception) { //Try generic method try { instruction.Operand = module.ResolveMethod(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); } catch (Exception) { //Try generic member try { instruction.Operand = module.ResolveMember(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments()); } catch (Exception) { throw; } } } } break; case OperandType.InlineSig: metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveSignature(metadataToken); break; case OperandType.InlineTok: metadataToken = ReadInt32(il, ref position); try { instruction.Operand = module.ResolveType(metadataToken); } catch { } // SSS : see what to do here break; case OperandType.InlineType: metadataToken = ReadInt32(il, ref position); // now we call the ResolveType always using the generic attributes type in order // to support decompilation of generic methods and classes // thanks to the guys from code project who commented on this missing feature try { instruction.Operand = module.ResolveType(metadataToken); } catch (Exception) { instruction.Operand = module.ResolveType(metadataToken, this.mi.DeclaringType.GetGenericArguments(), this.mi.GetGenericArguments()); } break; case OperandType.InlineI: { instruction.Operand = ReadInt32(il, ref position); break; } case OperandType.InlineI8: { instruction.Operand = ReadInt64(il, ref position); break; } case OperandType.InlineNone: { instruction.Operand = null; break; } case OperandType.InlineR: { instruction.Operand = ReadDouble(il, ref position); break; } case OperandType.InlineString: { metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveString(metadataToken); break; } case OperandType.InlineSwitch: { int count = ReadInt32(il, ref position); int[] casesAddresses = new int[count]; for (int i = 0; i < count; i++) { casesAddresses[i] = ReadInt32(il, ref position); } int[] cases = new int[count]; for (int i = 0; i < count; i++) { cases[i] = position + casesAddresses[i]; } break; } case OperandType.InlineVar: { instruction.Operand = ReadUInt16(il, ref position); break; } case OperandType.ShortInlineBrTarget: { instruction.Operand = ReadSByte(il, ref position) + position; break; } case OperandType.ShortInlineI: { instruction.Operand = ReadSByte(il, ref position); break; } case OperandType.ShortInlineR: { instruction.Operand = ReadSingle(il, ref position); break; } case OperandType.ShortInlineVar: { instruction.Operand = ReadByte(il, ref position); break; } default: { throw new Exception("Unknown operand type."); } } instructions.Add(instruction); } }
void CopyOpcode(byte[] Bytes, ref int i, ILGenerator Gen, Module Origin, List<int> ExceptionTrinkets, Dictionary<int, Label[]> LabelOrigins) { OpCode Code = GetOpcode(Bytes, ref i); // These are emitted by exception handling copier if an exception // block is imminent. If not, copy them as usual. if(Code == OpCodes.Leave && ExceptionTrinkets.Contains(i + 5)) { i += 4; return; } else if(Code == OpCodes.Leave_S && ExceptionTrinkets.Contains(i + 2)) { // This is a rather tricky one. See the comment preceding the call to MineLabels above. i++; return; } else if(Code == OpCodes.Endfinally && ExceptionTrinkets.Contains(i+1)) return; switch(Code.OperandType) { // If no argument, then re-emit the opcode case OperandType.InlineNone: { Gen.Emit(Code); break; } // If argument is a method, re-emit the method reference case OperandType.InlineMethod: { int Token = BitHelper.ReadInteger(Bytes, ref i); MethodBase Base = Origin.ResolveMethod(Token); if(Base is MethodInfo) Gen.Emit(Code, GrabMethod(Base as MethodInfo)); else if(Base is ConstructorInfo) Gen.Emit(Code, GrabConstructor(Base as ConstructorInfo)); else throw new InvalidOperationException("Inline method is neither method nor constructor."); break; } // Argument is a field reference case OperandType.InlineField: { int Token = BitHelper.ReadInteger(Bytes, ref i); FieldInfo Field = Origin.ResolveField(Token); Gen.Emit(Code, GrabField(Field)); break; } // Argument is a type reference case OperandType.InlineType: { int Token = BitHelper.ReadInteger(Bytes, ref i); Type Ref = Origin.ResolveType(Token); Gen.Emit(Code, GrabType(Ref)); break; } // Argument is an inline string case OperandType.InlineString: { int Token = BitHelper.ReadInteger(Bytes, ref i); string Copy = Origin.ResolveString(Token); Gen.Emit(Code, Copy); break; } // Argument is a metadata token case OperandType.InlineTok: { int Token = BitHelper.ReadInteger(Bytes, ref i); MemberInfo Info = Origin.ResolveMember(Token); if(Info.MemberType == MemberTypes.Field) { if(Code != OpCodes.Ldtoken || !TryReplaceBackingField(Bytes, i, Gen, Origin)) Gen.Emit(Code, GrabField(Info as FieldInfo)); } else if(Info.MemberType == MemberTypes.Method) Gen.Emit(Code, GrabMethod(Info as MethodInfo)); else if(Info.MemberType == MemberTypes.TypeInfo || Info.MemberType == MemberTypes.NestedType) Gen.Emit(Code, GrabType(Info as Type)); else throw new InvalidOperationException("Inline token is neither field, nor method, nor type"); break; } // Argument is a switch map case OperandType.InlineSwitch: { if(!LabelOrigins.ContainsKey(i)) throw new Exception("No switchmap found for RVA "+i.ToString("X")); Label[] Labels = LabelOrigins[i]; i += 4 + Labels.Length*4; Gen.Emit(Code, Labels); break; } // Argument is a single-byte branch target case OperandType.ShortInlineBrTarget: { if(!LabelOrigins.ContainsKey(i)) throw new Exception("No label origin found for RVA "+i.ToString("X")); Gen.Emit(Code, LabelOrigins[i][0]); i++; break; } // Argument is a byte case OperandType.ShortInlineI: case OperandType.ShortInlineVar: { Gen.Emit(Code, Bytes[++i]); break; } // Argument is a short case OperandType.InlineVar: { Gen.Emit(Code, BitHelper.ReadShort(Bytes, ref i)); break; } case OperandType.InlineBrTarget: { if(!LabelOrigins.ContainsKey(i)) throw new Exception("No label origin found for RVA "+i.ToString("X")); Gen.Emit(Code, LabelOrigins[i][0]); i += 4; break; } // Argument is a 32-bit integer case OperandType.InlineI: case OperandType.ShortInlineR: // This is actually a 32-bit float, but we don't care { Gen.Emit(Code, BitHelper.ReadInteger(Bytes, ref i)); break; } // Argument is a 64-bit integer case OperandType.InlineI8: { Gen.Emit(Code, BitHelper.ReadLong(Bytes, ref i)); break; } // Argument is a 64-bit float case OperandType.InlineR: { Gen.Emit(Code, BitHelper.ReadDouble(Bytes, ref i)); break; } // If ever we run across OpCodes.Calli this'll probably happen default: throw new InvalidOperationException("The method copier ran across an unknown opcode."); } }
public static IntPtr ResolveToken(int token) { System.Reflection.Module module = typeof(CalliInj).Module; return(module.ResolveMethod(token).MethodHandle.GetFunctionPointer()); }
private void Write(BinaryWriter bw, Module module, MethodBody mb) { var locals = mb.LocalVariables; bw.Write(locals.Count); for (int i=0;i< locals.Count;i++) { bw.Write(locals[i].LocalType.FullName); bw.Write(locals[i].IsPinned); } var il = mb.GetILAsByteArray(); for(int i = 0; i < il.Length;) { EArgumentType argType = EArgumentType.None; var opcode = (EOpCode)il[i]; bw.Write(il[i]); i++; if(opcode == EOpCode.Extended) { bw.Write(il[i]); argType = ((EExtendedOpCode)il[i]).ArgFor(); i++; } else argType = opcode.ArgFor(); switch (argType) { case EArgumentType.Field: var fi = module.ResolveField(BitConverter.ToInt32(il, i)); i += 4; bw.Write(Names.Field(fi)); break; case EArgumentType.Float32: bw.Write(BitConverter.ToSingle(il, i)); i += 4; break; case EArgumentType.Float64: bw.Write(BitConverter.ToDouble(il, i)); i += 8; break; case EArgumentType.Token: case EArgumentType.Int32: bw.Write(BitConverter.ToInt32(il, i)); i += 4; break; case EArgumentType.Int64: bw.Write(BitConverter.ToInt64(il, i)); i += 8; break; case EArgumentType.Int8: bw.Write((sbyte)il[i]); i++; break; case EArgumentType.ListOfInt: uint count = BitConverter.ToUInt32(il, i); bw.Write(count); i += 4; while(count > 0) { bw.Write(BitConverter.ToInt32(il, i)); i += 4; } break; case EArgumentType.Method: var mi = module.ResolveMethod(BitConverter.ToInt32(il, i)); i += 4; bw.Write(Names.Method(mi)); break; case EArgumentType.String: var str = module.ResolveString(BitConverter.ToInt32(il, i)); i += 4; bw.Write(str); break; case EArgumentType.Type: var t = module.ResolveType(BitConverter.ToInt32(il, i)); i += 4; bw.Write(t.FullName); break; case EArgumentType.Uint16: bw.Write(BitConverter.ToUInt16(il, i)); i += 2; break; case EArgumentType.Uint32: bw.Write(BitConverter.ToUInt32(il, i)); i += 4; break; case EArgumentType.Uint8: bw.Write(il[i]); i++; break; } } bw.Write((byte)EOpCode.Terminator); /* var handlers = mb.ExceptionHandlingClauses; m_bw.Write(handlers.Count); foreach(var h in handlers) { m_bw.Write(h.TryOffset); m_bw.Write(h.TryLength); m_bw.Write(h.FilterOffset); m_bw.Write(h.HandlerOffset); m_bw.Write(h.HandlerLength); m_bw.Write((uint)h.Flags); //m_bw.Write(h.) }*/ }
private static int _ReadOperand(MethodBase This, OpCode code, int position, byte[] il, Module module, ILInstruction instruction) { int metadataToken; switch (code.OperandType) { case OperandType.InlineBrTarget: { metadataToken = ReadInt32(il, ref position); metadataToken += position; instruction.Operand = metadataToken; break; } case OperandType.InlineField: { metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveField(metadataToken); break; } case OperandType.InlineMethod: { metadataToken = ReadInt32(il, ref position); try { instruction.Operand = module.ResolveMethod(metadataToken); } catch { instruction.Operand = module.ResolveMember(metadataToken); } break; } case OperandType.InlineSig: { metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveSignature(metadataToken); break; } case OperandType.InlineTok: { metadataToken = ReadInt32(il, ref position); try { instruction.Operand = module.ResolveType(metadataToken); } catch { } // SSS : see what to do here break; } case OperandType.InlineType: { metadataToken = ReadInt32(il, ref position); // now we call the ResolveType always using the generic attributes type in order // to support decompilation of generic methods and classes // thanks to the guys from code project who commented on this missing feature instruction.Operand = module.ResolveType(metadataToken, This.DeclaringType.GetGenericArguments(), This.GetGenericArguments()); break; } case OperandType.InlineI: { instruction.Operand = ReadInt32(il, ref position); break; } case OperandType.InlineI8: { instruction.Operand = ReadInt64(il, ref position); break; } case OperandType.InlineNone: { instruction.Operand = null; break; } case OperandType.InlineR: { instruction.Operand = ReadDouble(il, ref position); break; } case OperandType.InlineString: { metadataToken = ReadInt32(il, ref position); instruction.Operand = module.ResolveString(metadataToken); break; } case OperandType.InlineSwitch: { var count = ReadInt32(il, ref position); var casesAddresses = new int[count]; for (var i = 0; i < count; i++) { casesAddresses[i] = ReadInt32(il, ref position); } var cases = new int[count]; for (var i = 0; i < count; i++) { cases[i] = position + casesAddresses[i]; } break; } case OperandType.InlineVar: { instruction.Operand = ReadUInt16(il, ref position); break; } case OperandType.ShortInlineBrTarget: { instruction.Operand = ReadSByte(il, ref position) + position; break; } case OperandType.ShortInlineI: { if (instruction.Code == OpCodes.Ldc_I4_S) { instruction.Operand = ReadSByte(il, ref position); } else { instruction.Operand = ReadByte(il, ref position); } break; } case OperandType.ShortInlineR: { instruction.Operand = ReadSingle(il, ref position); break; } case OperandType.ShortInlineVar: { instruction.Operand = ReadByte(il, ref position); break; } default: { throw new Exception("Unknown operand type."); } } return(position); }
private static string PrintInlineMethod(MSILInstruction instruction, Module module) { var methodBase = module.ResolveMethod((int)instruction.MetadataToken); return instruction.OpCode.Name + " " + methodBase.ReflectedType + "::" + methodBase.Name; }
private void ConstructInstructions(Module module) { byte[] localIlbytes = this.il; int position = 0; while (position < localIlbytes.Length) { var instruction = new ILInstruction(); // get the operation code of the current instruction OpCode code; ushort value = localIlbytes[position++]; if (GlobalIntermediateLanguageConstants.SingleByteOpCodes.Count == 0) { throw new InvalidOperationException( "Attempt to use Method Body Reader before Global Intermediate Language Constants has been initialised. Global Intermediate Language Constants. Load Op Codes must be called once."); } if (value != 0xfe) { code = GlobalIntermediateLanguageConstants.SingleByteOpCodes[value]; } else { value = localIlbytes[position++]; code = GlobalIntermediateLanguageConstants.MultiByteOpCodes[value]; } instruction.Code = code; instruction.Offset = position - 1; int metadataToken; // get the operand of the current operation switch (code.OperandType) { case OperandType.InlineBrTarget: metadataToken = ReadInt32(ref position); metadataToken += position; instruction.Operand = metadataToken; break; case OperandType.InlineField: // TODO All these try catch blocks need to go try { metadataToken = ReadInt32(ref position); instruction.Operand = module.ResolveField(metadataToken); } catch { instruction.Operand = new object(); } break; case OperandType.InlineMethod: metadataToken = ReadInt32(ref position); try { instruction.Operand = module.ResolveMethod(metadataToken); } catch { instruction.Operand = new object(); } break; case OperandType.InlineSig: metadataToken = ReadInt32(ref position); instruction.Operand = module.ResolveSignature(metadataToken); break; case OperandType.InlineTok: metadataToken = ReadInt32(ref position); try { instruction.Operand = module.ResolveType(metadataToken); } catch { } // TODO : see what to do here break; case OperandType.InlineType: metadataToken = ReadInt32(ref position); // now we call the ResolveType always using the generic attributes type in order // to support decompilation of generic methods and classes // thanks to the guys from code project who commented on this missing feature Type[] declaringTypeGenericArgs = this.mi.DeclaringType.GetGenericArguments(); Type[] genericArgs = null; if (this.mi.IsGenericMethod) { genericArgs = this.mi.GetGenericArguments(); } instruction.Operand = module.ResolveType(metadataToken, declaringTypeGenericArgs, genericArgs); break; case OperandType.InlineI: { instruction.Operand = ReadInt32(ref position); break; } case OperandType.InlineI8: { instruction.Operand = ReadInt64(ref position); break; } case OperandType.InlineNone: { instruction.Operand = null; break; } case OperandType.InlineR: { instruction.Operand = ReadDouble(ref position); break; } case OperandType.InlineString: { metadataToken = ReadInt32(ref position); instruction.Operand = module.ResolveString(metadataToken); break; } case OperandType.InlineSwitch: { int count = ReadInt32(ref position); var casesAddresses = new int[count]; for (int i = 0; i < count; i++) { casesAddresses[i] = ReadInt32(ref position); } var cases = new int[count]; for (int i = 0; i < count; i++) { cases[i] = position + casesAddresses[i]; } break; } case OperandType.InlineVar: { instruction.Operand = ReadUInt16(ref position); break; } case OperandType.ShortInlineBrTarget: { instruction.Operand = ReadSByte(ref position) + position; break; } case OperandType.ShortInlineI: { instruction.Operand = ReadSByte(ref position); break; } case OperandType.ShortInlineR: { instruction.Operand = ReadSingle(ref position); break; } case OperandType.ShortInlineVar: { instruction.Operand = ReadByte(ref position); break; } default: { throw new NotSupportedException("Unknown operand type."); } } this.instructions.Add(instruction); } }
public string ToString( Module module ) { OpCode opCode = OpCode; string operandStr = ""; int operandStart = _startIndex + opCode.Size; switch (opCode.OperandType) { case OperandType.InlineBrTarget: break; case OperandType.InlineField: operandStr = module.ResolveField(_il.GetInt32(operandStart)).Name; break; case OperandType.InlineI: operandStr = _il.GetInt32(operandStart).ToString(); break; case OperandType.InlineI8: operandStr = _il.GetInt64(operandStart).ToString(); break; case OperandType.InlineMethod: operandStr = module.ResolveMethod(_il.GetInt32(operandStart)).Name; break; case OperandType.InlineNone: break; case OperandType.InlineR: operandStr = _il.GetDouble(operandStart).ToString(); break; case OperandType.InlineSig: operandStr = string.Join("", module.ResolveSignature(_il.GetInt32(operandStart)) .Select(b => b.ToString("X2"))); break; case OperandType.InlineString: operandStr = "\"" + module.ResolveString(_il.GetInt32(operandStart)) + "\""; break; case OperandType.InlineSwitch: break; case OperandType.InlineTok: operandStr = module.ResolveType(_il.GetInt32(operandStart)).Name; break; case OperandType.InlineType: operandStr = module.ResolveType(_il.GetInt32(operandStart)).Name; break; case OperandType.InlineVar: operandStr = _il.GetInt16(operandStart).ToString(); break; case OperandType.ShortInlineBrTarget: break; case OperandType.ShortInlineI: operandStr = ((int) _il[operandStart]).ToString(); break; case OperandType.ShortInlineR: operandStr = _il.GetSingle(operandStart).ToString(); break; case OperandType.ShortInlineVar: operandStr = ((int) _il[operandStart]).ToString(); break; } return opCode.Name + " " + operandStr; }
public override System.Reflection.MethodBase ResolveMethod(int Metadatatoken) { return(_Module.ResolveMethod(Metadatatoken)); }
public static void SimulateEvalStack(IEnumerable<ILInstructionRun> runs, IEnumerable<int> controlFlow, Dictionary<int, List<Tuple<int, int>>> dataFlowSource, Module module) { var runArray = runs as ILInstructionRun[] ?? runs.ToArray(); Action<int, int, int> appendSource = (target, popIndex, source) => { List<Tuple<int, int>> sources; if (dataFlowSource.TryGetValue(target, out sources)) { sources.Add(Tuple.Create(popIndex, source)); } else { dataFlowSource.Add(target, new List<Tuple<int, int>> { Tuple.Create(popIndex, source) }); } }; var stack = new Stack<int>(); foreach (var flow in controlFlow) { var run = runArray.Single(r => r.StartIndex == flow); foreach (var inst in run.Instructions) { OpCode opCode = inst.OpCode; int popCount = 0; int pushCount = 0; if (opCode.StackBehaviourPop == StackBehaviour.Varpop || opCode.StackBehaviourPush == StackBehaviour.Varpush) { switch (opCode.OperandType) { case OperandType.InlineMethod: var token = inst.GetOperandToken(); var method = module.ResolveMethod(token); var para = method.GetParameters(); popCount = para.Length; if (!method.IsConstructor && !method.IsStatic) { popCount++; } if (!method.IsConstructor) { var mi = (MethodInfo) method; pushCount = mi.ReturnType == typeof (void) ? 0 : 1; } break; case OperandType.InlineNone: break; default: throw new NotImplementedException(); } } switch (opCode.StackBehaviourPop) { default: throw new NotSupportedException("んなもんしらねーよ"); case StackBehaviour.Pop0: break; case StackBehaviour.Pop1: case StackBehaviour.Popi: case StackBehaviour.Popref: appendSource(inst.StartIndex,0, stack.Pop()); break; case StackBehaviour.Pop1_pop1: case StackBehaviour.Popi_pop1: case StackBehaviour.Popi_popi: case StackBehaviour.Popi_popi8: case StackBehaviour.Popi_popr4: case StackBehaviour.Popi_popr8: case StackBehaviour.Popref_pop1: case StackBehaviour.Popref_popi: appendSource(inst.StartIndex,0, stack.Pop()); appendSource(inst.StartIndex,1, stack.Pop()); break; case StackBehaviour.Popi_popi_popi: case StackBehaviour.Popref_popi_pop1: case StackBehaviour.Popref_popi_popi8: case StackBehaviour.Popref_popi_popr4: case StackBehaviour.Popref_popi_popr8: case StackBehaviour.Popref_popi_popref: appendSource(inst.StartIndex,0, stack.Pop()); appendSource(inst.StartIndex,1, stack.Pop()); appendSource(inst.StartIndex,2, stack.Pop()); break; case StackBehaviour.Varpop: for (int i = 0; i < popCount; i++) { appendSource(inst.StartIndex,i, stack.Pop()); } break; } switch (opCode.StackBehaviourPush) { default: throw new NotSupportedException("それも知らんて"); case StackBehaviour.Push0: break; case StackBehaviour.Push1: case StackBehaviour.Pushi: case StackBehaviour.Pushi8: case StackBehaviour.Pushr4: case StackBehaviour.Pushr8: case StackBehaviour.Pushref: stack.Push(inst.StartIndex); break; case StackBehaviour.Push1_push1: stack.Push(inst.StartIndex); stack.Push(inst.StartIndex); break; case StackBehaviour.Varpush: for (int i = 0; i < pushCount; i++) { stack.Push(inst.StartIndex); } break; } } } }