//获取函数的特性 private static AddCustomTrace getTraceAttribute(TypeDefinition type, MethodDefinition method) { Type inejectClassType = Type.GetType(type.FullName); if (inejectClassType == null) { throw new NullReferenceException("Class Type is null, Attribute: " + type.FullName); } MethodInfo methodinfo = inejectClassType.GetMethod(method.Name); if (methodinfo == null) { throw new NullReferenceException("methodinfo in class " + type.FullName + " is null, method name: " + method.Name); } AddCustomTrace attr = (AddCustomTrace)methodinfo.GetCustomAttributes(typeof(AddCustomTrace), true)[0]; if (attr == null) { throw new NullReferenceException("attr AddCustomTrace on method " + method.Name + " is null"); } return(attr); }
private static void Inject(ModuleDefinition module, MethodDefinition method, TypeDefinition type) { if (module == null) { throw new ArgumentNullException("input argument invalid, module is null"); } if (method == null) { throw new ArgumentNullException("input argument invalid, method is null"); } if (type == null) { throw new ArgumentNullException("input argument invalid, type is null"); } //获取方法AddCustomTrace AddCustomTrace attr = getTraceAttribute(type, method); //判断功能是否开启 if (attr.enable != true) { //Debug.Log(method.Name + " close add custom trace attribute."); return; } //获取特性名称 String name = attr.name; //更改待注入函数局部变量表 method.Body.InitLocals = true; var customTraceType = module.ImportReference(typeof(CustomTrace)); var customTraceTypeDef = new VariableDefinition(customTraceType); method.Body.Variables.Add(customTraceTypeDef); //准备注入的函数 MethodReference getInstance = module.ImportReference(typeof(APMS).GetMethod("getInstance")); MethodReference createInstance = module.ImportReference(typeof(APMS).GetMethod("createCustomTrace", new Type[] { typeof(string) })); MethodReference customTraceStart = module.ImportReference(typeof(CustomTrace).GetMethod("start")); MethodReference customTraceEnd = module.ImportReference(typeof(CustomTrace).GetMethod("stop")); //设置一些标签用于语句跳转 Instruction first = method.Body.Instructions[0]; // 开始注入IL代码 var ilProcessor = method.Body.GetILProcessor(); ilProcessor.InsertBefore(first, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Call, getInstance)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, name)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Callvirt, createInstance)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Stloc, customTraceTypeDef)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldloc, customTraceTypeDef)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Callvirt, customTraceStart)); ilProcessor.InsertBefore(first, ilProcessor.Create(OpCodes.Nop)); //在每一个返回的地方插入stop函数,注意插入指令之后,method.Body.Instructions.Count会增加,需要调整i值 for (int i = 0; i < method.Body.Instructions.Count; i++) { Instruction ins = method.Body.Instructions[i]; OpCode code = ins.OpCode; if (ins.OpCode.Equals(OpCodes.Ret) || ins.OpCode.Equals(OpCodes.Throw)) { //Debug.Log("method: " + method.Name + "i: " + i + " code: " + code); ilProcessor.InsertBefore(ins, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(ins, Instruction.Create(OpCodes.Ldloc, customTraceTypeDef)); ilProcessor.InsertBefore(ins, Instruction.Create(OpCodes.Callvirt, customTraceEnd)); ilProcessor.InsertBefore(ins, ilProcessor.Create(OpCodes.Nop)); i += 4; } } }
private static void Inject(ModuleDefinition module, MethodDefinition method, TypeDefinition type, AssemblyDefinition assembly) { if (module == null) { throw new ArgumentNullException("input argument invalid, module is null"); } if (method == null) { throw new ArgumentNullException("input argument invalid, method is null"); } if (type == null) { throw new ArgumentNullException("input argument invalid, type is null"); } //get AddCustomTrace attribute in method AddCustomTrace attr = getTraceAttribute(type, method, assembly); //whether the function is turned on if (attr.enable != true) { return; } //get name of attribute String name = attr.name; //Change the local variable table of the function to be injected method.Body.InitLocals = true; var customTraceType = module.ImportReference(typeof(CustomTrace)); var customTraceTypeDef = new VariableDefinition(customTraceType); method.Body.Variables.Add(customTraceTypeDef); //Prepare functions to be injected MethodReference getInstance = module.ImportReference(typeof(APMS).GetMethod("getInstance")); MethodReference createInstance = module.ImportReference(typeof(APMS).GetMethod("createCustomTrace", new Type[] { typeof(string) })); MethodReference customTraceStart = module.ImportReference(typeof(CustomTrace).GetMethod("start")); MethodReference customTraceEnd = module.ImportReference(typeof(CustomTrace).GetMethod("stop")); //Set some labels for statement jump Instruction first = method.Body.Instructions[0]; // start injecting IL code var ilProcessor = method.Body.GetILProcessor(); ilProcessor.InsertBefore(first, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Call, getInstance)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, name)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Callvirt, createInstance)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Stloc, customTraceTypeDef)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldloc, customTraceTypeDef)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Callvirt, customTraceStart)); ilProcessor.InsertBefore(first, ilProcessor.Create(OpCodes.Nop)); //Insert stop functions at every return. Note that after inserting the instruction, //method.Body.Instructions.Count increment,and need to adjust the value of i for (int i = 0; i < method.Body.Instructions.Count; i++) { Instruction ins = method.Body.Instructions[i]; OpCode code = ins.OpCode; if (ins.OpCode.Equals(OpCodes.Ret) || ins.OpCode.Equals(OpCodes.Throw)) { //Debug.Log("method: " + method.Name + "i: " + i + " code: " + code); ilProcessor.InsertBefore(ins, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(ins, Instruction.Create(OpCodes.Ldloc, customTraceTypeDef)); ilProcessor.InsertBefore(ins, Instruction.Create(OpCodes.Callvirt, customTraceEnd)); ilProcessor.InsertBefore(ins, ilProcessor.Create(OpCodes.Nop)); i += 4; } } }