/// <summary> /// Creates a CIL method body from a raw CIL method body. /// </summary> /// <param name="method">The method that owns the method body.</param> /// <param name="rawBody">The raw method body.</param> /// <param name="operandResolver">The object instance to use for resolving operands of an instruction in the /// method body.</param> /// <returns>The method body.</returns> public static CilMethodBody FromRawMethodBody(MethodDefinition method, CilRawMethodBody rawBody, ICilOperandResolver operandResolver = null) { var result = new CilMethodBody(method); if (operandResolver is null) operandResolver = result; // Read raw instructions. var reader = new ByteArrayReader(rawBody.Code); var disassembler = new CilDisassembler(reader); result.Instructions.AddRange(disassembler.ReadAllInstructions()); // Read out extra metadata. if (rawBody is CilRawFatMethodBody fatBody) { result.MaxStack = fatBody.MaxStack; result.InitializeLocals = fatBody.InitLocals; ReadLocalVariables(method.Module, result, fatBody); ReadExceptionHandlers(fatBody, result); } else { result.MaxStack = 8; result.InitializeLocals = false; } // Resolve operands. foreach (var instruction in result.Instructions) instruction.Operand = ResolveOperand(result, instruction, operandResolver) ?? instruction.Operand; return result; }
public static object ResolveOperandReflection(ModuleReaderContext context, CilMethodBody methodBody, CilInstruction instruction, ICilOperandResolver resolver, List <object> tokens, ReferenceImporter importer) { switch (instruction.OpCode.OperandType) { case CilOperandType.InlineBrTarget: case CilOperandType.ShortInlineBrTarget: return(methodBody.Instructions .GetByOffset(((ICilLabel)instruction.Operand).Offset) ?.CreateLabel()); case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: return(ReadToken(context, ((MetadataToken)instruction.Operand).ToUInt32(), tokens, importer)); case CilOperandType.InlineString: return(ReadToken(context, ((MetadataToken)instruction.Operand).ToUInt32(), tokens, importer)); case CilOperandType.InlineSwitch: var result = new List <ICilLabel>(); var labels = (IList <ICilLabel>)instruction.Operand; for (int i = 0; i < labels.Count; i++) { var label = labels[i]; var target = methodBody.Instructions.GetByOffset(label.Offset); result.Add(target != null ? new CilInstructionLabel(target) : label); } return(result); case CilOperandType.InlineVar: case CilOperandType.ShortInlineVar: return(resolver.ResolveLocalVariable(Convert.ToInt32(instruction.Operand))); case CilOperandType.InlineArgument: case CilOperandType.ShortInlineArgument: return(resolver.ResolveParameter(Convert.ToInt32(instruction.Operand))); case CilOperandType.InlineI: case CilOperandType.InlineI8: case CilOperandType.InlineNone: case CilOperandType.InlineR: case CilOperandType.ShortInlineI: case CilOperandType.ShortInlineR: return(instruction.Operand); case CilOperandType.InlinePhi: throw new NotSupportedException(); default: throw new ArgumentOutOfRangeException(); } }
private static object ResolveOperand(CilMethodBody methodBody, CilInstruction instruction, ICilOperandResolver resolver) { switch (instruction.OpCode.OperandType) { case CilOperandType.InlineBrTarget: case CilOperandType.ShortInlineBrTarget: return new CilInstructionLabel( methodBody.Instructions.GetByOffset(((ICilLabel) instruction.Operand).Offset)); case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: return resolver.ResolveMember((MetadataToken) instruction.Operand); case CilOperandType.InlineString: return resolver.ResolveString((MetadataToken) instruction.Operand); case CilOperandType.InlineSwitch: var result = new List<ICilLabel>(); var labels = (IEnumerable<ICilLabel>) instruction.Operand; foreach (var label in labels) { var target = methodBody.Instructions.GetByOffset(label.Offset); result.Add(target == null ? label : new CilInstructionLabel(target)); } return result; case CilOperandType.InlineVar: case CilOperandType.ShortInlineVar: return resolver.ResolveLocalVariable(Convert.ToInt32(instruction.Operand)); case CilOperandType.InlineArgument: case CilOperandType.ShortInlineArgument: return resolver.ResolveParameter(Convert.ToInt32(instruction.Operand)); case CilOperandType.InlineI: case CilOperandType.InlineI8: case CilOperandType.InlineNone: case CilOperandType.InlineR: case CilOperandType.ShortInlineI: case CilOperandType.ShortInlineR: return instruction.Operand; case CilOperandType.InlinePhi: throw new NotSupportedException(); default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Creates a CIL method body from a dynamic method. /// </summary> /// <param name="method">The method that owns the method body.</param> /// <param name="dynamicMethodObj">The Dynamic Method/Delegate/DynamicResolver.</param> /// <param name="operandResolver"> /// The object instance to use for resolving operands of an instruction in the /// method body. /// </param> /// <param name="importer"> /// The object instance to use for importing operands of an instruction in the /// method body. /// </param> /// <returns>The method body.</returns> public static CilMethodBody FromDynamicMethod( MethodDefinition method, object dynamicMethodObj, ICilOperandResolver operandResolver = null, ReferenceImporter importer = null) { if (!(method.Module is SerializedModuleDefinition module)) { throw new ArgumentException("Method body should reference a serialized module."); } var result = new CilMethodBody(method); operandResolver ??= new CilOperandResolver(method.Module, result); importer ??= new ReferenceImporter(method.Module); dynamicMethodObj = DynamicMethodHelper.ResolveDynamicResolver(dynamicMethodObj); //Get Runtime Fields var code = FieldReader.ReadField <byte[]>(dynamicMethodObj, "m_code"); var scope = FieldReader.ReadField <object>(dynamicMethodObj, "m_scope"); var tokenList = FieldReader.ReadField <List <object> >(scope, "m_tokens"); var localSig = FieldReader.ReadField <byte[]>(dynamicMethodObj, "m_localSignature"); var ehHeader = FieldReader.ReadField <byte[]>(dynamicMethodObj, "m_exceptionHeader"); var ehInfos = FieldReader.ReadField <IList <object> >(dynamicMethodObj, "m_exceptions"); // Read raw instructions. var reader = new ByteArrayReader(code); var disassembler = new CilDisassembler(reader); result.Instructions.AddRange(disassembler.ReadAllInstructions()); //Local Variables DynamicMethodHelper.ReadLocalVariables(result, method, localSig); //Exception Handlers DynamicMethodHelper.ReadReflectionExceptionHandlers(result, ehInfos, ehHeader, importer); // Resolve all operands. foreach (var instruction in result.Instructions) { instruction.Operand = DynamicMethodHelper.ResolveOperandReflection(module.ReaderContext, result, instruction, operandResolver, tokenList, importer) ?? instruction.Operand; } return(result); }
/// <summary> /// Creates a new CIL disassembler using the provided input stream. /// </summary> /// <param name="reader">The input stream to read the code from.</param> /// <param name="operandResolver">The object responsible for resolving operands.</param> public CilDisassembler(IBinaryStreamReader reader, ICilOperandResolver operandResolver) { _reader = reader ?? throw new ArgumentNullException(nameof(reader)); _operandResolver = operandResolver ?? throw new ArgumentNullException(nameof(operandResolver)); }