Guest User

Untitled

a guest
May 24th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.80 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. using Mono.Cecil;
  6. using Mono.Cecil.Cil;
  7.  
  8. class MethodProcessor {
  9.  
  10. readonly MethodBody body;
  11. readonly MethodDefinition method;
  12. readonly ModuleDefinition module;
  13.  
  14. ILProcessor il;
  15.  
  16. VariableDefinition reflection_parameters;
  17.  
  18. public MethodProcessor (MethodDefinition method)
  19. {
  20. this.method = method;
  21. this.body = method.Body;
  22. this.module = method.Module;
  23. }
  24.  
  25. ILProcessor GetILProcessor ()
  26. {
  27. if (il != null)
  28. return il;
  29.  
  30. return il = body.GetILProcessor ();
  31. }
  32.  
  33. VariableDefinition GetReflectionParameters ()
  34. {
  35. if (reflection_parameters != null)
  36. return reflection_parameters;
  37.  
  38. reflection_parameters = new VariableDefinition (module.Import (typeof (System.Reflection.ParameterInfo [])));
  39. body.Variables.Add (reflection_parameters);
  40. body.InitLocals = true;
  41.  
  42. var il = GetILProcessor ();
  43.  
  44. var instructions = new [] {
  45. il.Create (OpCodes.Ldtoken, method),
  46. il.Create (OpCodes.Call, ImportGetMethodFromHandle ()),
  47. il.Create (OpCodes.Callvirt, module.Import (typeof (System.Reflection.MethodBase).GetMethod ("GetParameters"))),
  48. il.Create (OpCodes.Stloc, reflection_parameters),
  49. };
  50.  
  51. il.InsertBefore (body.Instructions [0], instructions);
  52.  
  53. return reflection_parameters;
  54. }
  55.  
  56. MethodReference ImportGetMethodFromHandle ()
  57. {
  58. return module.Import (typeof (System.Reflection.MethodBase).GetMethod ("GetMethodFromHandle", new [] { typeof (RuntimeMethodHandle) }));
  59. }
  60.  
  61. MethodReference ImportGetFieldFromHandle ()
  62. {
  63. return module.Import (typeof (System.Reflection.FieldInfo).GetMethod ("GetFieldFromHandle", new [] { typeof (RuntimeFieldHandle) }));
  64. }
  65.  
  66. TypeReference ImportMethodInfo ()
  67. {
  68. return method.Module.Import (typeof (System.Reflection.MethodInfo));
  69. }
  70.  
  71. public void Run ()
  72. {
  73. foreach (var instruction in body.Instructions.ToArray ()) {
  74.  
  75. MethodReference reference;
  76. if (!IsMethodCall (instruction, out reference))
  77. continue;
  78.  
  79. if (!IsOfMethod (reference))
  80. continue;
  81.  
  82. switch (reference.DeclaringType.Name) {
  83. case "Parameter":
  84. ProcessParameter (instruction);
  85. break;
  86. case "Property":
  87. ProcessProperty (instruction);
  88. break;
  89. case "Method":
  90. ProcessMethod (instruction);
  91. break;
  92. case "Field":
  93. ProcessField (instruction);
  94. break;
  95. case "Event":
  96. ProcessEvent (instruction);
  97. break;
  98. }
  99. }
  100. }
  101.  
  102. static bool IsOfMethod (MethodReference reference)
  103. {
  104. return reference.Name == "Of";
  105. }
  106.  
  107. static bool IsMethodCall (Instruction instruction, out MethodReference reference)
  108. {
  109. reference = null;
  110. if (instruction.OpCode.FlowControl != FlowControl.Call)
  111. return false;
  112.  
  113. reference = instruction.Operand as MethodReference;
  114. return reference != null;
  115. }
  116.  
  117. void ProcessParameter (Instruction instruction)
  118. {
  119. var load_arg = instruction.Previous;
  120.  
  121. var il = GetILProcessor ();
  122.  
  123. var instructions = new [] {
  124. il.Create (OpCodes.Ldloc, GetReflectionParameters ()),
  125. il.Create (OpCodes.Ldc_I4, GetParameter (load_arg, method).Index),
  126. il.Create (OpCodes.Ldelem_Ref),
  127. };
  128.  
  129. il.InsertBefore (load_arg, instructions);
  130.  
  131. il.Remove (load_arg);
  132. il.Remove (instruction);
  133. }
  134.  
  135. static ParameterDefinition GetParameter (Instruction instruction, MethodDefinition method)
  136. {
  137. int index;
  138. switch (instruction.OpCode.Code) {
  139. case Code.Ldarg:
  140. return (ParameterDefinition) instruction.Operand;
  141. case Code.Ldarg_0:
  142. case Code.Ldarg_S:
  143. index = 0;
  144. break;
  145. case Code.Ldarg_1:
  146. index = 1;
  147. break;
  148. case Code.Ldarg_2:
  149. index = 2;
  150. break;
  151. default:
  152. throw new NotSupportedException ();
  153. }
  154.  
  155. if (method.HasThis)
  156. index--;
  157.  
  158. return method.Parameters [index];
  159. }
  160.  
  161. void ProcessProperty (Instruction instruction)
  162. {
  163. var call_get = instruction.Previous;
  164. var load_subject = call_get.Previous;
  165. var getter = (MethodReference) call_get.Operand;
  166. var call_property = (MethodReference) instruction.Operand;
  167.  
  168. var il = GetILProcessor ();
  169.  
  170. var instructions = new [] {
  171. il.Create (OpCodes.Ldtoken, getter),
  172. il.Create (OpCodes.Call, ImportGetMethodFromHandle ()),
  173. il.Create (OpCodes.Castclass, ImportMethodInfo ()),
  174. il.Create (OpCodes.Call, call_property.DeclaringType.Resolve ().Methods.First (m => m.Name == "Of" && m.Parameters.Count > 0 && m.Parameters [0].ParameterType.Name == "MethodInfo")),
  175. };
  176.  
  177. il.InsertBefore (load_subject, instructions);
  178.  
  179. il.Remove (load_subject);
  180. il.Remove (call_get);
  181. il.Remove (instruction);
  182. }
  183.  
  184. void ProcessMethod (Instruction instruction)
  185. {
  186. var new_delegate = instruction.Previous;
  187. var ld_ftn = new_delegate.Previous;
  188. var ld_this = ld_ftn.Previous;
  189.  
  190. var il = GetILProcessor ();
  191.  
  192. var instructions = new [] {
  193. il.Create (OpCodes.Ldtoken, ld_ftn.Operand as MethodReference),
  194. il.Create (OpCodes.Call, ImportGetMethodFromHandle ()),
  195. il.Create (OpCodes.Castclass, ImportMethodInfo ()),
  196. };
  197.  
  198. il.InsertBefore (ld_this, instructions);
  199.  
  200. il.Remove (ld_this);
  201. il.Remove (ld_ftn);
  202. il.Remove (new_delegate);
  203. il.Remove (instruction);
  204. }
  205.  
  206. void ProcessField (Instruction instruction)
  207. {
  208. var load_field = instruction.Previous;
  209. var load_this = IsStatic (load_field.OpCode) ? load_field.Previous : null;
  210.  
  211. var il = GetILProcessor ();
  212.  
  213. var instructions = new [] {
  214. il.Create (OpCodes.Ldtoken, load_field.Operand as FieldReference),
  215. il.Create (OpCodes.Call, ImportGetFieldFromHandle ()),
  216. };
  217.  
  218. il.InsertBefore (load_this ?? load_field, instructions);
  219.  
  220. if (load_this != null)
  221. il.Remove (load_this);
  222. il.Remove (load_field);
  223. il.Remove (instruction);
  224. }
  225.  
  226. static bool IsStatic (OpCode code)
  227. {
  228. return code == OpCodes.Ldsfld;
  229. }
  230.  
  231. void ProcessEvent (Instruction instruction)
  232. {
  233. var call_event = (MethodReference) instruction.Operand;
  234. var load_field = instruction.Previous;
  235. var load_this = IsStatic (load_field.OpCode) ? load_field.Previous : null;
  236.  
  237. var il = GetILProcessor ();
  238.  
  239. var instructions = new [] {
  240. il.Create (OpCodes.Ldtoken, load_field.Operand as FieldReference),
  241. il.Create (OpCodes.Call, ImportGetFieldFromHandle ()),
  242. il.Create (OpCodes.Call, call_event.DeclaringType.Resolve ().Methods.First (m => m.Name == "Of" && m.Parameters.Count > 0 && m.Parameters [0].ParameterType.Name == "FieldInfo")),
  243. };
  244.  
  245. il.InsertBefore (load_this ?? load_field, instructions);
  246.  
  247. if (load_this != null)
  248. il.Remove (load_this);
  249. il.Remove (load_field);
  250. il.Remove (instruction);
  251. }
  252. }
  253.  
  254. static class ILProcessorRocks {
  255.  
  256. public static void InsertBefore (this ILProcessor il, Instruction target, IEnumerable<Instruction> instructions)
  257. {
  258. foreach (var instruction in instructions)
  259. il.InsertBefore (target, instruction);
  260. }
  261. }
  262.  
  263. class Program {
  264.  
  265. static void Main (string [] args)
  266. {
  267. var module = ModuleDefinition.ReadModule (args [0]);
  268.  
  269. foreach (var type in module.Types) {
  270. foreach (var method in type.Methods) {
  271. if (!method.HasBody)
  272. continue;
  273.  
  274. var processor = new MethodProcessor (method);
  275. processor.Run ();
  276. }
  277. }
  278.  
  279. module.Write (args [0]);
  280. }
  281. }
Add Comment
Please, Sign In to add comment