예제 #1
0
        /// <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;
        }
예제 #2
0
        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();
            }
        }
예제 #3
0
        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();
            }
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
 /// <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));
 }