1 // 2 // Copyright (c) 2010-2022 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using System.IO; 10 using System.Linq; 11 using System.Runtime.InteropServices; 12 using Mono.Cecil; 13 14 namespace Antmicro.Renode.Utilities 15 { 16 public class AssemblyHelper 17 { TryInitializeBundledAssemblies()18 public static bool TryInitializeBundledAssemblies() 19 { 20 var result = false; 21 for(var i = 0; i < BundledAssembliesCount; i++) 22 { 23 var bundledAssembly = GetBundledAssemblyById(i); 24 bundledAssemblies.Add(bundledAssembly); 25 result = true; 26 } 27 28 return result; 29 } 30 GetBundledAssembliesNames()31 public static IEnumerable<string> GetBundledAssembliesNames() 32 { 33 return bundledAssemblies.Select(x => x.Name); 34 } 35 GetBundledAssemblyByFullName(string fullName)36 public static AssemblyDefinition GetBundledAssemblyByFullName(string fullName) 37 { 38 return bundledAssemblies.Select(x => x.Definition).FirstOrDefault(x => x.FullName == fullName); 39 } 40 GetBundledAssemblyByName(string name)41 public static AssemblyDefinition GetBundledAssemblyByName(string name) 42 { 43 return bundledAssemblies.FirstOrDefault(x => x.Name == name).Definition; 44 } 45 GetAssembliesLocations()46 public static IEnumerable<string> GetAssembliesLocations() 47 { 48 if(BundledAssembliesCount > 0) 49 { 50 foreach(var assembly in bundledAssemblies.Select(x => x.Location)) 51 { 52 yield return assembly; 53 } 54 } 55 foreach(var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(x => !x.IsDynamic).Select(x => x.Location).Where(Path.IsPathRooted)) 56 { 57 yield return assembly; 58 } 59 } 60 61 public static int BundledAssembliesCount 62 { 63 get 64 { 65 try 66 { 67 return GetBundlesCountInternal(); 68 } 69 catch 70 { 71 // an exception means we couldn't locate 72 // `GetBundlesCount` function in this binary; 73 // that, in turn, means that there are no 74 // bundled assemblies - that's why we simply 75 // return 0 76 return 0; 77 } 78 } 79 } 80 GetBundledAssemblyById(int id)81 private static BundledAssemblyDefinition GetBundledAssemblyById(int id) 82 { 83 unsafe 84 { 85 var result = new BundledAssemblyDefinition(); 86 using(var stream = new UnmanagedMemoryStream((byte*)GetBundleDataPointerInternal(id).ToPointer(), GetBundleDataSizeInternal(id))) 87 { 88 result.Name = Marshal.PtrToStringAnsi(GetBundleNameInternal(id)); 89 result.Definition = AssemblyDefinition.ReadAssembly(stream); 90 result.Location = ExtractAssemblyToFile(stream, result.Name); 91 } 92 return result; 93 } 94 } 95 ExtractAssemblyToFile(Stream stream, string fileName)96 private static string ExtractAssemblyToFile(Stream stream, string fileName) 97 { 98 var outputFile = TemporaryFilesManager.Instance.GetTemporaryFile(fileName); 99 using(var fileStream = File.Create(outputFile, (int)stream.Length)) 100 { 101 var bytesInStream = new byte[stream.Length]; 102 stream.Seek(0, SeekOrigin.Begin); 103 stream.Read(bytesInStream, 0, bytesInStream.Length); 104 fileStream.Write(bytesInStream, 0, bytesInStream.Length); 105 } 106 return outputFile; 107 } 108 109 [DllImport("__Internal", EntryPoint = "GetBundlesCount")] GetBundlesCountInternal()110 private static extern int GetBundlesCountInternal(); 111 112 [DllImport("__Internal", EntryPoint = "GetBundleName")] GetBundleNameInternal(int id)113 private static extern IntPtr GetBundleNameInternal(int id); 114 115 [DllImport("__Internal", EntryPoint = "GetBundleDataSize")] GetBundleDataSizeInternal(int id)116 private static extern UInt32 GetBundleDataSizeInternal(int id); 117 118 [DllImport("__Internal", EntryPoint = "GetBundleDataPointer")] GetBundleDataPointerInternal(int id)119 private static extern IntPtr GetBundleDataPointerInternal(int id); 120 121 private static readonly List<BundledAssemblyDefinition> bundledAssemblies = new List<BundledAssemblyDefinition>(); 122 123 private struct BundledAssemblyDefinition 124 { 125 public string Name; 126 public AssemblyDefinition Definition; 127 public string Location; 128 } 129 } 130 } 131