Пример #1
0
        public void Append(Instruction instr)
        {
            Instruction last = null, current = instr;

            if (m_instrs.Count > 0)
            {
                last = m_instrs [m_instrs.Count - 1];
            }

            if (last != null)
            {
                last.Next        = instr;
                current.Previous = last;
            }

            m_instrs.Add(current);
        }
Пример #2
0
        void ReadCilBody(MethodBody body, BinaryReader br)
        {
            long        start = br.BaseStream.Position;
            Instruction last  = null;

            m_instructions.Clear();
            InstructionCollection code    = body.Instructions;
            GenericContext        context = new GenericContext(body.Method);

            while (br.BaseStream.Position < start + body.CodeSize)
            {
                OpCode op;
                long   offset = br.BaseStream.Position - start;
                int    cursor = br.ReadByte();
                if (cursor == 0xfe)
                {
                    op = OpCodes.TwoBytesOpCode [br.ReadByte()];
                }
                else
                {
                    op = OpCodes.OneByteOpCode [cursor];
                }

                Instruction instr = new Instruction((int)offset, op);
                switch (op.OperandType)
                {
                case OperandType.InlineNone:
                    break;

                case OperandType.InlineSwitch:
                    uint   length   = br.ReadUInt32();
                    int [] branches = new int [length];
                    int [] buf      = new int [length];
                    for (int i = 0; i < length; i++)
                    {
                        buf [i] = br.ReadInt32();
                    }
                    for (int i = 0; i < length; i++)
                    {
                        branches [i] = Convert.ToInt32(br.BaseStream.Position - start + buf [i]);
                    }
                    instr.Operand = branches;
                    break;

                case OperandType.ShortInlineBrTarget:
                    sbyte sbrtgt = br.ReadSByte();
                    instr.Operand = Convert.ToInt32(br.BaseStream.Position - start + sbrtgt);
                    break;

                case OperandType.InlineBrTarget:
                    int brtgt = br.ReadInt32();
                    instr.Operand = Convert.ToInt32(br.BaseStream.Position - start + brtgt);
                    break;

                case OperandType.ShortInlineI:
                    if (op == OpCodes.Ldc_I4_S)
                    {
                        instr.Operand = br.ReadSByte();
                    }
                    else
                    {
                        instr.Operand = br.ReadByte();
                    }
                    break;

                case OperandType.ShortInlineVar:
                    instr.Operand = GetVariable(body, br.ReadByte());
                    break;

                case OperandType.ShortInlineParam:
                    instr.Operand = GetParameter(body, br.ReadByte());
                    break;

                case OperandType.InlineSig:
                    instr.Operand = GetCallSiteAt(br.ReadInt32(), context);
                    break;

                case OperandType.InlineI:
                    instr.Operand = br.ReadInt32();
                    break;

                case OperandType.InlineVar:
                    instr.Operand = GetVariable(body, br.ReadInt16());
                    break;

                case OperandType.InlineParam:
                    instr.Operand = GetParameter(body, br.ReadInt16());
                    break;

                case OperandType.InlineI8:
                    instr.Operand = br.ReadInt64();
                    break;

                case OperandType.ShortInlineR:
                    instr.Operand = br.ReadSingle();
                    break;

                case OperandType.InlineR:
                    instr.Operand = br.ReadDouble();
                    break;

                case OperandType.InlineString:
                    instr.Operand = m_root.Streams.UserStringsHeap [GetRid(br.ReadInt32())];
                    break;

                case OperandType.InlineField:
                case OperandType.InlineMethod:
                case OperandType.InlineType:
                case OperandType.InlineTok:
                    MetadataToken token = new MetadataToken(br.ReadInt32());
                    switch (token.TokenType)
                    {
                    case TokenType.TypeDef:
                        instr.Operand = m_reflectReader.GetTypeDefAt(token.RID);
                        break;

                    case TokenType.TypeRef:
                        instr.Operand = m_reflectReader.GetTypeRefAt(token.RID);
                        break;

                    case TokenType.TypeSpec:
                        instr.Operand = m_reflectReader.GetTypeSpecAt(token.RID, context);
                        break;

                    case TokenType.Field:
                        instr.Operand = m_reflectReader.GetFieldDefAt(token.RID);
                        break;

                    case TokenType.Method:
                        instr.Operand = m_reflectReader.GetMethodDefAt(token.RID);
                        break;

                    case TokenType.MethodSpec:
                        instr.Operand = m_reflectReader.GetMethodSpecAt(token.RID, context);
                        break;

                    case TokenType.MemberRef:
                        instr.Operand = m_reflectReader.GetMemberRefAt(token.RID, context);
                        break;

                    default:
                        throw new ReflectionException("Wrong token: " + token);
                    }
                    break;
                }

                m_instructions.Add(instr.Offset, instr);

                if (last != null)
                {
                    last.Next      = instr;
                    instr.Previous = last;
                }

                last = instr;

                code.Add(instr);
            }

            // resolve branches
            foreach (Instruction i in code)
            {
                switch (i.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    i.Operand = GetInstruction(body, (int)i.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int []         lbls   = (int [])i.Operand;
                    Instruction [] instrs = new Instruction [lbls.Length];
                    for (int j = 0; j < lbls.Length; j++)
                    {
                        instrs [j] = GetInstruction(body, lbls [j]);
                    }
                    i.Operand = instrs;
                    break;
                }
            }

            if (m_reflectReader.SymbolReader != null)
            {
                m_reflectReader.SymbolReader.Read(body, m_instructions);
            }
        }