public static void Main(string[] args) { if (args.Length != 3) { Console.Error.WriteLine("usage: minvoke.exe MapAssemblyName InputAssemblyName OutputAssemblyName"); Environment.Exit(1); } string map_assembly_name = args[0]; string input_assembly_name = args[1]; string output_assembly_name = args[2]; Console.WriteLine("building list of MapDllImports from map assembly {0}", map_assembly_name); DllImportMap map = BuildMap(map_assembly_name); Console.WriteLine("building list of DllImports in input assembly {0}", input_assembly_name); var input_assembly = AssemblyDefinition.ReadAssembly(input_assembly_name); DllImports imports = CollectDllImports(input_assembly); Console.WriteLine("retargeting assembly {0} -> {1}", input_assembly_name, output_assembly_name); Retarget(input_assembly, map, imports); input_assembly.Write(output_assembly_name); }
private static void Retarget(TypeDefinition type, DllImportMap map, DllImports imports) { foreach (var nested in type.NestedTypes) { Retarget(nested, map, imports); } foreach (MethodDefinition md in type.Methods) { if (!md.HasBody) { continue; } for (int i = 0; i < md.Body.Instructions.Count; i++) { Instruction ins = md.Body.Instructions[i]; if (ins.OpCode == OpCodes.Call) { MethodDefinition method_operand = ins.Operand as MethodDefinition; if (method_operand == null) { continue; } PInvokeInfo pinfo = method_operand.PInvokeInfo; if (pinfo == null) { continue; } ImportKey key = new ImportKey(pinfo.Module.Name, pinfo.EntryPoint); if (imports.ContainsKey(key)) { //Console.WriteLine ("{0} is a pinvoke, {1}/{2}", method_operand, pinfo.EntryPoint, pinfo.Module.Name); if (map.ContainsKey(key)) { Console.WriteLine("retargeting reference to method method {0}/{1}", key.module_name, key.entry_point); var il = md.Body.GetILProcessor(); MethodDefinition mapped_method = map[key]; MethodReference mapped_ref; mapped_ref = type.Module.Import(mapped_method); Instruction callMethod = il.Create(OpCodes.Call, mapped_ref); il.Replace(ins, callMethod); } else { Console.WriteLine("WARNING: no map entry for method {0}/{1}", key.module_name, key.entry_point); } } } } } }
private static void Retarget(AssemblyDefinition assembly, DllImportMap map, DllImports imports) { foreach (TypeDefinition t in assembly.MainModule.Types) { if (t.Name == "<Module>") { continue; } Retarget(t, map, imports); } }
private static DllImportMap BuildMap(string map_assembly) { DllImportMap map = new DllImportMap(); var assembly = AssemblyDefinition.ReadAssembly(map_assembly); foreach (TypeDefinition t in assembly.MainModule.GetAllTypes()) { if (t.Name == "<Module>") { continue; } if (t.IsSpecialName || t.IsRuntimeSpecialName) { continue; } foreach (MethodDefinition md in t.Methods) { if (md.IsSpecialName) { continue; } if (IsFinalizer(md)) { continue; } CustomAttribute attr = GetMapDllImportAttribute(md); if (attr == null) { continue; } ImportKey key = new ImportKey(attr.ConstructorArguments [0].Value.ToString(), md.Name); map.Add(key, md); } } return(map); }