예제 #1
0
        /// <summary>
        /// Decodes the instruction stream of the reader and populates the compiler.
        /// </summary>
        /// <param name="compiler">The compiler to populate.</param>
        /// <param name="header">The method _header.</param>
        private void Decode(IMethodCompiler compiler, ref MethodHeader header)
        {
            // Start of the code stream
            long codeStart = _codeReader.BaseStream.Position;

            // End of the code stream
            long codeEnd = _codeReader.BaseStream.Position + header.codeSize;

            // Prefix instruction
            //PrefixInstruction prefix = null;

            // Setup context
            Context ctx = new Context(InstructionSet, -1);

            while (codeEnd != _codeReader.BaseStream.Position)
            {
                // Determine the instruction offset
                int instOffset = (int)(_codeReader.BaseStream.Position - codeStart);

                // Read the next opcode From the stream
                OpCode op = (OpCode)_codeReader.ReadByte();
                if (OpCode.Extop == op)
                {
                    op = (OpCode)(0x100 | _codeReader.ReadByte());
                }

                ICILInstruction instruction = Instruction.Get(op);

                if (instruction == null)
                {
                    throw new Exception("CIL " + op + " is not yet supported");
                }

                //if (instruction is PrefixInstruction) {
                //    prefix = instruction as PrefixInstruction;
                //    continue;
                //}

                // Create and initialize the corresponding instruction
                ctx.AppendInstruction(instruction);
                instruction.Decode(ctx, this);
                ctx.Label = instOffset;
                //ctx.Prefix = prefix;

                Debug.Assert(ctx.Instruction != null);

                // Do we need to patch branch targets?
                if (instruction is IBranchInstruction && instruction.FlowControl != FlowControl.Return)
                {
                    int pc = (int)(_codeReader.BaseStream.Position - codeStart);

                    for (int i = 0; i < ctx.Branch.Targets.Length; i++)
                    {
                        ctx.Branch.Targets[i] += pc;
                    }
                }

                //prefix = null;
            }
        }
예제 #2
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            using (Stream code = methodCompiler.GetInstructionStream())
            {
                // Initialize the instruction
                methodCompiler.InstructionSet = new InstructionSet(256);

                // update the base class
                InstructionSet = methodCompiler.InstructionSet;

                using (codeReader = new BinaryReader(code))
                {
                    // The size of the code in bytes
                    MethodHeader header = new MethodHeader();
                    ReadMethodHeader(codeReader, ref header);

                    if (header.localsSignature.RID != 0)
                    {
                        StandAloneSigRow row = methodCompiler.Method.Module.MetadataModule.Metadata.ReadStandAloneSigRow(header.localsSignature);

                        LocalVariableSignature localsSignature;

                        if (methodCompiler.Method.DeclaringType is CilGenericType)
                        {
                            localsSignature = new LocalVariableSignature(methodCompiler.Method.Module.MetadataModule.Metadata, row.SignatureBlobIdx, (methodCompiler.Method.DeclaringType as CilGenericType).GenericArguments);
                        }
                        else
                        {
                            localsSignature = new LocalVariableSignature(methodCompiler.Method.Module.MetadataModule.Metadata, row.SignatureBlobIdx);
                        }

                        methodCompiler.SetLocalVariableSignature(localsSignature);
                    }

                    /* Decode the instructions */
                    Decode(methodCompiler, ref header);

                    // When we leave, the operand stack must only contain the locals...
                    //Debug.Assert(_operandStack.Count == _method.Locals.Count);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            // The size of the code in bytes
            MethodHeader header = new MethodHeader();

            using (Stream code = MethodCompiler.GetInstructionStream())
            {
                // Initalize the instruction, setting the initalize size to 10 times the code stream
                MethodCompiler.InstructionSet = new InstructionSet((int)code.Length * 10);

                // update the base class
                InstructionSet = MethodCompiler.InstructionSet;

                using (BinaryReader reader = new BinaryReader(code))
                {
                    _compiler   = MethodCompiler;
                    _method     = MethodCompiler.Method;
                    _codeReader = reader;

                    ReadMethodHeader(reader, ref header);
                    //Debug.WriteLine("Decoding " + compiler.Method.ToString());

                    if (0 != header.localsSignature)
                    {
                        StandAloneSigRow  row;
                        IMetadataProvider md = _method.Module.Metadata;
                        md.Read(header.localsSignature, out row);
                        MethodCompiler.SetLocalVariableSignature(LocalVariableSignature.Parse(md, row.SignatureBlobIdx));
                    }

                    /* Decode the instructions */
                    Decode(MethodCompiler, ref header);

                    // When we leave, the operand stack must only contain the locals...
                    //Debug.Assert(_operandStack.Count == _method.Locals.Count);
                    _codeReader = null;
                    _compiler   = null;
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Reads the method header from the instruction stream.
        /// </summary>
        /// <param name="reader">The reader used to decode the instruction stream.</param>
        /// <param name="header">The method header structure to populate.</param>
        private void ReadMethodHeader(BinaryReader reader, ref MethodHeader header)
        {
            // Read first byte
            header.flags = (MethodFlags)reader.ReadByte();

            // Check least significant 2 bits
            switch (header.flags & MethodFlags.HeaderMask)
            {
            case MethodFlags.TinyFormat:
                header.codeSize = ((uint)(header.flags & MethodFlags.TinyCodeSizeMask) >> 2);
                header.flags   &= MethodFlags.HeaderMask;
                break;

            case MethodFlags.FatFormat:
                // Read second byte of flags
                header.flags = (MethodFlags)(reader.ReadByte() << 8 | (byte)header.flags);
                if (MethodFlags.ValidHeader != (header.flags & MethodFlags.HeaderSizeMask))
                {
                    throw new InvalidDataException(@"Invalid method _header.");
                }
                header.maxStack        = reader.ReadUInt16();
                header.codeSize        = reader.ReadUInt32();
                header.localsSignature = new Token(reader.ReadUInt32());                         // ReadStandAloneSigRow
                break;

            default:
                throw new InvalidDataException(@"Invalid method header while trying to decode " + this.methodCompiler.Method.ToString() + ". (Flags = " + header.flags.ToString("X") + ", Rva = " + this.methodCompiler.Method.Rva + ")");
            }

            // Are there sections following the code?
            if (MethodFlags.MoreSections == (header.flags & MethodFlags.MoreSections))
            {
                // Yes, seek to them and process those sections
                long codepos = reader.BaseStream.Position;

                // Seek to the end of the code...
                long dataSectPos = codepos + header.codeSize;
                if (0 != (dataSectPos & 3))
                {
                    dataSectPos += (4 - (dataSectPos % 4));
                }
                reader.BaseStream.Position = dataSectPos;

                // Read all headers, so the IL decoder knows how to handle these...
                byte flags;

                do
                {
                    flags = reader.ReadByte();
                    bool isFat = (0x40 == (flags & 0x40));
                    int  length;
                    int  blocks;
                    if (isFat)
                    {
                        byte[] buffer = new byte[4];
                        reader.Read(buffer, 0, 3);
                        length = LittleEndianBitConverter.GetInt32(buffer, 0);
                        blocks = (length - 4) / 24;
                    }
                    else
                    {
                        length = reader.ReadByte();
                        blocks = (length - 4) / 12;

                        /* Read & skip the padding. */
                        reader.ReadInt16();
                    }

                    Debug.Assert(0x01 == (flags & 0x3F), @"Unsupported method data section.");
                    // Read the clause
                    for (int i = 0; i < blocks; i++)
                    {
                        EhClause clause = new EhClause();
                        clause.Read(reader, isFat);
                        //this.methodCompiler.Method.ExceptionClauseHeader.AddClause(clause);
                        // FIXME: Create proper basic Blocks for each item in the clause
                    }
                }while (0x80 == (flags & 0x80));

                //methodCompiler.Method.ExceptionClauseHeader.Sort();
                reader.BaseStream.Position = codepos;
            }
        }
예제 #5
0
        /// <summary>
        /// Reads the method header from the instruction stream.
        /// </summary>
        /// <param name="reader">The reader used to decode the instruction stream.</param>
        /// <param name="header">The method header structure to populate.</param>
        private void ReadMethodHeader(BinaryReader reader, ref MethodHeader header)
        {
            header.flags = (MethodFlags)reader.ReadByte();
            switch (header.flags & MethodFlags.HeaderMask)
            {
                case MethodFlags.TinyFormat:
                    header.codeSize = ((uint)(header.flags & MethodFlags.TinyCodeSizeMask) >> 2);
                    header.flags &= MethodFlags.HeaderMask;
                    break;

                case MethodFlags.FatFormat:
                    header.flags = (MethodFlags)(reader.ReadByte() << 8 | (byte)header.flags);
                    if (MethodFlags.ValidHeader != (header.flags & MethodFlags.HeaderSizeMask))
                        throw new InvalidDataException(@"Invalid method _header.");
                    header.maxStack = reader.ReadUInt16();
                    header.codeSize = reader.ReadUInt32();
                    header.localsSignature = (TokenTypes)reader.ReadUInt32();
                    break;

                default:
                    throw new InvalidDataException(@"Invalid method header.");
            }

            // Are there sections following the code?
            if (MethodFlags.MoreSections == (header.flags & MethodFlags.MoreSections))
            {
                // Yes, seek to them and process those sections
                long codepos = reader.BaseStream.Position;

                // Seek to the end of the code...
                long dataSectPos = codepos + header.codeSize;
                if (0 != (dataSectPos & 3))
                    dataSectPos += (4 - (dataSectPos % 4));
                reader.BaseStream.Position = dataSectPos;

                // Read all headers, so the IL decoder knows how to handle these...
                byte flags;

                do
                {
                    flags = reader.ReadByte();
                    bool isFat = (0x40 == (flags & 0x40));
                    int length;
                    int blocks;
                    if (isFat)
                    {
                        byte[] buffer = new byte[4];
                        reader.Read(buffer, 0, 3);
                        length = LittleEndianBitConverter.GetInt32(buffer, 0);
                        blocks = (length - 4) / 24;
                    }
                    else
                    {
                        length = reader.ReadByte();
                        blocks = (length - 4) / 12;

                        /* Read & skip the padding. */
                        reader.ReadInt16();
                    }

                    Debug.Assert(0x01 == (flags & 0x3F), @"Unsupported method data section.");
                    // Read the clause
                    for (int i = 0; i < blocks; i++)
                    {
                        EhClause clause = new EhClause();
                        clause.Read(reader, isFat);
                        this.methodCompiler.Method.ExceptionClauseHeader.AddClause(clause);
                        // FIXME: Create proper basic Blocks for each item in the clause
                    }
                }
                while (0x80 == (flags & 0x80));

                methodCompiler.Method.ExceptionClauseHeader.Sort();
                reader.BaseStream.Position = codepos;
            }
        }
예제 #6
0
        /// <summary>
        /// Decodes the instruction stream of the reader and populates the compiler.
        /// </summary>
        /// <param name="compiler">The compiler to populate.</param>
        /// <param name="header">The method _header.</param>
        private void Decode(IMethodCompiler compiler, ref MethodHeader header)
        {
            // Start of the code stream
            long codeStart = codeReader.BaseStream.Position;

            // End of the code stream
            long codeEnd = codeReader.BaseStream.Position + header.codeSize;

            // Prefix instruction
            //PrefixInstruction prefix = null;

            // Setup context
            Context ctx = new Context(InstructionSet, -1);

            while (codeEnd != codeReader.BaseStream.Position)
            {
                // Determine the instruction offset
                int instOffset = (int)(codeReader.BaseStream.Position - codeStart);

                // Read the next opcode from the stream
                OpCode op = (OpCode)codeReader.ReadByte();
                if (OpCode.Extop == op)
                    op = (OpCode)(0x100 | codeReader.ReadByte());

                ICILInstruction instruction = Instruction.Get(op);

                if (instruction == null)
                    throw new Exception("CIL " + op + " is not yet supported");

                //if (instruction is PrefixInstruction) {
                //    prefix = instruction as PrefixInstruction;
                //    continue;
                //}

                // Create and initialize the corresponding instruction
                ctx.AppendInstruction(instruction);
                ctx.Label = instOffset;
                instruction.Decode(ctx, this);
                //ctx.Prefix = prefix;

                Debug.Assert(ctx.Instruction != null);

                // Do we need to patch branch targets?
                if (instruction is IBranchInstruction && instruction.FlowControl != FlowControl.Return)
                {
                    int pc = (int)(codeReader.BaseStream.Position - codeStart);

                    for (int i = 0; i < ctx.Branch.Targets.Length; i++)
                        ctx.Branch.Targets[i] += pc;
                }

                //prefix = null;
            }
        }
예제 #7
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            // The size of the code in bytes
            MethodHeader header = new MethodHeader();

            using (Stream code = methodCompiler.GetInstructionStream())
            {
                // Initialize the instruction, setting the initialize size the same as the code stream
                methodCompiler.InstructionSet = new InstructionSet((int)code.Length);

                // update the base class
                InstructionSet = methodCompiler.InstructionSet;

                using (BinaryReader reader = new BinaryReader(code))
                {
                    codeReader = reader;

                    //Debug.WriteLine("Decoding " + methodCompiler.Method.ToString());
                    ReadMethodHeader(reader, ref header);

                    if (header.localsSignature != 0)
                    {
                        StandAloneSigRow row = methodCompiler.Method.MetadataModule.Metadata.ReadStandAloneSigRow(header.localsSignature);

                        LocalVariableSignature localsSignature = new LocalVariableSignature(methodCompiler.Method.MetadataModule.Metadata, row.SignatureBlobIdx);

                        if (methodCompiler.Method.DeclaringType is CilGenericType)
                        {
                            localsSignature.ApplyGenericType((methodCompiler.Method.DeclaringType as CilGenericType).GenericArguments);
                        }

                        methodCompiler.SetLocalVariableSignature(localsSignature);
                    }

                    /* Decode the instructions */
                    Decode(methodCompiler, ref header);

                    // When we leave, the operand stack must only contain the locals...
                    //Debug.Assert(_operandStack.Count == _method.Locals.Count);
                    codeReader = null;
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            using (Stream code = methodCompiler.GetInstructionStream())
            {
                // Initialize the instruction
                methodCompiler.InstructionSet = new InstructionSet(256);

                // update the base class
                InstructionSet = methodCompiler.InstructionSet;

                using (codeReader = new BinaryReader(code))
                {
                    // The size of the code in bytes
                    MethodHeader header = new MethodHeader();
                    ReadMethodHeader(codeReader, ref header);

                    if (header.localsSignature.RID != 0)
                    {
                        StandAloneSigRow row = methodCompiler.Method.Module.MetadataModule.Metadata.ReadStandAloneSigRow(header.localsSignature);

                        LocalVariableSignature localsSignature;

                        if (methodCompiler.Method.DeclaringType is CilGenericType)
                        {
                            localsSignature = new LocalVariableSignature(methodCompiler.Method.Module.MetadataModule.Metadata, row.SignatureBlobIdx, (methodCompiler.Method.DeclaringType as CilGenericType).GenericArguments);
                        }
                        else
                        {
                            localsSignature = new LocalVariableSignature(methodCompiler.Method.Module.MetadataModule.Metadata, row.SignatureBlobIdx);
                        }

                        methodCompiler.SetLocalVariableSignature(localsSignature);
                    }

                    /* Decode the instructions */
                    Decode(methodCompiler, ref header);

                    // When we leave, the operand stack must only contain the locals...
                    //Debug.Assert(_operandStack.Count == _method.Locals.Count);
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            // The size of the code in bytes
            MethodHeader header = new MethodHeader();

            using (Stream code = MethodCompiler.GetInstructionStream())
            {

                // Initalize the instruction, setting the initalize size to 10 times the code stream
                MethodCompiler.InstructionSet = new InstructionSet((int)code.Length * 10);

                // update the base class
                InstructionSet = MethodCompiler.InstructionSet;

                using (BinaryReader reader = new BinaryReader(code))
                {
                    _compiler = MethodCompiler;
                    _method = MethodCompiler.Method;
                    _codeReader = reader;

                    ReadMethodHeader(reader, ref header);
                    //Debug.WriteLine("Decoding " + compiler.Method.ToString());

                    if (0 != header.localsSignature)
                    {
                        StandAloneSigRow row;
                        IMetadataProvider md = _method.Module.Metadata;
                        md.Read(header.localsSignature, out row);
                        MethodCompiler.SetLocalVariableSignature(LocalVariableSignature.Parse(md, row.SignatureBlobIdx));
                    }

                    /* Decode the instructions */
                    Decode(MethodCompiler, ref header);

                    // When we leave, the operand stack must only contain the locals...
                    //Debug.Assert(_operandStack.Count == _method.Locals.Count);
                    _codeReader = null;
                    _compiler = null;
                }
            }
        }