mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
接入obfuz->2.0
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class AssemblyCache : AssemblyCacheBase
|
||||
{
|
||||
|
||||
public AssemblyCache(IAssemblyResolver assemblyResolver) : base(assemblyResolver)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa4650e79a52228488aa85e0690ca52c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,99 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public abstract class AssemblyCacheBase
|
||||
{
|
||||
private readonly IAssemblyResolver _assemblyPathResolver;
|
||||
private readonly ModuleContext _modCtx;
|
||||
private readonly AssemblyResolver _asmResolver;
|
||||
private bool _loadedNetstandard;
|
||||
|
||||
|
||||
public ModuleContext ModCtx => _modCtx;
|
||||
|
||||
public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>();
|
||||
|
||||
private readonly List<ModuleDefMD> _loadedModulesIncludeNetstandard = new List<ModuleDefMD>();
|
||||
|
||||
protected AssemblyCacheBase(IAssemblyResolver assemblyResolver)
|
||||
{
|
||||
_assemblyPathResolver = assemblyResolver;
|
||||
_modCtx = ModuleDef.CreateModuleContext();
|
||||
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
|
||||
_asmResolver.EnableTypeDefCache = true;
|
||||
_asmResolver.UseGAC = false;
|
||||
}
|
||||
|
||||
|
||||
public ModuleDefMD TryLoadModule(string moduleName, bool loadReferenceAssemblies = true)
|
||||
{
|
||||
string dllPath = _assemblyPathResolver.ResolveAssembly(moduleName, false);
|
||||
if (string.IsNullOrEmpty(dllPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return LoadModule(moduleName, loadReferenceAssemblies);
|
||||
}
|
||||
|
||||
public ModuleDefMD LoadModule(string moduleName, bool loadReferenceAssemblies = true)
|
||||
{
|
||||
// Debug.Log($"load module:{moduleName}");
|
||||
if (LoadedModules.TryGetValue(moduleName, out var mod))
|
||||
{
|
||||
return mod;
|
||||
}
|
||||
if (moduleName == "netstandard")
|
||||
{
|
||||
if (!_loadedNetstandard)
|
||||
{
|
||||
LoadNetStandard();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
|
||||
LoadedModules.Add(moduleName, mod);
|
||||
|
||||
if (loadReferenceAssemblies)
|
||||
{
|
||||
foreach (var refAsm in mod.GetAssemblyRefs())
|
||||
{
|
||||
LoadModule(refAsm.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
private void LoadNetStandard()
|
||||
{
|
||||
string netstandardDllPath = _assemblyPathResolver.ResolveAssembly("netstandard", false);
|
||||
if (!string.IsNullOrEmpty(netstandardDllPath))
|
||||
{
|
||||
DoLoadModule(netstandardDllPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.0"));
|
||||
DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.1"));
|
||||
}
|
||||
_loadedNetstandard = true;
|
||||
}
|
||||
|
||||
private ModuleDefMD DoLoadModule(string dllPath)
|
||||
{
|
||||
//Debug.Log($"do load module:{dllPath}");
|
||||
ModuleDefMD mod = ModuleDefMD.Load(File.ReadAllBytes(dllPath), _modCtx);
|
||||
mod.EnableTypeDefFindCache = true;
|
||||
_asmResolver.AddToCache(mod);
|
||||
_loadedModulesIncludeNetstandard.Add(mod);
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b01fa99119e72141bfee5628c0ffce1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,50 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class AssemblyReferenceDeepCollector : AssemblyCacheBase
|
||||
{
|
||||
private readonly List<string> _rootAssemblies;
|
||||
|
||||
public IReadOnlyList<string> GetRootAssemblyNames()
|
||||
{
|
||||
return _rootAssemblies;
|
||||
}
|
||||
|
||||
public List<ModuleDefMD> GetLoadedModulesExcludeRootAssemblies()
|
||||
{
|
||||
return LoadedModules.Where(e => !_rootAssemblies.Contains(e.Key)).Select(e => e.Value).ToList();
|
||||
}
|
||||
|
||||
public List<ModuleDefMD> GetLoadedModules()
|
||||
{
|
||||
return LoadedModules.Select(e => e.Value).ToList();
|
||||
}
|
||||
|
||||
public List<ModuleDefMD> GetLoadedModulesOfRootAssemblies()
|
||||
{
|
||||
return _rootAssemblies.Select(ass => LoadedModules[ass]).ToList();
|
||||
}
|
||||
|
||||
public AssemblyReferenceDeepCollector(IAssemblyResolver assemblyResolver, List<string> rootAssemblies) : base(assemblyResolver)
|
||||
{
|
||||
_rootAssemblies = rootAssemblies;
|
||||
LoadAllAssembiles();
|
||||
}
|
||||
|
||||
private void LoadAllAssembiles()
|
||||
{
|
||||
foreach (var asm in _rootAssemblies)
|
||||
{
|
||||
LoadModule(asm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0342c7d8575fdea49896260c77285286
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public abstract class AssemblyResolverBase : IAssemblyResolver
|
||||
{
|
||||
public string ResolveAssembly(string assemblyName, bool throwExIfNotFind)
|
||||
{
|
||||
if (TryResolveAssembly(assemblyName, out string assemblyPath))
|
||||
{
|
||||
return assemblyPath;
|
||||
}
|
||||
if (throwExIfNotFind)
|
||||
{
|
||||
if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName))
|
||||
{
|
||||
throw new Exception($"resolve Hot update dll:{assemblyName} failed! Please make sure that this hot update dll exists or the search path is configured in the external hot update path.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"resolve AOT dll:{assemblyName} failed! Please make sure that the AOT project has referenced the dll and generated the trimmed AOT dll correctly.");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract bool TryResolveAssembly(string assemblyName, out string assemblyPath);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f8d48774b790364cbd36f1f68fd6614
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
|
||||
public class AssemblySorter
|
||||
{
|
||||
class Node
|
||||
{
|
||||
public string Name;
|
||||
public List<Node> Dependencies = new List<Node>();
|
||||
|
||||
public Node(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
class TopologicalSorter
|
||||
{
|
||||
|
||||
public static List<Node> Sort(List<Node> nodes)
|
||||
{
|
||||
List<Node> sorted = new List<Node>();
|
||||
HashSet<Node> visited = new HashSet<Node>();
|
||||
HashSet<Node> tempMarks = new HashSet<Node>();
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
if (!visited.Contains(node))
|
||||
{
|
||||
Visit(node, visited, tempMarks, sorted);
|
||||
}
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private static void Visit(Node node, HashSet<Node> visited, HashSet<Node> tempMarks, List<Node> sorted)
|
||||
{
|
||||
if (tempMarks.Contains(node))
|
||||
{
|
||||
throw new Exception("Detected cyclic dependency!");
|
||||
}
|
||||
|
||||
if (!visited.Contains(node))
|
||||
{
|
||||
tempMarks.Add(node);
|
||||
foreach (var dependency in node.Dependencies)
|
||||
{
|
||||
Visit(dependency, visited, tempMarks, sorted);
|
||||
}
|
||||
tempMarks.Remove(node);
|
||||
visited.Add(node);
|
||||
sorted.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, Dictionary<string, HashSet<string>> refs)
|
||||
{
|
||||
var nodes = new List<Node>();
|
||||
var nodeMap = new Dictionary<string, Node>();
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var node = new Node(assembly);
|
||||
nodes.Add(node);
|
||||
nodeMap.Add(assembly, node);
|
||||
}
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var node = nodeMap[assembly];
|
||||
foreach (var refAssembly in refs[assembly])
|
||||
{
|
||||
node.Dependencies.Add(nodeMap[refAssembly]);
|
||||
}
|
||||
}
|
||||
var sortedNodes = TopologicalSorter.Sort(nodes);
|
||||
return sortedNodes.Select(node => node.Name).ToList();
|
||||
}
|
||||
|
||||
public static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, IAssemblyResolver assemblyResolver)
|
||||
{
|
||||
var assCache = new AssemblyCache(assemblyResolver);
|
||||
var assRefAssemblies = new Dictionary<string, HashSet<string>>();
|
||||
foreach (var assName in assemblies)
|
||||
{
|
||||
var refAssemblies = new HashSet<string>();
|
||||
var mod = assCache.LoadModule(assName, false);
|
||||
foreach (var refAss in mod.GetAssemblyRefs())
|
||||
{
|
||||
if (assemblies.Contains(refAss.Name.ToString()))
|
||||
{
|
||||
refAssemblies.Add(refAss.Name.ToString());
|
||||
}
|
||||
}
|
||||
assRefAssemblies.Add(assName, refAssemblies);
|
||||
}
|
||||
return SortAssemblyByReferenceOrder(assemblies, assRefAssemblies);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9b8eb45398fa344daa8c6e9b9fbf291
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class CombinedAssemblyResolver : AssemblyResolverBase
|
||||
{
|
||||
private readonly IAssemblyResolver[] _resolvers;
|
||||
|
||||
public CombinedAssemblyResolver(params IAssemblyResolver[] resolvers)
|
||||
{
|
||||
_resolvers = resolvers;
|
||||
}
|
||||
|
||||
protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
|
||||
{
|
||||
foreach(var resolver in _resolvers)
|
||||
{
|
||||
var assembly = resolver.ResolveAssembly(assemblyName, false);
|
||||
if (assembly != null)
|
||||
{
|
||||
assemblyPath = assembly;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assemblyPath = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89b83906438c52d4b9af4aaef055f177
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class FixedSetAssemblyResolver : AssemblyResolverBase
|
||||
{
|
||||
private readonly string _rootDir;
|
||||
private readonly HashSet<string> _fileNames;
|
||||
|
||||
public FixedSetAssemblyResolver(string rootDir, IEnumerable<string> fileNameNotExts)
|
||||
{
|
||||
_rootDir = rootDir;
|
||||
_fileNames = new HashSet<string>(fileNameNotExts);
|
||||
}
|
||||
|
||||
protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
|
||||
{
|
||||
if (_fileNames.Contains(assemblyName))
|
||||
{
|
||||
assemblyPath = $"{_rootDir}/{assemblyName}.dll";
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
assemblyPath = $"{_rootDir}/{assemblyName}.dll.bytes";
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assemblyPath = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f135accd10f42c64b9735c3aa8cb1e77
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,110 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
|
||||
public class GenericArgumentContext
|
||||
{
|
||||
private readonly List<TypeSig> typeArgsStack;
|
||||
private readonly List<TypeSig> methodArgsStack;
|
||||
|
||||
public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack)
|
||||
{
|
||||
this.typeArgsStack = typeArgsStack;
|
||||
this.methodArgsStack = methodArgsStack;
|
||||
}
|
||||
|
||||
public TypeSig Resolve(TypeSig typeSig)
|
||||
{
|
||||
if (!typeSig.ContainsGenericParameter)
|
||||
{
|
||||
return typeSig;
|
||||
}
|
||||
typeSig = typeSig.RemovePinnedAndModifiers();
|
||||
switch (typeSig.ElementType)
|
||||
{
|
||||
case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next));
|
||||
case ElementType.ByRef: return new ByRefSig(Resolve(typeSig.Next));
|
||||
|
||||
case ElementType.SZArray: return new SZArraySig(Resolve(typeSig.Next));
|
||||
case ElementType.Array:
|
||||
{
|
||||
var ara = (ArraySig)typeSig;
|
||||
return new ArraySig(Resolve(typeSig.Next), ara.Rank, ara.Sizes, ara.LowerBounds);
|
||||
}
|
||||
|
||||
case ElementType.Var:
|
||||
{
|
||||
GenericVar genericVar = (GenericVar)typeSig;
|
||||
var newSig = Resolve(typeArgsStack, genericVar.Number);
|
||||
if (newSig == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return newSig;
|
||||
}
|
||||
|
||||
case ElementType.MVar:
|
||||
{
|
||||
GenericMVar genericVar = (GenericMVar)typeSig;
|
||||
var newSig = Resolve(methodArgsStack, genericVar.Number);
|
||||
if (newSig == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return newSig;
|
||||
}
|
||||
case ElementType.GenericInst:
|
||||
{
|
||||
var gia = (GenericInstSig)typeSig;
|
||||
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => Resolve(ga)).ToList());
|
||||
}
|
||||
|
||||
case ElementType.FnPtr:
|
||||
{
|
||||
var fptr = (FnPtrSig)typeSig;
|
||||
var cs = fptr.Signature;
|
||||
CallingConventionSig ccs;
|
||||
switch (cs)
|
||||
{
|
||||
case MethodSig ms:
|
||||
{
|
||||
ccs = new MethodSig(ms.GetCallingConvention(), ms.GenParamCount, Resolve(ms.RetType), ms.Params.Select(p => Resolve(p)).ToList());
|
||||
break;
|
||||
}
|
||||
case PropertySig ps:
|
||||
{
|
||||
ccs = new PropertySig(ps.HasThis, Resolve(ps.RetType));
|
||||
break;
|
||||
}
|
||||
case GenericInstMethodSig gims:
|
||||
{
|
||||
ccs = new GenericInstMethodSig(gims.GenericArguments.Select(ga => Resolve(ga)).ToArray());
|
||||
break;
|
||||
}
|
||||
default: throw new NotSupportedException(cs.ToString());
|
||||
}
|
||||
return new FnPtrSig(ccs);
|
||||
}
|
||||
|
||||
case ElementType.ValueArray:
|
||||
{
|
||||
var vas = (ValueArraySig)typeSig;
|
||||
return new ValueArraySig(Resolve(vas.Next), vas.Size);
|
||||
}
|
||||
default: return typeSig;
|
||||
}
|
||||
}
|
||||
|
||||
private TypeSig Resolve(List<TypeSig> args, uint number)
|
||||
{
|
||||
return args[(int)number];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07595a9b5b2f54c44a67022ae3e077d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,74 @@
|
||||
using dnlib.DotNet;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class GenericClass
|
||||
{
|
||||
public TypeDef Type { get; }
|
||||
|
||||
public List<TypeSig> KlassInst { get; }
|
||||
|
||||
private readonly int _hashCode;
|
||||
|
||||
public GenericClass(TypeDef type, List<TypeSig> classInst)
|
||||
{
|
||||
Type = type;
|
||||
KlassInst = classInst;
|
||||
_hashCode = ComputHashCode();
|
||||
}
|
||||
|
||||
public GenericClass ToGenericShare()
|
||||
{
|
||||
return new GenericClass(Type, MetaUtil.ToShareTypeSigs(Type.Module.CorLibTypes, KlassInst));
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is GenericClass gc)
|
||||
{
|
||||
return Type == gc.Type && MetaUtil.EqualsTypeSigArray(KlassInst, gc.KlassInst);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _hashCode;
|
||||
}
|
||||
|
||||
private int ComputHashCode()
|
||||
{
|
||||
int hash = TypeEqualityComparer.Instance.GetHashCode(Type);
|
||||
if (KlassInst != null)
|
||||
{
|
||||
hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public TypeSig ToTypeSig()
|
||||
{
|
||||
return new GenericInstSig(this.Type.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst);
|
||||
}
|
||||
|
||||
public static GenericClass ResolveClass(TypeSpec type, GenericArgumentContext ctx)
|
||||
{
|
||||
var sig = type.TypeSig.ToGenericInstSig();
|
||||
if (sig == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
TypeDef def = type.ResolveTypeDef();
|
||||
if (def == null)
|
||||
{
|
||||
Debug.LogWarning($"type:{type} ResolveTypeDef() == null");
|
||||
return null;
|
||||
}
|
||||
var klassInst = ctx != null ? sig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : sig.GenericArguments.ToList();
|
||||
return new GenericClass(def, klassInst);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c95ff173013909548bd9e2008812f9ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,109 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class GenericMethod
|
||||
{
|
||||
public MethodDef Method { get; }
|
||||
|
||||
public List<TypeSig> KlassInst { get; }
|
||||
|
||||
public List<TypeSig> MethodInst { get; }
|
||||
|
||||
private readonly int _hashCode;
|
||||
|
||||
public GenericMethod(MethodDef method, List<TypeSig> classInst, List<TypeSig> methodInst)
|
||||
{
|
||||
Method = method;
|
||||
KlassInst = classInst;
|
||||
MethodInst = methodInst;
|
||||
_hashCode = ComputHashCode();
|
||||
}
|
||||
|
||||
public GenericMethod ToGenericShare()
|
||||
{
|
||||
ICorLibTypes corLibTypes = Method.Module.CorLibTypes;
|
||||
return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(corLibTypes, KlassInst), MetaUtil.ToShareTypeSigs(corLibTypes, MethodInst));
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
GenericMethod o = (GenericMethod)obj;
|
||||
return Method == o.Method
|
||||
&& MetaUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
|
||||
&& MetaUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _hashCode;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Method}|{string.Join(",", (IEnumerable<TypeSig>)KlassInst ?? Array.Empty<TypeSig>())}|{string.Join(",", (IEnumerable<TypeSig>)MethodInst ?? Array.Empty<TypeSig>())}";
|
||||
}
|
||||
|
||||
private int ComputHashCode()
|
||||
{
|
||||
int hash = MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(Method);
|
||||
if (KlassInst != null)
|
||||
{
|
||||
hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst));
|
||||
}
|
||||
if (MethodInst != null)
|
||||
{
|
||||
hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(MethodInst));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public MethodSpec ToMethodSpec()
|
||||
{
|
||||
IMethodDefOrRef mt = KlassInst != null ?
|
||||
(IMethodDefOrRef)new MemberRefUser(this.Method.Module, Method.Name, Method.MethodSig, new TypeSpecUser(new GenericInstSig(this.Method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst)))
|
||||
: this.Method;
|
||||
return new MethodSpecUser(mt, new GenericInstMethodSig(MethodInst));
|
||||
}
|
||||
|
||||
public static GenericMethod ResolveMethod(IMethod method, GenericArgumentContext ctx)
|
||||
{
|
||||
//Debug.Log($"== resolve method:{method}");
|
||||
TypeDef typeDef = null;
|
||||
List<TypeSig> klassInst = null;
|
||||
List<TypeSig> methodInst = null;
|
||||
|
||||
MethodDef methodDef = null;
|
||||
|
||||
|
||||
var decalringType = method.DeclaringType;
|
||||
typeDef = decalringType.ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
GenericInstSig gis = decalringType.TryGetGenericInstSig();
|
||||
if (gis != null)
|
||||
{
|
||||
klassInst = ctx != null ? gis.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : gis.GenericArguments.ToList();
|
||||
}
|
||||
methodDef = method.ResolveMethodDef();
|
||||
if (methodDef == null)
|
||||
{
|
||||
//Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
|
||||
return null;
|
||||
}
|
||||
if (method is MethodSpec methodSpec)
|
||||
{
|
||||
methodInst = ctx != null ? methodSpec.GenericInstMethodSig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList()
|
||||
: methodSpec.GenericInstMethodSig.GenericArguments.ToList();
|
||||
}
|
||||
return new GenericMethod(methodDef, klassInst, methodInst);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88ecf3d52ec393b4cac142518944e487
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public interface IAssemblyResolver
|
||||
{
|
||||
string ResolveAssembly(string assemblyName, bool throwExIfNotFind);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f962a018018dbb945a19f82d2e098686
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,217 @@
|
||||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using HybridCLR.Editor.Settings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public static class MetaUtil
|
||||
{
|
||||
|
||||
public static bool EqualsTypeSig(TypeSig a, TypeSig b)
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (a != null && b != null)
|
||||
{
|
||||
return TypeEqualityComparer.Instance.Equals(a, b);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool EqualsTypeSigArray(List<TypeSig> a, List<TypeSig> b)
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (a != null && b != null)
|
||||
{
|
||||
if (a.Count != b.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.Count; i++)
|
||||
{
|
||||
if (!TypeEqualityComparer.Instance.Equals(a[i], b[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TypeSig Inflate(TypeSig sig, GenericArgumentContext ctx)
|
||||
{
|
||||
if (!sig.ContainsGenericParameter)
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
return ctx.Resolve(sig);
|
||||
}
|
||||
|
||||
public static TypeSig ToShareTypeSig(ICorLibTypes corTypes, TypeSig typeSig)
|
||||
{
|
||||
var a = typeSig.RemovePinnedAndModifiers();
|
||||
switch (a.ElementType)
|
||||
{
|
||||
case ElementType.Void: return corTypes.Void;
|
||||
case ElementType.Boolean: return corTypes.Byte;
|
||||
case ElementType.Char: return corTypes.UInt16;
|
||||
case ElementType.I1: return corTypes.SByte;
|
||||
case ElementType.U1:return corTypes.Byte;
|
||||
case ElementType.I2: return corTypes.Int16;
|
||||
case ElementType.U2: return corTypes.UInt16;
|
||||
case ElementType.I4: return corTypes.Int32;
|
||||
case ElementType.U4: return corTypes.UInt32;
|
||||
case ElementType.I8: return corTypes.Int64;
|
||||
case ElementType.U8: return corTypes.UInt64;
|
||||
case ElementType.R4: return corTypes.Single;
|
||||
case ElementType.R8: return corTypes.Double;
|
||||
case ElementType.String: return corTypes.Object;
|
||||
case ElementType.TypedByRef: return corTypes.TypedReference;
|
||||
case ElementType.I: return corTypes.IntPtr;
|
||||
case ElementType.U: return corTypes.UIntPtr;
|
||||
case ElementType.Object: return corTypes.Object;
|
||||
case ElementType.Sentinel: return typeSig;
|
||||
case ElementType.Ptr: return corTypes.UIntPtr;
|
||||
case ElementType.ByRef: return corTypes.UIntPtr;
|
||||
case ElementType.SZArray: return corTypes.Object;
|
||||
case ElementType.Array: return corTypes.Object;
|
||||
case ElementType.ValueType:
|
||||
{
|
||||
TypeDef typeDef = a.ToTypeDefOrRef().ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new Exception($"type:{a} definition could not be found");
|
||||
}
|
||||
if (typeDef.IsEnum)
|
||||
{
|
||||
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
|
||||
}
|
||||
return typeSig;
|
||||
}
|
||||
case ElementType.Var:
|
||||
case ElementType.MVar:
|
||||
case ElementType.Class: return corTypes.Object;
|
||||
case ElementType.GenericInst:
|
||||
{
|
||||
var gia = (GenericInstSig)a;
|
||||
TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new Exception($"type:{a} definition could not be found");
|
||||
}
|
||||
if (typeDef.IsEnum)
|
||||
{
|
||||
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
|
||||
}
|
||||
if (!typeDef.IsValueType)
|
||||
{
|
||||
return corTypes.Object;
|
||||
}
|
||||
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(corTypes, ga)).ToList());
|
||||
}
|
||||
case ElementType.FnPtr: return corTypes.UIntPtr;
|
||||
case ElementType.ValueArray: return typeSig;
|
||||
case ElementType.Module: return typeSig;
|
||||
default:
|
||||
throw new NotSupportedException(typeSig.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static List<TypeSig> ToShareTypeSigs(ICorLibTypes corTypes, IList<TypeSig> typeSigs)
|
||||
{
|
||||
if (typeSigs == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return typeSigs.Select(s => ToShareTypeSig(corTypes, s)).ToList();
|
||||
}
|
||||
|
||||
public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
||||
{
|
||||
var externalDirs = HybridCLRSettings.Instance.externalHotUpdateAssembliyDirs;
|
||||
var defaultHotUpdateOutputDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
|
||||
IAssemblyResolver defaultHotUpdateResolver = new FixedSetAssemblyResolver(defaultHotUpdateOutputDir, hotUpdateDlls);
|
||||
if (externalDirs == null || externalDirs.Length == 0)
|
||||
{
|
||||
return defaultHotUpdateResolver;
|
||||
}
|
||||
else
|
||||
{
|
||||
var resolvers = new List<IAssemblyResolver>();
|
||||
foreach (var dir in externalDirs)
|
||||
{
|
||||
resolvers.Add(new FixedSetAssemblyResolver($"{dir}/{target}", hotUpdateDlls));
|
||||
resolvers.Add(new FixedSetAssemblyResolver(dir, hotUpdateDlls));
|
||||
}
|
||||
resolvers.Add(defaultHotUpdateResolver);
|
||||
return new CombinedAssemblyResolver(resolvers.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static IAssemblyResolver CreateAOTAssemblyResolver(BuildTarget target)
|
||||
{
|
||||
return new PathAssemblyResolver(SettingsUtil.GetAssembliesPostIl2CppStripDir(target));
|
||||
}
|
||||
|
||||
public static IAssemblyResolver CreateHotUpdateAndAOTAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
||||
{
|
||||
return new CombinedAssemblyResolver(
|
||||
CreateHotUpdateAssemblyResolver(target, hotUpdateDlls),
|
||||
CreateAOTAssemblyResolver(target)
|
||||
);
|
||||
}
|
||||
|
||||
public static string ResolveNetStandardAssemblyPath(string assemblyName)
|
||||
{
|
||||
return $"{SettingsUtil.HybridCLRDataPathInPackage}/NetStandard/{assemblyName}.dll";
|
||||
}
|
||||
|
||||
|
||||
public static List<TypeSig> CreateDefaultGenericParams(ModuleDef module, int genericParamCount)
|
||||
{
|
||||
var methodGenericParams = new List<TypeSig>();
|
||||
for (int i = 0; i < genericParamCount; i++)
|
||||
{
|
||||
methodGenericParams.Add(module.CorLibTypes.Object);
|
||||
}
|
||||
return methodGenericParams;
|
||||
}
|
||||
|
||||
public static bool IsSupportedPInvokeTypeSig(TypeSig typeSig)
|
||||
{
|
||||
typeSig = typeSig.RemovePinnedAndModifiers();
|
||||
if (typeSig.IsByRef)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
switch (typeSig.ElementType)
|
||||
{
|
||||
case ElementType.SZArray:
|
||||
case ElementType.Array:
|
||||
//case ElementType.Class:
|
||||
case ElementType.String:
|
||||
//case ElementType.Object:
|
||||
return false;
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsSupportedPInvokeMethodSignature(MethodSig methodSig)
|
||||
{
|
||||
return IsSupportedPInvokeTypeSig(methodSig.RetType) && methodSig.Params.All(p => IsSupportedPInvokeTypeSig(p));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3dbfe2e8b6a92742b18e287c5d281dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,79 @@
|
||||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.ABI;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class MethodReferenceAnalyzer
|
||||
{
|
||||
private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod;
|
||||
|
||||
private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();
|
||||
|
||||
public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod)
|
||||
{
|
||||
_onNewMethod = onNewMethod;
|
||||
}
|
||||
|
||||
public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)
|
||||
{
|
||||
var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);
|
||||
|
||||
if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
|
||||
{
|
||||
foreach (var met in effectInsts)
|
||||
{
|
||||
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
|
||||
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var body = method.Body;
|
||||
if (body == null || !body.HasInstructions)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
effectInsts = new List<IMethod>();
|
||||
foreach (var inst in body.Instructions)
|
||||
{
|
||||
if (inst.Operand == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (inst.Operand)
|
||||
{
|
||||
case IMethod met:
|
||||
{
|
||||
if (!met.IsMethod)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
|
||||
if (resolveMet == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
effectInsts.Add(met);
|
||||
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||
break;
|
||||
}
|
||||
case ITokenOperand token:
|
||||
{
|
||||
//GenericParamContext paramContext = method.HasGenericParameters || method.DeclaringType.HasGenericParameters ?
|
||||
// new GenericParamContext(method.DeclaringType, method) : default;
|
||||
//method.Module.ResolveToken(token.MDToken, paramContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_methodEffectInsts.TryAdd(method, effectInsts);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c644b0c018fb87498d69c3202439d21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class PathAssemblyResolver : AssemblyResolverBase
|
||||
{
|
||||
private readonly string[] _searchPaths;
|
||||
public PathAssemblyResolver(params string[] searchPaths)
|
||||
{
|
||||
_searchPaths = searchPaths;
|
||||
}
|
||||
|
||||
protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
|
||||
{
|
||||
foreach(var path in _searchPaths)
|
||||
{
|
||||
assemblyPath = Path.Combine(path, $"{assemblyName}.dll");
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"resolve {assemblyName} at {assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
assemblyPath = Path.Combine(path, $"{assemblyName}.dll.bytes");
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"resolve {assemblyName} at {assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assemblyPath = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 121d574bf01969444aa6619a8f6dbb4c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user