Example #1
0
        public static ExceptionHandler FromReader(CilMethodBody cilMethodBody, IBinaryStreamReader reader, bool fatFormat)
        {
            var offset                   = reader.Position;
            var handerType               = fatFormat ? reader.ReadUInt32() : reader.ReadUInt16();
            var tryOffset                = fatFormat ? reader.ReadInt32() : reader.ReadUInt16();
            var tryLength                = fatFormat ? reader.ReadInt32() : reader.ReadByte();
            var handlerOffset            = fatFormat ? reader.ReadInt32() : reader.ReadUInt16();
            var handlerLength            = fatFormat ? reader.ReadInt32() : reader.ReadByte();
            var classTokenOrFilterOffset = reader.ReadUInt32();

            var handler = new ExceptionHandler((ExceptionHandlerType)handerType)
            {
                IsFat        = fatFormat,
                TryStart     = cilMethodBody.GetInstructionByOffset(tryOffset),
                TryEnd       = cilMethodBody.GetInstructionByOffset(tryOffset + tryLength),
                HandlerStart = cilMethodBody.GetInstructionByOffset(handlerOffset),
                HandlerEnd   = cilMethodBody.GetInstructionByOffset(handlerOffset + handlerLength),
            };

            switch (handler.HandlerType)
            {
            case ExceptionHandlerType.Exception:
                handler.CatchType = (ITypeDefOrRef)((IOperandResolver)cilMethodBody).ResolveMember(new MetadataToken(classTokenOrFilterOffset));
                break;

            case ExceptionHandlerType.Filter:
                handler.FilterStart = cilMethodBody.GetInstructionByOffset((int)classTokenOrFilterOffset);
                break;
            }

            return(handler);
        }
Example #2
0
 public StackInbalanceException(CilMethodBody body, int offset)
     : base(string.Format("Stack inbalance was detected at offset {0:X4} in method body of {1}", offset,
                          body.Method))
 {
     Body   = body;
     Offset = offset;
 }
Example #3
0
        /// <summary>
        /// Interprets a raw method body to a CILMethodBody, disassembling all instructions, obtaining the local variables
        /// and reading the extra sections for exception handlers.
        /// </summary>
        /// <param name="method">The parent method the method body is associated to.</param>
        /// <param name="rawMethodBody">The raw method body to convert.</param>
        /// <returns>The converted method body.</returns>
        public static CilMethodBody FromRawMethodBody(MethodDefinition method, CilRawMethodBody rawMethodBody)
        {
            var body = new CilMethodBody(method);

            var fatBody = rawMethodBody as CilRawFatMethodBody;

            if (fatBody != null)
            {
                // Read fat method body header fields.
                body.MaxStack   = fatBody.MaxStack;
                body.InitLocals = fatBody.InitLocals;

                if (method.Image.TryResolveMember(new MetadataToken(fatBody.LocalVarSigToken), out var signature))
                {
                    body.Signature = signature as StandAloneSignature;
                }
            }
            else
            {
                // Set values for tiny method bodies.
                body.MaxStack   = 8;
                body.InitLocals = false;
            }

            // Read code.
            var codeReader   = new MemoryStreamReader(rawMethodBody.Code);
            var disassembler = new CilDisassembler(codeReader, body);

            foreach (var instruction in disassembler.Disassemble())
            {
                body.Instructions.Add(instruction);
            }

            if (fatBody != null)
            {
                // Read exception handlers.
                foreach (var section in fatBody.ExtraSections)
                {
                    var sectionReader = new MemoryStreamReader(section.Data);
                    while (sectionReader.CanRead(section.IsFat
                        ? ExceptionHandler.FatExceptionHandlerSize
                        : ExceptionHandler.SmallExceptionHandlerSize))
                    {
                        body.ExceptionHandlers.Add(ExceptionHandler.FromReader(body, sectionReader, section.IsFat));
                    }
                }
            }

            return(body);
        }
Example #4
0
        /// <summary>
        /// Determines the amount of values pushed onto the stack by this instruction.
        /// </summary>
        /// <param name="parent">The parent method body the instruction is residing in.</param>
        /// <returns>A non-negative number representing the amount of values pushed onto the stack.</returns>
        public int GetStackPushCount(CilMethodBody parent)
        {
            MethodSignature signature  = null;
            var             member     = Operand as ICallableMemberReference;
            var             standalone = Operand as StandAloneSignature;

            if (member != null)
            {
                signature = member.Signature as MethodSignature;
            }
            else if (standalone != null)
            {
                signature = standalone.Signature as MethodSignature;
            }

            switch (OpCode.StackBehaviourPush)
            {
            case CilStackBehaviour.Push1:
            case CilStackBehaviour.Pushi:
            case CilStackBehaviour.Pushi8:
            case CilStackBehaviour.Pushr4:
            case CilStackBehaviour.Pushr8:
            case CilStackBehaviour.Pushref:
                return(1);

            case CilStackBehaviour.Push1_push1:
                return(2);

            case CilStackBehaviour.Varpush:
                if (signature != null &&
                    (!signature.ReturnType.IsTypeOf("System", "Void") || OpCode.Code == CilCode.Newobj))
                {
                    return(1);
                }
                break;
            }

            return(0);
        }
Example #5
0
        public static CilMethodBody FromRawMethodBody(MethodDefinition method, CilRawMethodBody rawMethodBody)
        {
            var body = new CilMethodBody(method);

            var fatBody = rawMethodBody as CilRawFatMethodBody;

            if (fatBody != null)
            {
                body.MaxStack   = fatBody.MaxStack;
                body.InitLocals = fatBody.InitLocals;

                IMetadataMember signature;
                if (method.Image.TryResolveMember(new MetadataToken(fatBody.LocalVarSigToken), out signature))
                {
                    body.Signature = signature as StandAloneSignature;
                }
            }

            var codeReader   = new MemoryStreamReader(rawMethodBody.Code);
            var disassembler = new CilDisassembler(codeReader, body);

            foreach (var instruction in disassembler.Disassemble())
            {
                body.Instructions.Add(instruction);
            }

            if (fatBody != null)
            {
                foreach (var section in fatBody.ExtraSections)
                {
                    var sectionReader = new MemoryStreamReader(section.Data);
                    body.ExceptionHandlers.Add(ExceptionHandler.FromReader(body, sectionReader, section.IsFat));
                }
            }

            return(body);
        }
 public DefaultOperandBuilder(CilMethodBody methodBody, MetadataBuffer buffer)
 {
     _methodBody = methodBody;
     _buffer     = buffer;
 }
Example #7
0
        public int GetStackDelta(CilMethodBody parent)
        {
            int delta = 0;

            MethodSignature signature  = null;
            var             member     = Operand as IMethodDefOrRef;
            var             standalone = Operand as StandAloneSignature;

            if (member != null)
            {
                signature = (MethodSignature)member.Signature;
            }
            else if (standalone != null)
            {
                signature = (MethodSignature)standalone.Signature;
            }

            switch (OpCode.StackBehaviourPop)
            {
            case CilStackBehaviour.Pop1:
            case CilStackBehaviour.Popi:
            case CilStackBehaviour.Popref:
                delta = -1;
                break;

            case CilStackBehaviour.Pop1_pop1:
            case CilStackBehaviour.Popi_pop1:
            case CilStackBehaviour.Popi_popi:
            case CilStackBehaviour.Popi_popi8:
            case CilStackBehaviour.Popi_popr4:
            case CilStackBehaviour.Popi_popr8:
            case CilStackBehaviour.Popref_pop1:
            case CilStackBehaviour.Popref_popi:
                delta = -2;
                break;

            case CilStackBehaviour.Popi_popi_popi:
            case CilStackBehaviour.Popref_popi_popi:
            case CilStackBehaviour.Popref_popi_popi8:
            case CilStackBehaviour.Popref_popi_popr4:
            case CilStackBehaviour.Popref_popi_popr8:
            case CilStackBehaviour.Popref_popi_popref:
                delta = -3;
                break;

            case CilStackBehaviour.Varpop:
                if (signature == null)
                {
                    if (OpCode.Code == CilCode.Ret)
                    {
                        delta = parent.Method.Signature.ReturnType.IsTypeOf("System", "Void") ? 0 : -1;
                    }
                    else
                    {
                        throw new ArgumentException("Invalid or unsupported operand.");
                    }
                }
                else
                {
                    delta = -signature.Parameters.Count;
                    if (signature.HasThis)
                    {
                        delta--;
                    }
                }
                break;
            }

            switch (OpCode.StackBehaviourPush)
            {
            case CilStackBehaviour.Push1:
            case CilStackBehaviour.Pushi:
            case CilStackBehaviour.Pushi8:
            case CilStackBehaviour.Pushr4:
            case CilStackBehaviour.Pushr8:
            case CilStackBehaviour.Pushref:
                delta++;
                break;

            case CilStackBehaviour.Push1_push1:
                delta += 2;
                break;

            case CilStackBehaviour.Varpush:
                if (signature == null)
                {
                    throw new ArgumentException("Invalid or unsupported operand.");
                }

                if (!signature.ReturnType.IsTypeOf("System", "Void"))
                {
                    delta++;
                }
                break;

            case CilStackBehaviour.Popref_popi_pop1:
                delta += 3;
                break;
            }

            return(delta);
        }
Example #8
0
 public CilInstructionFormatter(CilMethodBody methodBody)
 {
     _methodBody = methodBody ?? throw new ArgumentNullException(nameof(methodBody));
 }
 public CilInstructionCollection(CilMethodBody body)
 {
     _body = body ?? throw new ArgumentNullException(nameof(body));
 }
Example #10
0
 /// <summary>
 /// Determines the stack delta of the instruction. That is, the amount of values pushed onto the stack
 /// subtracted from the amount of values popped from the stack.
 /// </summary>
 /// <param name="parent">The parent method body the instruction is residing in.</param>
 /// <returns>A number representing the stack delta.</returns>
 public int GetStackDelta(CilMethodBody parent)
 {
     return(GetStackPushCount(parent) - GetStackPopCount(parent));
 }
Example #11
0
        /// <summary>
        /// Determines the amount of values popped from the stack by this instruction.
        /// </summary>
        /// <param name="parent">The parent method body the instruction is residing in.</param>
        /// <returns>A non-negative number representing the amount of values popped from the stack.</returns>
        public int GetStackPopCount(CilMethodBody parent)
        {
            MethodSignature signature  = null;
            var             member     = Operand as ICallableMemberReference;
            var             standalone = Operand as StandAloneSignature;

            if (member != null)
            {
                signature = member.Signature as MethodSignature;
            }
            else if (standalone != null)
            {
                signature = standalone.Signature as MethodSignature;
            }

            switch (OpCode.StackBehaviourPop)
            {
            case CilStackBehaviour.Pop1:
            case CilStackBehaviour.Popi:
            case CilStackBehaviour.Popref:
                return(1);

            case CilStackBehaviour.Pop1_pop1:
            case CilStackBehaviour.Popi_pop1:
            case CilStackBehaviour.Popi_popi:
            case CilStackBehaviour.Popi_popi8:
            case CilStackBehaviour.Popi_popr4:
            case CilStackBehaviour.Popi_popr8:
            case CilStackBehaviour.Popref_pop1:
            case CilStackBehaviour.Popref_popi:
                return(2);

            case CilStackBehaviour.Popi_popi_popi:
            case CilStackBehaviour.Popref_popi_pop1:
            case CilStackBehaviour.Popref_popi_popi:
            case CilStackBehaviour.Popref_popi_popi8:
            case CilStackBehaviour.Popref_popi_popr4:
            case CilStackBehaviour.Popref_popi_popr8:
            case CilStackBehaviour.Popref_popi_popref:
                return(3);

            case CilStackBehaviour.Varpop:
                if (signature == null)
                {
                    if (OpCode.Code == CilCode.Ret)
                    {
                        return(parent.Method.Signature.ReturnType.IsTypeOf("System", "Void") ? 0 : 1);
                    }
                }
                else
                {
                    int count = signature.Parameters.Count;
                    if (signature.HasThis && OpCode.Code != CilCode.Newobj)
                    {
                        count++;
                    }
                    return(count);
                }

                break;
            }

            return(0);
        }