//------------------------------------------------------------------------------------- internal static void Customize(byte[] body, DynamicILInfo ilInfo, Dictionary<int, DiscoverMemberInfo> schema) { BindingFlags bf = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Static; ArrayReader ar = new ArrayReader(body); while(ar.CanRead) { int offset = ar.Position; OpCode opCode = OpCodes.Nop; //int token = 0; Byte code = ar.ReadByte(); if(code != 0xFE) opCode = OneByteOpCodes[code]; else opCode = TwoByteOpCodes[ar.ReadByte()]; switch(opCode.OperandType) { #region ... case OperandType.InlineNone: break; //The operand is an 8-bit integer branch target. case OperandType.ShortInlineBrTarget: ar.ReadSByte(); break; //The operand is a 32-bit integer branch target. case OperandType.InlineBrTarget: ar.ReadInt32(); break; //The operand is an 8-bit integer: 001F ldc.i4.s, FE12 unaligned. case OperandType.ShortInlineI: ar.ReadByte(); break; //The operand is a 32-bit integer. case OperandType.InlineI: ar.ReadInt32(); break; //The operand is a 64-bit integer. case OperandType.InlineI8: ar.ReadInt64(); break; //The operand is a 32-bit IEEE floating point number. case OperandType.ShortInlineR: ar.ReadSingle(); break; //The operand is a 64-bit IEEE floating point number. case OperandType.InlineR: ar.ReadDouble(); break; //The operand is an 8-bit integer containing the ordinal of a local variable or an argument case OperandType.ShortInlineVar: ar.ReadByte(); break; //The operand is 16-bit integer containing the ordinal of a local variable or an argument. case OperandType.InlineVar: ar.ReadUInt16(); break; #endregion ... //The operand is a 32-bit metadata string token. case OperandType.InlineString: { #region ... int token = ar.ReadInt32(); string s = new String(schema[token].Name.ToCharArray()); ar.OverwriteInt32(ilInfo.GetTokenFor(s), offset + opCode.Size); #endregion ... } break; //The operand is a 32-bit metadata signature token. case OperandType.InlineSig: { #region ... throw new Exception("НАДО ПРОВЕРИТЬ InlineSig !!!"); //int token = ar.ReadInt32(); //OverwriteInt32(ilInfo.GetTokenFor(inlineSigInstruction.Signature), //inlineSigInstruction.Offset + inlineSigInstruction.OpCode.Size); #endregion ... } //break; //The operand is a 32-bit metadata token. case OperandType.InlineMethod: { #region ... int token = ar.ReadInt32(); MethodBase mi; Type t = schema[token].DeclaringType; // ?? dstType; if(schema[token].Name.StartsWith(".ctor")) mi = t.GetConstructor(bf, null, schema[token].ParametersTypes, null); else mi = t.GetMethod(schema[token].Name, bf, null, schema[token].ParametersTypes, null); if(mi == null) throw new PulsarException("Не удалось определить MethodBase для операнда {0}:{1}", opCode, opCode.OperandType); ar.OverwriteInt32(ilInfo.GetTokenFor(mi.MethodHandle, t.TypeHandle), offset + opCode.Size); #endregion ... } break; //The operand is a 32-bit metadata token. case OperandType.InlineField: { #region ... int token = ar.ReadInt32(); FieldInfo fi = schema[token].DeclaringType.GetField(schema[token].Name, bf | BindingFlags.FlattenHierarchy); if(fi == null) throw new PulsarException("Не удалось определить FieldInfo для операнда {0}:{1}", opCode, opCode.OperandType); ar.OverwriteInt32(ilInfo.GetTokenFor(fi.FieldHandle), offset + opCode.Size); #endregion ... } break; //The operand is a 32-bit metadata token. case OperandType.InlineType: { #region ... int token = ar.ReadInt32(); Type t = schema[token].DeclaringType; ar.OverwriteInt32(ilInfo.GetTokenFor(t.TypeHandle), offset + opCode.Size); #endregion ... } break; //The operand is a FieldRef, MethodRef, or TypeRef token. case OperandType.InlineTok: { #region ... throw new Exception("НАДО ПРОВЕРИТЬ InlineTok !!!"); //int token = ar.ReadInt32(); // MemberInfo mi = inlineTokInstruction.Member; //int token = 0; //if(mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) //{ // Type type = mi as Type; // token = ilInfo.GetTokenFor(type.TypeHandle); //} //else if(mi.MemberType == MemberTypes.Method || mi.MemberType == MemberTypes.Constructor) //{ // MethodBase m = mi as MethodBase; // token = ilInfo.GetTokenFor(m.MethodHandle, m.DeclaringType.TypeHandle); //} //else if(mi.MemberType == MemberTypes.Field) //{ // FieldInfo f = mi as FieldInfo; // //CLR BUG: token = ilInfo.GetTokenFor(f.FieldHandle, f.DeclaringType.TypeHandle); // token = ilInfo.GetTokenFor(f.FieldHandle); //} //OverwriteInt32(token, // inlineTokInstruction.Offset + inlineTokInstruction.OpCode.Size); #endregion ... } //break; //The operand is the 32-bit integer argument to a switch instruction. case OperandType.InlineSwitch: { #region ... throw new Exception("НАДО ПРОВЕРИТЬ InlineSwitch !!!"); //Int32 cases = ar.ReadInt32(); //Int32[] deltas = new Int32[cases]; //for(Int32 i = 0; i < cases; i++) // deltas[i] = ar.ReadInt32(); #endregion ... } //break; default: throw new BadImageFormatException("Unexpected OperandType " + opCode.OperandType); } } }
//------------------------------------------------------------------------------------- internal static Dictionary<int, DiscoverMemberInfo> Discover(byte[] body, MethodInfo mi, Type dstType) { Dictionary<int, DiscoverMemberInfo> res = new Dictionary<int, DiscoverMemberInfo>(); ArrayReader ar = new ArrayReader(body); while(ar.CanRead) { int offset = ar.Position; OpCode opCode = OpCodes.Nop; //int token = 0; Byte code = ar.ReadByte(); if(code != 0xFE) opCode = OneByteOpCodes[code]; else opCode = TwoByteOpCodes[ar.ReadByte()]; switch(opCode.OperandType) { #region ... case OperandType.InlineNone: break; //The operand is an 8-bit integer branch target. case OperandType.ShortInlineBrTarget: ar.ReadSByte(); break; //The operand is a 32-bit integer branch target. case OperandType.InlineBrTarget: ar.ReadInt32(); break; //The operand is an 8-bit integer: 001F ldc.i4.s, FE12 unaligned. case OperandType.ShortInlineI: ar.ReadByte(); break; //The operand is a 32-bit integer. case OperandType.InlineI: ar.ReadInt32(); break; //The operand is a 64-bit integer. case OperandType.InlineI8: ar.ReadInt64(); break; //The operand is a 32-bit IEEE floating point number. case OperandType.ShortInlineR: ar.ReadSingle(); break; //The operand is a 64-bit IEEE floating point number. case OperandType.InlineR: ar.ReadDouble(); break; //The operand is an 8-bit integer containing the ordinal of a local variable or an argument case OperandType.ShortInlineVar: ar.ReadByte(); break; //The operand is 16-bit integer containing the ordinal of a local variable or an argument. case OperandType.InlineVar: ar.ReadUInt16(); break; #endregion ... //The operand is a 32-bit metadata string token. case OperandType.InlineString: { #region ... int token = ar.ReadInt32(); if(res.ContainsKey(token)) break; string s = mi.Module.ResolveString(token); res.Add(token, new DiscoverMemberInfo(s)); #endregion ... } break; //The operand is a 32-bit metadata signature token. case OperandType.InlineSig: { #region ... throw new Exception("НАДО ПРОВЕРИТЬ InlineSig !!!"); //int token = ar.ReadInt32(); //if(res.ContainsKey(token)) // break; #endregion ... } //break; //The operand is a 32-bit metadata token. case OperandType.InlineMethod: { #region ... int token = ar.ReadInt32(); if(res.ContainsKey(token)) break; MethodBase mb = mi.Module.ResolveMethod(token); if(mb == null) throw new PulsarException("Не удалось определить MethodBase для операнда {0}:{1}", opCode, opCode.OperandType); DiscoverMemberInfo dmi = new DiscoverMemberInfo(); dmi.Name = mb.Name; dmi.GenericArguments = (mb.IsConstructor) ? null : mb.GetGenericArguments(); //dmi.DeclaringTypeGenericArguments = (mb.DeclaringType ?? typeof(Type)).GetGenericArguments(); dmi.ParametersTypes = dmi.GetParametesTypes(mb.GetParameters()); if(mi.DeclaringType.Equals(mb.DeclaringType)) dmi.DeclaringType = dstType; else dmi.DeclaringType = mb.DeclaringType; res.Add(token, dmi); #endregion ... } break; //The operand is a 32-bit metadata token. case OperandType.InlineField: { #region ... int token = ar.ReadInt32(); if(res.ContainsKey(token)) break; FieldInfo fi = mi.Module.ResolveField(token); if(fi == null) throw new PulsarException("Не удалось определить FieldInfo для операнда {0}:{1}", opCode, opCode.OperandType); DiscoverMemberInfo dmi = new DiscoverMemberInfo(); dmi.Name = fi.Name; if(mi.DeclaringType.Equals(fi.DeclaringType)) dmi.DeclaringType = dstType; else dmi.DeclaringType = fi.DeclaringType; res.Add(token, dmi); #endregion ... } break; //The operand is a 32-bit metadata token. case OperandType.InlineType: { #region ... int token = ar.ReadInt32(); if(res.ContainsKey(token)) break; Type t = mi.Module.ResolveType(token, null, null); if(t == null) throw new PulsarException("Не удалось определить Type для операнда {0}:{1}", opCode, opCode.OperandType); DiscoverMemberInfo dmi = new DiscoverMemberInfo(); dmi.Name = t.FullName; dmi.DeclaringType = t; dmi.GenericArguments = t.GetGenericArguments(); res.Add(token, dmi); #endregion ... } break; //The operand is a FieldRef, MethodRef, or TypeRef token. case OperandType.InlineTok: { #region ... throw new Exception("НАДО ПРОВЕРИТЬ InlineTok !!!"); //int token = ar.ReadInt32(); //if(res.ContainsKey(token)) // break; // MemberInfo mi = inlineTokInstruction.Member; //int token = 0; //if(mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) //{ // Type type = mi as Type; // token = ilInfo.GetTokenFor(type.TypeHandle); //} //else if(mi.MemberType == MemberTypes.Method || mi.MemberType == MemberTypes.Constructor) //{ // MethodBase m = mi as MethodBase; // token = ilInfo.GetTokenFor(m.MethodHandle, m.DeclaringType.TypeHandle); //} //else if(mi.MemberType == MemberTypes.Field) //{ // FieldInfo f = mi as FieldInfo; // //CLR BUG: token = ilInfo.GetTokenFor(f.FieldHandle, f.DeclaringType.TypeHandle); // token = ilInfo.GetTokenFor(f.FieldHandle); //} //OverwriteInt32(token, // inlineTokInstruction.Offset + inlineTokInstruction.OpCode.Size); #endregion ... } // break; //The operand is the 32-bit integer argument to a switch instruction. case OperandType.InlineSwitch: { #region ... throw new Exception("НАДО ПРОВЕРИТЬ InlineSwitch !!!"); //Int32 cases = ar.ReadInt32(); //Int32[] deltas = new Int32[cases]; //for(Int32 i = 0; i < cases; i++) // deltas[i] = ar.ReadInt32(); #endregion ... } //break; default: throw new BadImageFormatException("Unexpected OperandType " + opCode.OperandType); } } return res; }