internal static MonoEventInfo Create(IMonoStructType klass, int index, Cecil.EventDefinition einfo) { TargetType type = klass.File.MonoLanguage.LookupMonoType (einfo.EventType); bool is_static = false; MonoFunctionType add, remove, raise; TargetMemberAccessibility accessibility = TargetMemberAccessibility.Private; if (einfo.AddMethod != null) { add = klass.LookupFunction (einfo.AddMethod); is_static = einfo.AddMethod.IsStatic; accessibility = MonoMethodInfo.GetAccessibility (einfo.AddMethod); } else add = null; if (einfo.RemoveMethod != null) { remove = klass.LookupFunction (einfo.RemoveMethod); is_static = einfo.RemoveMethod.IsStatic; accessibility = MonoMethodInfo.GetAccessibility (einfo.RemoveMethod); } else remove = null; if (einfo.InvokeMethod != null) { raise = klass.LookupFunction (einfo.InvokeMethod); is_static = einfo.InvokeMethod.IsStatic; accessibility = MonoMethodInfo.GetAccessibility (einfo.InvokeMethod); } else raise = null; return new MonoEventInfo ( klass, index, einfo, type, is_static, accessibility, add, remove, raise); }
public MonoClassType(MonoSymbolFile file, Cecil.TypeDefinition type) : base(file.MonoLanguage, TargetObjectKind.Class) { this.type = type; this.file = file; struct_type = new MonoStructType (file, this, type); if (type.GenericParameters.Count > 0) { StringBuilder sb = new StringBuilder (type.FullName); sb.Append ('<'); for (int i = 0; i < type.GenericParameters.Count; i++) { if (i > 0) sb.Append (','); sb.Append (type.GenericParameters [i].Name); } sb.Append ('>'); full_name = sb.ToString (); } else full_name = type.FullName; DebuggerBrowsableState? browsable_state; MonoSymbolFile.CheckCustomAttributes (type, out browsable_state, out debugger_display, out type_proxy, out is_compiler_generated); }
private MonoStringType(MonoSymbolFile file, Cecil.TypeDefinition typedef, int object_size, int size) : base(file, typedef, "string", FundamentalKind.String, size) { this.ObjectSize = object_size; this.CreateString = file.MonoLanguage.MonoDebuggerInfo.CreateString; }
public MonoEnumType(MonoSymbolFile file, Cecil.TypeDefinition type) : base(file.MonoLanguage) { this.type = type; this.file = file; class_type = new MonoClassType (file, type); }
public MonoEnumInfo(MonoEnumType type, TargetType field_type, int index, int pos, Cecil.FieldDefinition finfo) : base(field_type, finfo.Name, index, finfo.IsStatic, MonoFieldInfo.GetAccessibility (finfo), pos, 0, finfo.HasConstant) { FieldInfo = finfo; }
public Type FindType(Cecil.TypeReference typeRef) { var type = resolver.FindType(typeRef); if (type == null) { throw new Exception(String.Format("Cannot resolve type {0}", typeRef)); } return type; }
public static void InstrumentAssembly(Cecil.AssemblyDefinition assembly) { var typeCount = assembly.Modules.Sum(mod => mod.Types.Count); foreach (var module in assembly.Modules) { foreach (var type in module.Types) { InstrumentType(type); } } }
/// <summary> /// Find runtime type in current AppDomain based on Cecil.TypeReference. /// Do the actual lookup for type /// </summary> private Type LookupType(Cecil.TypeReference typeDef) { if (typeDef.IsGenericInstance) { var genericTypeDef = (Cecil.GenericInstanceType)typeDef; var ourArgs = genericTypeDef.GenericArguments.Select((arg) => { return FindType(arg); }).ToArray(); var ourBaseType = FindType(genericTypeDef.ElementType); return ourBaseType.MakeGenericType(ourArgs); } string assemblyName; try { assemblyName = typeDef.AssemblyQualifiedName; assemblyName = assemblyName.Substring(assemblyName.IndexOf(", ") + 2); //map our donor assembly to original loaded assembly assemblyName = assemblyName.Replace("Assembly-HotPatch-CSharp", "Assembly-CSharp"); } catch (Mono.Cecil.AssemblyResolutionException e) { //wtf. cecil bug? //sometimes happens with assemblies like System assemblyName = e.AssemblyReference.FullName; } var ourAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault( (assembly) => assemblyName.StartsWith(assembly.FullName)); if (ourAssembly == null) { return null; } if (typeDef.DeclaringType != null) { var parentType = FindType(typeDef.DeclaringType); return parentType.GetNestedType(typeDef.Name, Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Public); } var typedefName = typeDef.FullName; if (typeDef.IsArray) { typedefName = typedefName.Replace("[]", ""); } var ourType = ourAssembly.GetTypes().FirstOrDefault((typ) => typ.FullName == typedefName); if (ourType == null) { return null; } if (typeDef.IsArray) { return ourType.MakeArrayType(); } return ourType; }
private MonoEventInfo(IMonoStructType klass, int index, Cecil.EventDefinition einfo, TargetType type, bool is_static, TargetMemberAccessibility accessibility, MonoFunctionType add, MonoFunctionType remove, MonoFunctionType raise) : base(type, einfo.Name, index, is_static, accessibility, add, remove, raise) { this.Klass = klass; this.AddType = add; this.RemoveType = remove; this.RaiseType = raise; }
/// <summary> /// Find runtime type in current AppDomain based on Cecil.TypeReference. /// </summary> /// <param name="typeDef">Cecil type reference.</param> /// <returns>Runtime Type.</returns> public Type FindType(Cecil.TypeReference typeDef) { Type cachedType; if (typeCache.TryGetValue(typeDef.FullName, out cachedType)) { return cachedType; } var foundType = LookupType(typeDef); typeCache[typeDef.FullName] = foundType; return foundType; }
public override void Run() { var redirectMethods = new[] { "Write", "WriteLine" }; SourceDefinition.MainModule.ForEachInstruction((method, instruction) => { var mth = instruction.Operand as MethodReference; if (mth != null && mth.DeclaringType.FullName == "System.Console") { if (redirectMethods.Contains(mth.Name)) { var mthReference = this.Resolve(mth); if (mthReference != null) instruction.Operand = SourceDefinition.MainModule.Import(mthReference); } } }); }
internal MonoFunctionType(IMonoStructType klass, Cecil.MethodDefinition mdef) : base(klass.File.MonoLanguage) { this.klass = klass; this.method_info = mdef; this.token = MonoDebuggerSupport.GetMethodToken (mdef); this.name = GetMethodName (mdef) + MonoSymbolFile.GetMethodSignature (mdef); Cecil.TypeReference rtype; if (mdef.IsConstructor) { rtype = mdef.DeclaringType; has_return_type = true; } else { rtype = mdef.ReturnType.ReturnType; has_return_type = rtype.FullName != "System.Void"; } return_type = klass.File.MonoLanguage.LookupMonoType (rtype); parameter_types = new TargetType [mdef.Parameters.Count]; for (int i = 0; i < mdef.Parameters.Count; i++) parameter_types [i] = klass.File.MonoLanguage.LookupMonoType ( mdef.Parameters[i].ParameterType); }
Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference actualType, Cecil.TypeReference reqType) { if (reqType == null || actualType == reqType) { return expr; } else { bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType); bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType); if (TypeAnalysis.IsBoolean(reqType)) { if (TypeAnalysis.IsBoolean(actualType)) return expr; if (actualIsIntegerOrEnum) { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, MakePrimitive(0, actualType)); } else { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); } } if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) { return new ConditionalExpression { Condition = expr, TrueExpression = MakePrimitive(1, reqType), FalseExpression = MakePrimitive(0, reqType) }; } if (actualIsIntegerOrEnum && requiredIsIntegerOrEnum) { return expr.CastTo(AstBuilder.ConvertType(reqType)); } return expr; } }
static IEnumerable<Cecil.MethodDefinition> GetMethods(Cecil.TypeDefinition type, bool constructor) { foreach (var method in type.Methods) { if (constructor && method.IsConstructor) yield return method; if (!constructor && !method.IsConstructor) yield return method; } }
void EmitInstruction(ILGenerator il, OpCode opcode, Cecil.Cil.VariableDefinition operand) { il.Emit(opcode, operand.Index); }
public MonoFunctionType LookupFunction(Cecil.MethodDefinition mdef) { int token = MonoDebuggerSupport.GetMethodToken (mdef); if (function_hash == null) function_hash = new Dictionary<int,MonoFunctionType> (); if (!function_hash.ContainsKey (token)) { MonoFunctionType function = new MonoFunctionType (this, mdef); function_hash.Add (token, function); return function; } return function_hash [token]; }
internal static TargetMemberAccessibility GetAccessibility(Cecil.MethodDefinition method) { switch (method.Attributes & Cecil.MethodAttributes.MemberAccessMask) { case Cecil.MethodAttributes.Public: return TargetMemberAccessibility.Public; case Cecil.MethodAttributes.Family: case Cecil.MethodAttributes.FamANDAssem: return TargetMemberAccessibility.Protected; case Cecil.MethodAttributes.Assembly: case Cecil.MethodAttributes.FamORAssem: return TargetMemberAccessibility.Internal; default: return TargetMemberAccessibility.Private; } }
public MonoFunctionType LookupFunction(Cecil.MethodDefinition mdef) { get_methods (); return function_hash [mdef]; }
internal static string GetMethodName(Cecil.MethodDefinition mdef) { Cecil.GenericParameterCollection gen_params = mdef.GenericParameters; if ((gen_params == null) || (gen_params.Count == 0)) return mdef.Name; else return mdef.Name + "`" + gen_params.Count; }
public MonoFieldInfo(IMonoStructType type, TargetType field_type, int pos, Cecil.FieldDefinition finfo) : base(field_type, finfo.Name, pos, finfo.IsStatic, GetAccessibility (finfo), pos, 0, finfo.HasConstant) { FieldInfo = finfo; DebuggerTypeProxyAttribute type_proxy; MonoSymbolFile.CheckCustomAttributes (finfo, out browsable_state, out debugger_display, out type_proxy, out is_compiler_generated); }
public DynamicMethod RecompileMethod(Cecil.MethodDefinition methodDef) { Debug.Trace("Recompiling method: {0}", methodDef.FullName); var declaringType = FindType(methodDef.DeclaringType); var returnType = FindType(methodDef.ReturnType); Type[] paramTypes = methodDef.Parameters.Select((paramDef) => { return FindType(paramDef.ParameterType); }).ToArray(); if (!methodDef.IsStatic) { paramTypes = new Type[] { declaringType }.Concat(paramTypes).ToArray(); } var dynMethod = new DynamicMethod(methodDef.Name, returnType, paramTypes, true); ILGenerator il = dynMethod.GetILGenerator(); dynMethod.InitLocals = methodDef.Body.InitLocals; foreach (var variable in methodDef.Body.Variables) { var localType = FindType(variable.VariableType); Debug.Trace("Declaring local (cecil type: {0}) of type (runtime type: {1})", variable.VariableType, localType); il.DeclareLocal(localType); } var labels = new Dictionary<Cecil.Cil.Instruction, Label>(); foreach (var inst in methodDef.Body.Instructions) { if (inst.Operand != null && inst.Operand.GetType() == typeof(Cecil.Cil.Instruction)) { var opinst = (Cecil.Cil.Instruction)(inst.Operand); labels[opinst] = il.DefineLabel(); } } foreach (var inst in Instrument.IterateInstructions(methodDef)) { Debug.Trace("Emitting: {0}", inst); Label label; if (labels.TryGetValue(inst, out label)) { il.MarkLabel(label); } var ilop = FindOpcode(inst.OpCode); if (inst.Operand != null) { var operand = inst.Operand; var operandType = operand.GetType(); // Dynamic dispatch implementation: // We have to run different processing code depending on the type of instruction // operand. Visitor pattern cannot be implemented here, because we don't actually // own the classes that are the operands (and some of them are primitive or system // types). // Therefore, dynamic dispatcher is used. Method for each operand type is implemented // in this class, and reflection is used to find correct method to call. // In newer .net versions we would be able to do EmitInstruction(il, ilop, (dynamic)operand), // but the .net version we are targeting (because of Unity compatibility) does not // have `dynamic`. if (operandType == typeof(Cecil.Cil.Instruction)) { //branch location var operandInst = (Cecil.Cil.Instruction)operand; il.Emit(ilop, labels[operandInst]); } else if (primitiveOperandTypes.Contains(operandType)) { //if operand is primitive, call il.Emit directly Reflection.MethodInfo method; if (!EmitPrimitiveCache.TryGetValue(operandType, out method)) { method = typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode), operandType }); EmitPrimitiveCache[operandType] = method; } if (method == null) { throw new Exception(String.Format("Emit method for primitive type {0} not found.", operandType.Name)); } method.Invoke(il, new object[] { ilop, operand }); } else { //or else, call our EmitInstruction Reflection.MethodInfo method; if (!EmitInstructionCache.TryGetValue(operandType, out method)) { method = GetType().GetMethod("EmitInstruction", bindingAttr: bflags_all_instance, binder: null, modifiers: null, types: new Type[] { typeof(ILGenerator), typeof(OpCode), operandType }); EmitInstructionCache[operandType] = method; } if (method == null) { throw new Exception(String.Format("Don't know what to do with operand {0}", operandType.Name)); } method.Invoke(this, new object[] { il, ilop, operand }); } } else { il.Emit(ilop); } } return dynMethod; }
internal static MonoPropertyInfo Create(IMonoStructType klass, int index, Cecil.PropertyDefinition pinfo) { TargetType type = klass.File.MonoLanguage.LookupMonoType (pinfo.PropertyType); bool is_static = false; MonoFunctionType getter, setter; TargetMemberAccessibility accessibility = TargetMemberAccessibility.Private; if (pinfo.SetMethod != null) { setter = klass.LookupFunction (pinfo.SetMethod); is_static = pinfo.SetMethod.IsStatic; accessibility = MonoMethodInfo.GetAccessibility (pinfo.SetMethod); } else setter = null; if (pinfo.GetMethod != null) { getter = klass.LookupFunction (pinfo.GetMethod); is_static = pinfo.GetMethod.IsStatic; accessibility = MonoMethodInfo.GetAccessibility (pinfo.GetMethod); } else getter = null; return new MonoPropertyInfo ( type, klass, index, is_static, pinfo, accessibility, getter, setter); }
private MonoPropertyInfo(TargetType type, IMonoStructType klass, int index, bool is_static, Cecil.PropertyDefinition pinfo, TargetMemberAccessibility accessibility, MonoFunctionType getter, MonoFunctionType setter) : base(type, pinfo.Name, index, is_static, accessibility, getter, setter) { this.Klass = klass; this.GetterType = getter; this.SetterType = setter; bool is_compiler_generated; DebuggerTypeProxyAttribute type_proxy; MonoSymbolFile.CheckCustomAttributes (pinfo, out browsable_state, out debugger_display, out type_proxy, out is_compiler_generated); }
private MonoMethodInfo(IMonoStructType klass, int index, Cecil.MethodDefinition minfo, MonoFunctionType type) : base(type, MonoFunctionType.GetMethodName (minfo), index, minfo.IsStatic, GetAccessibility (minfo), type.FullName) { FunctionType = type; }
Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference actualType, Cecil.TypeReference reqType) { if (actualType == null || reqType == null || TypeAnalysis.IsSameType(actualType, reqType)) { return expr; } else if (actualType is ByReferenceType && reqType is PointerType && expr is DirectionExpression) { return Convert( new UnaryOperatorExpression(UnaryOperatorType.AddressOf, ((DirectionExpression)expr).Expression.Detach()), new PointerType(((ByReferenceType)actualType).ElementType), reqType); } else if (actualType is PointerType && reqType is ByReferenceType) { expr = Convert(expr, actualType, new PointerType(((ByReferenceType)reqType).ElementType)); return new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new UnaryOperatorExpression(UnaryOperatorType.Dereference, expr) }; } else if (actualType is PointerType && reqType is PointerType) { if (actualType.FullName != reqType.FullName) return expr.CastTo(AstBuilder.ConvertType(reqType)); else return expr; } else { bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType); bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType); if (TypeAnalysis.IsBoolean(reqType)) { if (TypeAnalysis.IsBoolean(actualType)) return expr; if (actualIsIntegerOrEnum) { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType)); } else { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); } } if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) { return new ConditionalExpression { Condition = expr, TrueExpression = AstBuilder.MakePrimitive(1, reqType), FalseExpression = AstBuilder.MakePrimitive(0, reqType) }; } if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType)) { return expr.CastTo(AstBuilder.ConvertType(actualType)); } bool actualIsPrimitiveType = actualIsIntegerOrEnum || actualType.MetadataType == MetadataType.Single || actualType.MetadataType == MetadataType.Double; bool requiredIsPrimitiveType = requiredIsIntegerOrEnum || reqType.MetadataType == MetadataType.Single || reqType.MetadataType == MetadataType.Double; if (actualIsPrimitiveType && requiredIsPrimitiveType) { return expr.CastTo(AstBuilder.ConvertType(reqType)); } return expr; } }
protected MonoObjectType(MonoSymbolFile file, Cecil.TypeDefinition typedef, int size) : base(file.MonoLanguage, "object", size) { this.file = file; this.typedef = typedef; }
static Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference reqType) { if (reqType == null) { return expr; } else { return Convert(expr, reqType.FullName); } }
public MonoClassType(MonoSymbolFile file, Cecil.TypeDefinition typedef, MonoClassInfo class_info) : this(file, typedef) { this.class_info = class_info; }
public MonoStructType(MonoSymbolFile file, TargetClassType type, Cecil.TypeDefinition typedef) { this.File = file; this.Type = type; this.TypeDef = typedef; }
internal static MonoMethodInfo Create(IMonoStructType klass, int index, Cecil.MethodDefinition minfo) { MonoFunctionType type = klass.LookupFunction (minfo); return new MonoMethodInfo (klass, index, minfo, type); }