static void RestoreConstrainedPrefix(MethodDef method) { if (method == null || method.Body == null) { return; } var instrs = method.Body.Instructions; for (int i = 0; i < instrs.Count; i++) { var instr = instrs[i]; if (instr.OpCode.Code != Code.Callvirt) { continue; } var calledMethod = instr.Operand as IMethod; if (calledMethod == null) { continue; } var sig = calledMethod.MethodSig; if (sig == null || !sig.HasThis) { continue; } var thisType = MethodStack.GetLoadedType(method, instrs, i, sig.Params.Count) as ByRefSig; if (thisType == null) { continue; } if (HasPrefix(instrs, i, Code.Constrained)) { continue; } instrs.Insert(i, OpCodes.Constrained.ToInstruction(thisType.Next.ToTypeDefOrRef())); i++; } }
public bool Restore(MethodDef method) { this.method = method; bool atLeastOneFailed = false; if (method == null || method.Body == null) { return(!atLeastOneFailed); } var instrs = method.Body.Instructions; for (int i = 0; i < instrs.Count; i++) { var instr = instrs[i]; if (instr.Operand != null) { continue; } TypeSig operandType = null, operandTypeTmp; OpCode newOpCode = null; SZArraySig arrayType; switch (instr.OpCode.Code) { case Code.Ldelem: arrayType = MethodStack.GetLoadedType(method, instrs, i, 1) as SZArraySig; if (arrayType == null) { break; } operandTypeTmp = arrayType.Next; if (operandTypeTmp == null) { newOpCode = OpCodes.Ldelem_Ref; } else { switch (operandTypeTmp.ElementType) { case ElementType.Boolean: newOpCode = OpCodes.Ldelem_I1; break; case ElementType.Char: newOpCode = OpCodes.Ldelem_U2; break; case ElementType.I: newOpCode = OpCodes.Ldelem_I; break; case ElementType.I1: newOpCode = OpCodes.Ldelem_I1; break; case ElementType.I2: newOpCode = OpCodes.Ldelem_I2; break; case ElementType.I4: newOpCode = OpCodes.Ldelem_I4; break; case ElementType.I8: newOpCode = OpCodes.Ldelem_I8; break; case ElementType.U: newOpCode = OpCodes.Ldelem_I; break; case ElementType.U1: newOpCode = OpCodes.Ldelem_U1; break; case ElementType.U2: newOpCode = OpCodes.Ldelem_U2; break; case ElementType.U4: newOpCode = OpCodes.Ldelem_U4; break; case ElementType.U8: newOpCode = OpCodes.Ldelem_I8; break; case ElementType.R4: newOpCode = OpCodes.Ldelem_R4; break; case ElementType.R8: newOpCode = OpCodes.Ldelem_R8; break; default: newOpCode = OpCodes.Ldelem_Ref; break; //TODO: Ldelem } } break; case Code.Stelem: arrayType = MethodStack.GetLoadedType(method, instrs, i, 2) as SZArraySig; if (arrayType == null) { break; } operandTypeTmp = arrayType.Next; if (operandTypeTmp == null) { newOpCode = OpCodes.Stelem_Ref; } else { switch (operandTypeTmp.ElementType) { case ElementType.U: case ElementType.I: newOpCode = OpCodes.Stelem_I; break; case ElementType.Boolean: case ElementType.U1: case ElementType.I1: newOpCode = OpCodes.Stelem_I1; break; case ElementType.Char: case ElementType.U2: case ElementType.I2: newOpCode = OpCodes.Stelem_I2; break; case ElementType.U4: case ElementType.I4: newOpCode = OpCodes.Stelem_I4; break; case ElementType.U8: case ElementType.I8: newOpCode = OpCodes.Stelem_I8; break; case ElementType.R4: newOpCode = OpCodes.Stelem_R4; break; case ElementType.R8: newOpCode = OpCodes.Stelem_R8; break; default: newOpCode = OpCodes.Stelem_Ref; break; //TODO: Stelem } } break; case Code.Ldelema: arrayType = MethodStack.GetLoadedType(method, instrs, i, 1) as SZArraySig; if (arrayType == null) { break; } operandType = arrayType.Next; break; case Code.Ldobj: operandType = GetPtrElementType(MethodStack.GetLoadedType(method, instrs, i, 0)); break; case Code.Stobj: operandType = MethodStack.GetLoadedType(method, instrs, i, 0); if (!IsValidType(operandType)) { operandType = GetPtrElementType(MethodStack.GetLoadedType(method, instrs, i, 1)); } break; default: continue; } if (newOpCode == null && !IsValidType(operandType)) { atLeastOneFailed = true; continue; } instr.Operand = operandType.ToTypeDefOrRef(); if (newOpCode != null) { instr.OpCode = newOpCode; } } return(!atLeastOneFailed); }