Пример #1
0
        internal MethodBody(ModuleReader module, int rva, IGenericContext context)
        {
            const byte CorILMethod_TinyFormat     = 0x02;
            const byte CorILMethod_FatFormat      = 0x03;
            const byte CorILMethod_MoreSects      = 0x08;
            const byte CorILMethod_InitLocals     = 0x10;
            const byte CorILMethod_Sect_EHTable   = 0x01;
            const byte CorILMethod_Sect_FatFormat = 0x40;
            const byte CorILMethod_Sect_MoreSects = 0x80;

            List <ExceptionHandlingClause> exceptionClauses = new List <ExceptionHandlingClause>();
            List <LocalVariableInfo>       locals           = new List <LocalVariableInfo>();
            Stream stream = module.GetStream();

            module.SeekRVA(rva);
            BinaryReader br = new BinaryReader(stream);
            byte         b  = br.ReadByte();

            if ((b & 3) == CorILMethod_TinyFormat)
            {
                initLocals = true;
                body       = br.ReadBytes(b >> 2);
                maxStack   = 8;
            }
            else if ((b & 3) == CorILMethod_FatFormat)
            {
                initLocals = (b & CorILMethod_InitLocals) != 0;
                short flagsAndSize = (short)(b | (br.ReadByte() << 8));
                if ((flagsAndSize >> 12) != 3)
                {
                    throw new BadImageFormatException("Fat format method header size should be 3");
                }
                maxStack = br.ReadUInt16();
                int codeLength = br.ReadInt32();
                localVarSigTok = br.ReadInt32();
                body           = br.ReadBytes(codeLength);
                if ((b & CorILMethod_MoreSects) != 0)
                {
                    stream.Position = (stream.Position + 3) & ~3;
                    int hdr = br.ReadInt32();
                    if ((hdr & CorILMethod_Sect_MoreSects) != 0 || (hdr & CorILMethod_Sect_EHTable) == 0)
                    {
                        throw new NotImplementedException();
                    }
                    else if ((hdr & CorILMethod_Sect_FatFormat) != 0)
                    {
                        int count = ComputeExceptionCount((hdr >> 8) & 0xFFFFFF, 24);
                        for (int i = 0; i < count; i++)
                        {
                            int flags                    = br.ReadInt32();
                            int tryOffset                = br.ReadInt32();
                            int tryLength                = br.ReadInt32();
                            int handlerOffset            = br.ReadInt32();
                            int handlerLength            = br.ReadInt32();
                            int classTokenOrFilterOffset = br.ReadInt32();
                            exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
                        }
                    }
                    else
                    {
                        int count = ComputeExceptionCount((hdr >> 8) & 0xFF, 12);
                        for (int i = 0; i < count; i++)
                        {
                            int flags                    = br.ReadUInt16();
                            int tryOffset                = br.ReadUInt16();
                            int tryLength                = br.ReadByte();
                            int handlerOffset            = br.ReadUInt16();
                            int handlerLength            = br.ReadByte();
                            int classTokenOrFilterOffset = br.ReadInt32();
                            exceptionClauses.Add(new ExceptionHandlingClause(module, flags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset, context));
                        }
                    }
                }
                if (localVarSigTok != 0)
                {
                    ByteReader sig = module.GetStandAloneSig((localVarSigTok & 0xFFFFFF) - 1);
                    Signature.ReadLocalVarSig(module, sig, context, locals);
                }
            }
            else
            {
                throw new BadImageFormatException();
            }
            this.exceptionClauses = exceptionClauses.AsReadOnly();
            this.locals           = locals.AsReadOnly();
        }