Instruction ReplaceInstruction(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod) { var nextInstruction = instruction.Next; var opcodeField = OpcodesFields.FirstOrDefault(info => info.Name == calledMethod.Name); OpCode opcode; if (opcodeField == null) { // Special case stelem because we don't want to call it Stelem_Any if (calledMethod.Name == "Stelem") { opcode = OpCodes.Stelem_Any; } // Special case ldelem because we don't want to call it Ldelem_Any else if (calledMethod.Name == "Ldelem") { opcode = OpCodes.Ldelem_Any; } else { throw new Exception(string.Format("Unknown opcode {0}, ignoring", calledMethod.Name)); } } else { opcode = (OpCode)opcodeField.GetValue(null); } if (calledMethod is GenericInstanceMethod) { var generic_method = calledMethod as GenericInstanceMethod; var typetok = generic_method.GenericArguments[0]; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, typetok)); } else { if (calledMethod.Parameters.Count == 0) { StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode)); } if (calledMethod.Parameters.Count == 1) { var stack = Analysis[instruction.Previous]; var operandEntry = stack.Head; StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, operandEntry.Item1, Analysis); if (!operandEntry.Item2.IsConstant) { Console.WriteLine("Inline ({0}) without constant argument, ignoring.", opcode); StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis); return(nextInstruction); } var operand = operandEntry.Item2.Value; if (opcode.OperandType == OperandType.InlineVar) { var variable = ilProcessor.Body.Variables[(int)operand]; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, variable)); } else if (opcode.OperandType == OperandType.InlineArg) { var variable = ilProcessor.Body.Method.Parameters[(int)operand]; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, variable)); } else if (opcode.OperandType == OperandType.InlineBrTarget) { var jump = Labels.GetJumpLocation(ilProcessor.Body, (string)operand); StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, jump)); } else if (opcode.OperandType == OperandType.ShortInlineI) { var integer = (byte)operand; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, integer)); } else if (opcode.OperandType == OperandType.InlineI) { var integer = (int)operand; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, integer)); } else if (opcode.OperandType == OperandType.InlineI8) { var integer = (long)operand; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, integer)); } else if (opcode.OperandType == OperandType.ShortInlineR) { var real = (float)operand; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, real)); } else if (opcode.OperandType == OperandType.InlineR) { var real = (double)operand; StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, real)); } else if (opcode.OperandType == OperandType.InlineSwitch) { var target_string = (string)operand; var targets = target_string.Split(';').Select(label => Labels.GetJumpLocation(ilProcessor.Body, label)).ToArray(); StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, targets)); } else if (opcode.OperandType == OperandType.InlineField) { var module = ilProcessor.Body.Method.Module; var field = (string)operand; var fieldref = Reference.ParseFieldReference( Reference.Scope.NewMethodScope(ilProcessor.Body.Method), field); StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, fieldref)); } else if (opcode.OperandType == OperandType.InlineMethod) { var module = ilProcessor.Body.Method.Module; var method = (string)operand; var methodref = Reference.ParseMethodReference( Reference.Scope.NewMethodScope(ilProcessor.Body.Method), method); StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, methodref)); } else if (opcode.OperandType == OperandType.InlineType) { var module = ilProcessor.Body.Method.Module; var type = (string)operand; var typeref = Reference.ParseTypeReference( Reference.Scope.NewMethodScope(ilProcessor.Body.Method), type); StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, typeref)); } else { throw new ArgumentException(string.Format("Inline opcode ({0}) without argument, ignoring.", opcode)); } } else { if (opcode.OperandType == OperandType.InlineSig) { return(ReplaceCalli(ilProcessor, instruction, calledMethod)); } } } return(nextInstruction); }
private Instruction ReplaceLoadAddress(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod) { var generic_method = calledMethod as GenericInstanceMethod; var typetok = generic_method.GenericArguments[0]; var stack = Analysis[instruction.Previous]; var operandEntry = stack.Head; var addr_instruction = operandEntry.Item1; var next = instruction.Next; if (addr_instruction.OpCode == OpCodes.Ldloc) { var local = (VariableDefinition)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldloca, local)); } else if (addr_instruction.OpCode == OpCodes.Ldarg) { var argument = (ParameterDefinition)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldarga, argument)); } else if (addr_instruction.OpCode == OpCodes.Ldsfld) { var field = (FieldReference)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldsflda, field)); } else if (addr_instruction.OpCode == OpCodes.Ldfld) { var field = (FieldReference)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldflda, field)); } else if ( addr_instruction.OpCode == OpCodes.Ldelem_Any) { var type = (TypeReference)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldelema, type)); } else if ( addr_instruction.OpCode == OpCodes.Ldelem_I || addr_instruction.OpCode == OpCodes.Ldelem_I1 || addr_instruction.OpCode == OpCodes.Ldelem_I2 || addr_instruction.OpCode == OpCodes.Ldelem_I4 || addr_instruction.OpCode == OpCodes.Ldelem_I8 || addr_instruction.OpCode == OpCodes.Ldelem_U1 || addr_instruction.OpCode == OpCodes.Ldelem_U2 || addr_instruction.OpCode == OpCodes.Ldelem_U4 || addr_instruction.OpCode == OpCodes.Ldelem_R4 || addr_instruction.OpCode == OpCodes.Ldelem_R8 || addr_instruction.OpCode == OpCodes.Ldelem_Ref) { var module = ilProcessor.Body.Method.Module; TypeReference type; switch (addr_instruction.OpCode.Code) { case Code.Ldelem_I: type = new TypeReference("System", "IntPtr", module, module); break; case Code.Ldelem_I1: type = new TypeReference("System", "SByte", module, module); break; case Code.Ldelem_I2: type = new TypeReference("System", "Int16", module, module); break; case Code.Ldelem_I4: type = new TypeReference("System", "Int32", module, module); break; case Code.Ldelem_I8: type = new TypeReference("System", "Int64", module, module); break; case Code.Ldelem_U1: type = new TypeReference("System", "Byte", module, module); break; case Code.Ldelem_U2: type = new TypeReference("System", "UInt16", module, module); break; case Code.Ldelem_U4: type = new TypeReference("System", "UInt32", module, module); break; case Code.Ldelem_R4: type = new TypeReference("System", "Single", module, module); break; case Code.Ldelem_R8: type = new TypeReference("System", "Double", module, module); break; case Code.Ldelem_Ref: default: { // array is the lower item in the stack var array_instruction = Analysis[addr_instruction.Previous].Tail.Head.Item1; // whatever load loaded this array it will have a type with it type = array_instruction.Operand as TypeReference; } break; } StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldelema, type)); } else { throw new Exception("ReplaceLoadAddress: How did we get here?!"); } StackAnalyser.RemoveInstruction(ilProcessor, instruction); return(next); }