1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Reflection; 10 using System.Reflection.Emit; 11 using System.Runtime.InteropServices; 12 using System.IO; 13 using Antmicro.Renode.Utilities; 14 15 namespace Antmicro.Renode.TAPHelper 16 { 17 public class DynamicModuleSpawner 18 { GetTAPHelper()19 public static string GetTAPHelper() 20 { 21 var generatedFileName = TemporaryFilesManager.Instance.GetTemporaryFile(); 22 var dirName = Path.GetDirectoryName(generatedFileName); 23 var filName = Path.GetFileName(generatedFileName); 24 25 // Copy Infrastructure.dll to temp directory 26 var currentAssemblyPath = Assembly.GetExecutingAssembly().CodeBase.Substring(7); 27 var targetPath = Path.Combine(TemporaryFilesManager.Instance.EmulatorTemporaryPath, "Infrastructure.dll"); 28 File.Copy(currentAssemblyPath, targetPath, true); 29 30 // Generate binary 31 GenerateTAPHelper(dirName, filName, currentAssemblyPath); 32 33 return generatedFileName; 34 } 35 DynamicModuleSpawner()36 private DynamicModuleSpawner() 37 { 38 } 39 GenerateTAPHelper(string path, string filename, string extensionsAssemblyPath)40 private static void GenerateTAPHelper(string path, string filename, string extensionsAssemblyPath) 41 { 42 var assembly = new AssemblyName { Name = "TAPHelperAssembly" }; 43 var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Save, path); 44 45 var moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name, filename); 46 var typeBuilder = moduleBuilder.DefineType("TAPHelper", TypeAttributes.Public|TypeAttributes.Class); 47 var mainMethodBuilder = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(string[]) }); 48 49 // 50 // Main method 51 // 52 var generator = mainMethodBuilder.GetILGenerator(); 53 var intptrLocale = generator.DeclareLocal(typeof(IntPtr)); 54 var setReturnFail = generator.DefineLabel(); 55 var freeMemoryAndFinish = generator.DefineLabel(); 56 57 // load the proper assembly 58 generator.Emit(OpCodes.Ldtoken, typeof(Func<IntPtr, bool, int>)); 59 generator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); 60 generator.Emit(OpCodes.Ldstr, extensionsAssemblyPath); 61 generator.Emit(OpCodes.Call, typeof(Assembly).GetMethod("LoadFrom", new [] { typeof(string) })); 62 generator.Emit(OpCodes.Ldstr, "Antmicro.Renode.TAPHelper.TAPTools"); 63 generator.Emit(OpCodes.Callvirt, typeof(Assembly).GetMethod("GetType", new [] { typeof(string) })); 64 generator.Emit(OpCodes.Ldstr, "OpenTAP"); 65 generator.Emit(OpCodes.Call, typeof(Delegate).GetMethod("CreateDelegate", new [] { typeof(Type), typeof(Type), typeof(string) })); 66 generator.Emit(OpCodes.Castclass, typeof(Func<IntPtr, bool, int>)); 67 68 // push device name on stack 69 generator.Emit(OpCodes.Ldarg_0); 70 generator.Emit(OpCodes.Ldc_I4, 0); 71 generator.Emit(OpCodes.Ldelem, typeof(string)); 72 generator.Emit(OpCodes.Call, typeof(Marshal).GetMethod("StringToCoTaskMemAuto")); 73 generator.Emit(OpCodes.Dup); 74 generator.Emit(OpCodes.Stloc, intptrLocale); 75 76 // push 'persistant' flag on stack 77 generator.Emit(OpCodes.Ldarg_0); 78 generator.Emit(OpCodes.Ldc_I4, 1); 79 generator.Emit(OpCodes.Ldelem, typeof(string)); 80 generator.Emit(OpCodes.Call, typeof(bool).GetMethod("Parse", new [] { typeof(string) })); 81 82 // call OpenTAP method 83 generator.Emit(OpCodes.Callvirt, typeof(Func<IntPtr, bool, int>).GetMethod("Invoke", new [] { typeof(IntPtr), typeof(bool) })); 84 85 generator.Emit(OpCodes.Ldc_I4, 0); 86 generator.Emit(OpCodes.Blt, setReturnFail); 87 generator.Emit(OpCodes.Ldc_I4, 0); 88 generator.Emit(OpCodes.Br, freeMemoryAndFinish); 89 90 generator.MarkLabel(setReturnFail); 91 /* 92 generator.Emit(OpCodes.Ldtoken, typeof(Func<int>)); 93 generator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); 94 generator.Emit(OpCodes.Ldstr, extensionsAssemblyPath); 95 generator.Emit(OpCodes.Call, typeof(Assembly).GetMethod("LoadFrom", new [] { typeof(string) })); 96 generator.Emit(OpCodes.Ldstr, "Antmicro.Renode.TAPHelper.LibC"); 97 generator.Emit(OpCodes.Callvirt, typeof(Assembly).GetMethod("GetType", new [] { typeof(string) })); 98 generator.Emit(OpCodes.Ldstr, "GetLastError"); 99 generator.Emit(OpCodes.Call, typeof(Delegate).GetMethod("CreateDelegate", new [] { typeof(Type), typeof(Type), typeof(string) })); 100 generator.Emit(OpCodes.Castclass, typeof(Func<int>)); 101 generator.Emit(OpCodes.Callvirt, typeof(Func<int>).GetMethod("Invoke", Type.EmptyTypes)); 102 */ 103 generator.Emit(OpCodes.Ldc_I4, 1); 104 105 // free memory 106 generator.MarkLabel(freeMemoryAndFinish); 107 generator.Emit(OpCodes.Ldloc, intptrLocale); 108 generator.Emit(OpCodes.Call, typeof(Marshal).GetMethod("FreeCoTaskMem")); 109 110 generator.Emit(OpCodes.Ret); 111 112 typeBuilder.CreateType(); 113 114 // Set the entrypoint (thereby declaring it an EXE) 115 assemblyBuilder.SetEntryPoint(mainMethodBuilder,PEFileKinds.ConsoleApplication); 116 assemblyBuilder.Save(filename); 117 } 118 } 119 } 120 121