/// <inheritdoc /> public DynamicCilOperandResolver(SerializedModuleDefinition contextModule, CilMethodBody methodBody, IList <object> tokens) : base(contextModule, methodBody) { _tokens = tokens ?? throw new ArgumentNullException(nameof(tokens)); _readerContext = contextModule.ReaderContext; _importer = new ReferenceImporter(contextModule); }
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(); } }
/// <summary> /// Creates a CIL method body from a raw CIL method body. /// </summary> /// <param name="context">The reader context.</param> /// <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( ModuleReaderContext context, MethodDefinition method, CilRawMethodBody rawBody, ICilOperandResolver operandResolver = null) { var result = new CilMethodBody(method); if (operandResolver is null) { operandResolver = new CilOperandResolver(context.ParentModule, 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); }
private static object ReadToken(ModuleReaderContext readerContext, MetadataToken token, IList <object> tokens, ReferenceImporter importer) { switch (token.Table) { case TableIndex.TypeDef: var type = tokens[(int)token.Rid]; if (type is RuntimeTypeHandle runtimeTypeHandle) { return(importer.ImportType(Type.GetTypeFromHandle(runtimeTypeHandle))); } break; case TableIndex.Field: var field = tokens[(int)token.Rid]; if (field is null) { return(null); } if (field is RuntimeFieldHandle runtimeFieldHandle) { return(importer.ImportField(FieldInfo.GetFieldFromHandle(runtimeFieldHandle))); } if (field.GetType().FullName == "System.Reflection.Emit.GenericFieldInfo") { var result = FieldReader.TryReadField <RuntimeFieldHandle>(field, "m_field", out var mField); var ctx = FieldReader.ReadField <RuntimeTypeHandle>(field, "m_context"); return(importer.ImportField(FieldInfo.GetFieldFromHandle(result ? mField : FieldReader.ReadField <RuntimeFieldHandle>(field, "m_fieldHandle"), ctx))); } break; case TableIndex.Method: case TableIndex.MemberRef: var obj = tokens[(int)token.Rid]; if (obj is RuntimeMethodHandle methodHandle) { return(importer.ImportMethod(MethodBase.GetMethodFromHandle(methodHandle))); } if (obj.GetType().FullName == "System.Reflection.Emit.GenericMethodInfo") { var context = FieldReader.ReadField <RuntimeTypeHandle>(obj, "m_context"); var res = FieldReader.TryReadField <RuntimeMethodHandle>(obj, "m_method", out var m_method); var m_handle = FieldReader.ReadField <RuntimeMethodHandle>(obj, "m_methodHandle"); var method = MethodBase.GetMethodFromHandle( res ? m_method : m_handle, context); return(importer.ImportMethod(method)); } if (obj.GetType().FullName == "System.Reflection.Emit.VarArgMethod") { return(importer.ImportMethod(FieldReader.ReadField <MethodInfo>(obj, "m_method"))); } break; case TableIndex.StandAloneSig: return(CallingConventionSignature.FromReader( new BlobReadContext(readerContext), new ByteArrayReader((byte[])tokens[(int)token.Rid]))); case (TableIndex)112: return(tokens[(int)token.Rid] as string); } return(null); }
/// <summary> /// Creates a new instance of the <see cref="BlobReadContext"/> structure. /// </summary> /// <param name="readerContext">The original read context.</param> /// <param name="traversedTokens">A collection of traversed metadata tokens.</param> public BlobReadContext(ModuleReaderContext readerContext, IEnumerable <MetadataToken> traversedTokens) { ReaderContext = readerContext; TraversedTokens = new HashSet <MetadataToken>(traversedTokens); }
/// <summary> /// Creates a new instance of the <see cref="BlobReadContext"/> structure. /// </summary> /// <param name="readerContext">The original read context.</param> public BlobReadContext(ModuleReaderContext readerContext) : this(readerContext, Enumerable.Empty <MetadataToken>()) { }