private PackedSwitchData ExtractPackedSwitch(Instruction ins, int offset) { int baseOffset = offset; var result = new PackedSwitchData(); ProcessPseudoCode(PseudoOpCodes.PackedSwitch, ref offset); int targetcount = ReadShort(ref offset); result.FirstKey = ReadInt(ref offset); for (var i = 0; i < targetcount; i++) { var target = ReadInt(ref offset); LazyInstructionsSetters.Add(() => result.Targets.Add(Lookup[(ushort)(ins.Offset + target)])); } if (offset - baseOffset != targetcount * 2 + 4) { throw new MalformedException("Unexpected Packed switch blocksize"); } return(result); }
/// <summary> /// Note that referencing operands, i.e. TypeReferences, FieldReference or /// MethodRefrences are not cloned, but only shallow copied. /// If you indend to modify those operand values themself, be sure to clone /// them beforehand. /// </summary> public static MethodBody Clone(MethodDefinition targetMethod, MethodDefinition sourceMethod) { var sourceBody = sourceMethod.Body; MethodBody body = new MethodBody(targetMethod, sourceBody.Registers.Count) { IncomingArguments = sourceBody.IncomingArguments, OutgoingArguments = sourceBody.OutgoingArguments }; foreach (var sourceIns in sourceBody.Instructions) { var ins = new Instruction(sourceIns.OpCode); foreach (var r in sourceIns.Registers) { ins.Registers.Add(body.Registers[r.Index]); } ins.Offset = sourceIns.Offset; ins.SequencePoint = ins.SequencePoint; ins.Operand = sourceIns.Operand; body.Instructions.Add(ins); } // fix instruction references var insByOffset = body.Instructions.ToDictionary(i => i.Offset); foreach (var ins in body.Instructions) { var targetIns = ins.Operand as Instruction; var packedSwitch = ins.Operand as PackedSwitchData; var sparseSwitch = ins.Operand as SparseSwitchData; if (targetIns != null) { ins.Operand = insByOffset[targetIns.Offset]; } else if (packedSwitch != null) { var ps = new PackedSwitchData(packedSwitch.Targets.Select(si => insByOffset[si.Offset])); ps.FirstKey = packedSwitch.FirstKey; ins.Operand = ps; } else if (sparseSwitch != null) { var ss = new SparseSwitchData(); foreach (var ssd in sparseSwitch.Targets) { ss.Targets.Add(ssd.Key, insByOffset[ssd.Value.Offset]); } ins.Operand = ss; } } foreach (var sourceEx in sourceBody.Exceptions) { var ex = new ExceptionHandler(); if (sourceEx.TryStart != null) { ex.TryStart = insByOffset[sourceEx.TryStart.Offset]; } if (sourceEx.TryEnd != null) { ex.TryEnd = insByOffset[sourceEx.TryEnd.Offset]; } if (sourceEx.CatchAll != null) { ex.CatchAll = insByOffset[sourceEx.CatchAll.Offset]; } foreach (var sourceCatch in sourceEx.Catches) { var c = new Catch { Type = sourceCatch.Type, Instruction = insByOffset[sourceCatch.Instruction.Offset] }; ex.Catches.Add(c); } body.Exceptions.Add(ex); } if (sourceBody.DebugInfo != null) { var di = body.DebugInfo = new DebugInfo(body); di.LineStart = sourceBody.DebugInfo.LineStart; di.Parameters = sourceBody.DebugInfo.Parameters.ToList(); foreach (var sourceInstruction in sourceBody.DebugInfo.DebugInstructions) { di.DebugInstructions.Add(new DebugInstruction(sourceInstruction.OpCode, sourceInstruction.Operands.ToList())); } } return(body); }
private PackedSwitchData ExtractPackedSwitch(Instruction ins, int offset) { int baseOffset = offset; var result = new PackedSwitchData(); ProcessPseudoCode(PseudoOpCodes.PackedSwitch, ref offset); int targetcount = ReadShort(ref offset); result.FirstKey = ReadInt(ref offset); for (var i=0; i<targetcount; i++) { var target = ReadInt(ref offset); LazyInstructionsSetters.Add( () => result.Targets.Add(Lookup[ins.Offset + target])); } if (offset - baseOffset != targetcount * 2 + 4) throw new MalformedException("Unexpected Packed switch blocksize"); return result; }