/// <summary>
 /// Creates a new instance of the <see cref="StackImbalanceException"/> class.
 /// </summary>
 /// <param name="body">The method body in which the inconsistency was detected.</param>
 /// <param name="offset">The offset at which the inconsistency was detected.</param>
 public StackImbalanceException(CilMethodBody body, int offset)
     : base(string.Format("Stack imbalance was detected at offset IL_{0:X4} in method body of {1}",
                          offset, body.Owner))
 {
     Body   = body;
     Offset = offset;
 }
Beispiel #2
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;
        }
 /// <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);
 }
        /// <summary>
        /// Reads a single exception handler from the provided input stream.
        /// </summary>
        /// <param name="body">The method body containing the exception handler.</param>
        /// <param name="reader">The input stream.</param>
        /// <param name="isFat"><c>true</c> if the fat format should be used, <c>false</c> otherwise.</param>
        /// <returns>The exception handler.</returns>
        public static CilExceptionHandler FromReader(CilMethodBody body, IBinaryStreamReader reader, bool isFat)
        {
            CilExceptionHandlerType handlerType;
            int tryStartOffset;
            int tryEndOffset;
            int handlerStartOffset;
            int handlerEndOffset;

            // Read raw structure.
            if (isFat)
            {
                handlerType        = (CilExceptionHandlerType)reader.ReadUInt32();
                tryStartOffset     = reader.ReadInt32();
                tryEndOffset       = tryStartOffset + reader.ReadInt32();
                handlerStartOffset = reader.ReadInt32();
                handlerEndOffset   = handlerStartOffset + reader.ReadInt32();
            }
            else
            {
                handlerType        = (CilExceptionHandlerType)reader.ReadUInt16();
                tryStartOffset     = reader.ReadUInt16();
                tryEndOffset       = tryStartOffset + reader.ReadByte();
                handlerStartOffset = reader.ReadUInt16();
                handlerEndOffset   = handlerStartOffset + reader.ReadByte();
            }

            int exceptionTokenOrFilterStart = reader.ReadInt32();

            // Create handler.
            var handler = new CilExceptionHandler
            {
                HandlerType = handlerType,
                TryStart    = body.Instructions.GetByOffset(tryStartOffset)?.CreateLabel() ??
                              new CilOffsetLabel(tryStartOffset),
                TryEnd       = body.Instructions.GetByOffset(tryEndOffset)?.CreateLabel() ?? new CilOffsetLabel(tryEndOffset),
                HandlerStart = body.Instructions.GetByOffset(handlerStartOffset)?.CreateLabel() ??
                               new CilOffsetLabel(handlerStartOffset),
                HandlerEnd = body.Instructions.GetByOffset(handlerEndOffset)?.CreateLabel() ??
                             new CilOffsetLabel(handlerEndOffset),
            };

            // Interpret last field.
            switch (handler.HandlerType)
            {
            case CilExceptionHandlerType.Exception when body.Owner.Module.TryLookupMember(exceptionTokenOrFilterStart, out var member):
                handler.ExceptionType = member as ITypeDefOrRef;

                break;

            case CilExceptionHandlerType.Filter:
                handler.FilterStart = body.Instructions.GetByOffset(exceptionTokenOrFilterStart)?.CreateLabel()
                                      ?? new CilOffsetLabel(exceptionTokenOrFilterStart);
                break;;
            }

            return(handler);
        }
Beispiel #5
0
 private static void ReadLocalVariables(
     ModuleDefinition module,
     CilMethodBody result,
     CilRawFatMethodBody fatBody)
 {
     if (fatBody.LocalVarSigToken != MetadataToken.Zero &&
         module.TryLookupMember(fatBody.LocalVarSigToken, out var member) &&
         member is StandAloneSignature {
         Signature : LocalVariablesSignature localVariablesSignature
     })
        private static byte[] BuildRawCodeStream(IMetadataTokenProvider provider, CilMethodBody body)
        {
            using var codeStream = new MemoryStream();

            var writer    = new BinaryStreamWriter(codeStream);
            var assembler = new CilAssembler(writer, new CilOperandBuilder(provider));

            assembler.WriteInstructions(body.Instructions);

            return(codeStream.ToArray());
        }
Beispiel #7
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();
            }
        }
Beispiel #8
0
 private static void ReadLocalVariables(ModuleDefinition module, CilMethodBody result,
     CilRawFatMethodBody fatBody)
 {
     if (fatBody.LocalVarSigToken != MetadataToken.Zero
         && module.TryLookupMember(fatBody.LocalVarSigToken, out var member)
         && member is StandAloneSignature signature
         && signature.Signature is LocalVariablesSignature localVariablesSignature)
     {
         foreach (var type in localVariablesSignature.VariableTypes)
             result.LocalVariables.Add(new CilLocalVariable(type));
     }
 }
Beispiel #9
0
        public CilMaxStackCalculator(CilMethodBody body)
        {
            _body = body ?? throw new ArgumentNullException(nameof(body));

            if (_body.Instructions.Count > 0)
            {
                _agenda             = new Stack <StackState>();
                _recordedStackSizes = new int?[_body.Instructions.Count];
            }
            else
            {
                _agenda             = null;
                _recordedStackSizes = null;
            }
        }
Beispiel #10
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);
        }
Beispiel #11
0
        private static void ReadExceptionHandlers(CilRawFatMethodBody fatBody, CilMethodBody result)
        {
            foreach (var section in fatBody.ExtraSections)
            {
                if (section.IsEHTable)
                {
                    var reader = new ByteArrayReader(section.Data);
                    int size = section.IsFat
                        ? CilExceptionHandler.FatExceptionHandlerSize
                        : CilExceptionHandler.TinyExceptionHandlerSize;

                    while (reader.CanRead(size))
                        result.ExceptionHandlers.Add(CilExceptionHandler.FromReader(result, reader, section.IsFat));
                }
            }
        }
        private CilRawMethodBody BuildFatMethodBody(IMetadataTokenProvider provider, CilMethodBody body, byte[] code)
        {
            // Serialize local variables.
            MetadataToken token;

            if (body.LocalVariables.Count == 0)
            {
                token = MetadataToken.Zero;
            }
            else
            {
                var localVarSig   = new LocalVariablesSignature(body.LocalVariables.Select(v => v.VariableType));
                var standAloneSig = new StandAloneSignature(localVarSig);
                token = provider.GetStandAloneSignatureToken(standAloneSig);
            }

            var fatBody = new CilRawFatMethodBody(CilMethodBodyAttributes.Fat, (ushort)body.MaxStack, token, code);

            fatBody.InitLocals = body.InitializeLocals;

            // Build up EH table section.
            if (body.ExceptionHandlers.Count > 0)
            {
                fatBody.HasSections = true;
                bool needsFatFormat = body.ExceptionHandlers.Any(e => e.IsFat);

                var attributes = CilExtraSectionAttributes.EHTable;
                if (needsFatFormat)
                {
                    attributes |= CilExtraSectionAttributes.FatFormat;
                }

                var rawSectionData = SerializeExceptionHandlers(provider, body.ExceptionHandlers, needsFatFormat);
                var section        = new CilExtraSection(attributes, rawSectionData);
                fatBody.ExtraSections.Add(section);
            }

            return(fatBody);
        }
 /// <summary>
 /// Creates a new instance of the <see cref="PhysicalCilOperandResolver"/> class.
 /// </summary>
 /// <param name="contextModule">The context module.</param>
 /// <param name="methodBody">The method body that references the operands.</param>
 public PhysicalCilOperandResolver(ModuleDefinition contextModule, CilMethodBody methodBody)
 {
     _contextModule = contextModule ?? throw new ArgumentNullException(nameof(contextModule));
     _methodBody    = methodBody ?? throw new ArgumentNullException(nameof(methodBody));
 }
Beispiel #14
0
 public CilLabelVerifier(CilMethodBody body)
 {
     _body        = body ?? throw new ArgumentNullException(nameof(body));
     _diagnostics = null;
     _cachedName  = null;
 }
 /// <summary>
 /// Determines the number of values that are popped from the stack by this instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="parent">The method body that this instruction resides in. When passed on <c>null</c>,
 /// a method body of a System.Void method is assumed.</param>
 /// <returns>The number of values popped from the stack.</returns>
 /// <exception cref="ArgumentOutOfRangeException">Occurs when the instruction's operation code provides an
 /// invalid stack behaviour.</exception>
 public static int GetStackPopCount(this CilInstruction instruction, CilMethodBody parent)
 {
     return(GetStackPopCount(instruction,
                             parent == null ||
                             (parent.Owner.Signature.ReturnType?.IsTypeOf("System", "Void")).GetValueOrDefault()));
 }
Beispiel #16
0
        private static byte[] BuildRawCodeStream(MethodBodySerializationContext context, CilMethodBody body)
        {
            using var codeStream = new MemoryStream();
            var bag = context.DiagnosticBag;

            var writer    = new BinaryStreamWriter(codeStream);
            var assembler = new CilAssembler(
                writer,
                new CilOperandBuilder(context.TokenProvider, bag),
                body.Owner.SafeToString(),
                bag);

            assembler.WriteInstructions(body.Instructions);

            return(codeStream.ToArray());
        }
 /// <summary>
 /// Creates a new collection of CIL instructions stored in a method body.
 /// </summary>
 /// <param name="body">The method body that owns the collection.</param>
 public CilInstructionCollection(CilMethodBody body)
 {
     Owner = body ?? throw new ArgumentNullException(nameof(body));
 }
Beispiel #18
0
 /// <summary>
 /// Determines the number of values that are popped from the stack by this instruction.
 /// </summary>
 /// <param name="instruction">The instruction.</param>
 /// <param name="parent">The method body that this instruction resides in. When passed on <c>null</c>,
 /// a method body of a System.Void method is assumed.</param>
 /// <returns>The number of values popped from the stack.</returns>
 /// <exception cref="ArgumentOutOfRangeException">Occurs when the instruction's operation code provides an
 /// invalid stack behaviour.</exception>
 public static int GetStackPopCount(this CilInstruction instruction, CilMethodBody parent) =>
 GetStackPopCount(instruction,
                  parent == null || parent.Owner.Signature.ReturnType.IsTypeOf("System", "Void"));