870 lines
32 KiB
C#
870 lines
32 KiB
C#
using dnlib.DotNet;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine.Assertions;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Obfuz.Utils
|
|
{
|
|
|
|
public static class MetaUtil
|
|
{
|
|
public static string GetModuleNameWithoutExt(string moduleName)
|
|
{
|
|
return Path.GetFileNameWithoutExtension(moduleName);
|
|
}
|
|
|
|
public static (string, string) SplitNamespaceAndName(string fullName)
|
|
{
|
|
int index = fullName.LastIndexOf('/');
|
|
if (index == -1)
|
|
{
|
|
int index2 = fullName.IndexOf('.');
|
|
return index2 >= 0 ? (fullName.Substring(0, index2), fullName.Substring(index2 + 1)) : ("", fullName);
|
|
}
|
|
return ("", fullName.Substring(index + 1));
|
|
}
|
|
|
|
|
|
public static TypeDef GetBaseTypeDef(TypeDef type)
|
|
{
|
|
ITypeDefOrRef baseType = type.BaseType;
|
|
if (baseType == null)
|
|
{
|
|
return null;
|
|
}
|
|
TypeDef baseTypeDef = baseType.ResolveTypeDef();
|
|
if (baseTypeDef != null)
|
|
{
|
|
return baseTypeDef;
|
|
}
|
|
if (baseType is TypeSpec baseTypeSpec)
|
|
{
|
|
GenericInstSig genericIns = baseTypeSpec.TypeSig.ToGenericInstSig();
|
|
return genericIns.GenericType.TypeDefOrRef.ResolveTypeDefThrow();
|
|
}
|
|
else
|
|
{
|
|
throw new Exception($"GetBaseTypeDef: {type} fail");
|
|
}
|
|
}
|
|
|
|
public static TypeDef GetTypeDefOrGenericTypeBaseThrowException(ITypeDefOrRef type)
|
|
{
|
|
if (type.IsTypeDef)
|
|
{
|
|
return (TypeDef)type;
|
|
}
|
|
if (type.IsTypeRef)
|
|
{
|
|
return type.ResolveTypeDefThrow();
|
|
}
|
|
if (type.IsTypeSpec)
|
|
{
|
|
GenericInstSig gis = type.TryGetGenericInstSig();
|
|
return gis.GenericType.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
}
|
|
throw new NotSupportedException($"{type}");
|
|
}
|
|
|
|
public static TypeDef GetTypeDefOrGenericTypeBaseOrNull(ITypeDefOrRef type)
|
|
{
|
|
if (type.IsTypeDef)
|
|
{
|
|
return (TypeDef)type;
|
|
}
|
|
if (type.IsTypeRef)
|
|
{
|
|
return type.ResolveTypeDefThrow();
|
|
}
|
|
if (type.IsTypeSpec)
|
|
{
|
|
GenericInstSig gis = type.TryGetGenericInstSig();
|
|
if (gis == null)
|
|
{
|
|
return null;
|
|
}
|
|
return gis.GenericType.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static TypeDef GetMemberRefTypeDefParentOrNull(IMemberRefParent parent)
|
|
{
|
|
if (parent is TypeDef typeDef)
|
|
{
|
|
return typeDef;
|
|
}
|
|
if (parent is TypeRef typeRef)
|
|
{
|
|
return typeRef.ResolveTypeDefThrow();
|
|
}
|
|
if (parent is TypeSpec typeSpec)
|
|
{
|
|
GenericInstSig gis = typeSpec.TryGetGenericInstSig();
|
|
if (gis == null)
|
|
{
|
|
return null;
|
|
}
|
|
return gis.GenericType.TypeDefOrRef.ResolveTypeDefThrow();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static bool IsInheritFromUnityObject(TypeDef typeDef)
|
|
{
|
|
TypeDef cur = typeDef;
|
|
while (true)
|
|
{
|
|
cur = GetBaseTypeDef(cur);
|
|
if (cur == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (cur.Name == "Object" && cur.Namespace == "UnityEngine" && cur.Module.Name == "UnityEngine.CoreModule.dll")
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static bool IsScriptOrSerializableType(TypeDef type)
|
|
{
|
|
if (type.ContainsGenericParameter)
|
|
{
|
|
return false;
|
|
}
|
|
if (type.IsSerializable)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
for (TypeDef parentType = GetBaseTypeDef(type); parentType != null; parentType = GetBaseTypeDef(parentType))
|
|
{
|
|
if ((parentType.Name == "MonoBehaviour" || parentType.Name == "ScriptableObject")
|
|
&& parentType.Namespace == "UnityEngine"
|
|
&& parentType.Module.Assembly.Name == "UnityEngine.CoreModule")
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool IsSerializableTypeSig(TypeSig typeSig)
|
|
{
|
|
typeSig = typeSig.RemovePinnedAndModifiers();
|
|
switch (typeSig.ElementType)
|
|
{
|
|
case ElementType.Boolean:
|
|
case ElementType.Char:
|
|
case ElementType.I1:
|
|
case ElementType.U1:
|
|
case ElementType.I2:
|
|
case ElementType.U2:
|
|
case ElementType.I4:
|
|
case ElementType.U4:
|
|
case ElementType.I8:
|
|
case ElementType.U8:
|
|
case ElementType.R4:
|
|
case ElementType.R8:
|
|
case ElementType.String:
|
|
return true;
|
|
case ElementType.Class:
|
|
return IsScriptOrSerializableType(typeSig.ToTypeDefOrRef().ResolveTypeDefThrow());
|
|
case ElementType.ValueType:
|
|
{
|
|
TypeDef typeDef = typeSig.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
if (typeDef.IsEnum)
|
|
{
|
|
return true;
|
|
}
|
|
return typeDef.IsSerializable;
|
|
}
|
|
case ElementType.GenericInst:
|
|
{
|
|
GenericInstSig genericIns = typeSig.ToGenericInstSig();
|
|
TypeDef typeDef = genericIns.GenericType.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
return typeDef.FullName == "System.Collections.Generic.List`1" && IsSerializableTypeSig(genericIns.GenericArguments[0]);
|
|
}
|
|
case ElementType.SZArray:
|
|
{
|
|
return IsSerializableTypeSig(typeSig.RemovePinnedAndModifiers().Next);
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static bool IsSerializableField(FieldDef field)
|
|
{
|
|
if (field.IsStatic)
|
|
{
|
|
return false;
|
|
}
|
|
var fieldSig = field.FieldSig.Type;
|
|
if (field.IsPublic)
|
|
{
|
|
return IsSerializableTypeSig(fieldSig);
|
|
}
|
|
if (field.CustomAttributes.Any(c => c.TypeFullName == "UnityEngine.SerializeField"))
|
|
{
|
|
//UnityEngine.Debug.Assert(IsSerializableTypeSig(fieldSig));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool MayRenameCustomDataType(ElementType type)
|
|
{
|
|
return type == ElementType.Class || type == ElementType.ValueType || type == ElementType.Object || type == ElementType.SZArray;
|
|
}
|
|
|
|
public static TypeSig RetargetTypeRefInTypeSig(TypeSig type)
|
|
{
|
|
TypeSig next = type.Next;
|
|
TypeSig newNext = next != null ? RetargetTypeRefInTypeSig(next) : null;
|
|
if (type.IsModifier || type.IsPinned)
|
|
{
|
|
if (next == newNext)
|
|
{
|
|
return type;
|
|
}
|
|
if (type is CModReqdSig cmrs)
|
|
{
|
|
return new CModReqdSig(cmrs.Modifier, newNext);
|
|
}
|
|
if (type is CModOptSig cmos)
|
|
{
|
|
return new CModOptSig(cmos.Modifier, newNext);
|
|
}
|
|
if (type is PinnedSig ps)
|
|
{
|
|
return new PinnedSig(newNext);
|
|
}
|
|
throw new System.NotSupportedException(type.ToString());
|
|
}
|
|
switch (type.ElementType)
|
|
{
|
|
case ElementType.Ptr:
|
|
{
|
|
if (next == newNext)
|
|
{
|
|
return type;
|
|
}
|
|
return new PtrSig(newNext);
|
|
}
|
|
case ElementType.ValueType:
|
|
case ElementType.Class:
|
|
{
|
|
var vts = type as ClassOrValueTypeSig;
|
|
TypeDef typeDef = vts.TypeDefOrRef.ResolveTypeDefThrow();
|
|
if (typeDef == vts.TypeDefOrRef)
|
|
{
|
|
return type;
|
|
}
|
|
return type.IsClassSig ? (TypeSig)new ClassSig(typeDef) : new ValueTypeSig(typeDef);
|
|
}
|
|
case ElementType.Array:
|
|
{
|
|
if (next == newNext)
|
|
{
|
|
return type;
|
|
}
|
|
return new ArraySig(newNext);
|
|
}
|
|
case ElementType.SZArray:
|
|
{
|
|
if (next == newNext)
|
|
{
|
|
return type;
|
|
}
|
|
return new SZArraySig(newNext);
|
|
}
|
|
case ElementType.GenericInst:
|
|
{
|
|
var gis = type as GenericInstSig;
|
|
ClassOrValueTypeSig genericType = gis.GenericType;
|
|
ClassOrValueTypeSig newGenericType = (ClassOrValueTypeSig)RetargetTypeRefInTypeSig(genericType);
|
|
bool anyChange = genericType != newGenericType;
|
|
var genericArgs = new List<TypeSig>();
|
|
foreach (var arg in gis.GenericArguments)
|
|
{
|
|
TypeSig newArg = RetargetTypeRefInTypeSig(arg);
|
|
anyChange |= newArg != genericType;
|
|
genericArgs.Add(newArg);
|
|
}
|
|
if (!anyChange)
|
|
{
|
|
return type;
|
|
}
|
|
return new GenericInstSig(newGenericType, genericArgs);
|
|
}
|
|
case ElementType.FnPtr:
|
|
{
|
|
var fp = type as FnPtrSig;
|
|
MethodSig methodSig = fp.MethodSig;
|
|
TypeSig newReturnType = RetargetTypeRefInTypeSig(methodSig.RetType);
|
|
bool anyChange = newReturnType != methodSig.RetType;
|
|
var newArgs = new List<TypeSig>();
|
|
foreach (TypeSig arg in methodSig.Params)
|
|
{
|
|
TypeSig newArg = RetargetTypeRefInTypeSig(arg);
|
|
anyChange |= newArg != newReturnType;
|
|
}
|
|
if (!anyChange)
|
|
{
|
|
return type;
|
|
}
|
|
var newParamsAfterSentinel = new List<TypeSig>();
|
|
foreach (TypeSig arg in methodSig.ParamsAfterSentinel)
|
|
{
|
|
TypeSig newArg = RetargetTypeRefInTypeSig(arg);
|
|
anyChange |= newArg != arg;
|
|
newParamsAfterSentinel.Add(newArg);
|
|
}
|
|
|
|
var newMethodSig = new MethodSig(methodSig.CallingConvention, methodSig.GenParamCount, newReturnType, newArgs, newParamsAfterSentinel);
|
|
return new FnPtrSig(newMethodSig);
|
|
}
|
|
case ElementType.ByRef:
|
|
{
|
|
if (next == newNext)
|
|
{
|
|
return type;
|
|
}
|
|
return new ByRefSig(newNext);
|
|
}
|
|
default:
|
|
{
|
|
return type;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public static object RetargetTypeRefInTypeSigOfValue(object oldValue)
|
|
{
|
|
if (oldValue == null)
|
|
{
|
|
return null;
|
|
}
|
|
string typeName = oldValue.GetType().FullName;
|
|
if (oldValue.GetType().IsPrimitive)
|
|
{
|
|
return oldValue;
|
|
}
|
|
if (oldValue is string || oldValue is UTF8String)
|
|
{
|
|
return oldValue;
|
|
}
|
|
if (oldValue is TypeSig typeSig)
|
|
{
|
|
return RetargetTypeRefInTypeSig(typeSig);
|
|
}
|
|
if (oldValue is CAArgument caValue)
|
|
{
|
|
TypeSig newType = RetargetTypeRefInTypeSig(caValue.Type);
|
|
object newValue = RetargetTypeRefInTypeSigOfValue(caValue.Value);
|
|
if (newType != caValue.Type || newValue != caValue.Value)
|
|
{
|
|
return new CAArgument(newType, newValue);
|
|
}
|
|
return oldValue;
|
|
}
|
|
if (oldValue is List<CAArgument> oldArr)
|
|
{
|
|
bool anyChange = false;
|
|
var newArr = new List<CAArgument>();
|
|
foreach (CAArgument oldArg in oldArr)
|
|
{
|
|
if (TryRetargetTypeRefInArgument(oldArg, out var newArg))
|
|
{
|
|
anyChange = true;
|
|
newArr.Add(newArg);
|
|
}
|
|
else
|
|
{
|
|
newArr.Add(oldArg);
|
|
}
|
|
}
|
|
return anyChange ? newArr : oldArr;
|
|
}
|
|
throw new NotSupportedException($"type:{oldValue.GetType()} value:{oldValue}");
|
|
}
|
|
|
|
|
|
|
|
public static bool TryRetargetTypeRefInArgument(CAArgument oldArg, out CAArgument newArg)
|
|
{
|
|
TypeSig newType = RetargetTypeRefInTypeSig(oldArg.Type);
|
|
object newValue = RetargetTypeRefInTypeSigOfValue(oldArg.Value);
|
|
if (newType != oldArg.Type || oldArg.Value != newValue)
|
|
{
|
|
newArg = new CAArgument(newType, newValue);
|
|
return true;
|
|
}
|
|
newArg = default;
|
|
return false;
|
|
}
|
|
|
|
public static bool TryRetargetTypeRefInNamedArgument(CANamedArgument arg)
|
|
{
|
|
bool anyChange = false;
|
|
TypeSig newType = RetargetTypeRefInTypeSig(arg.Type);
|
|
if (newType != arg.Type)
|
|
{
|
|
anyChange = true;
|
|
arg.Type = newType;
|
|
}
|
|
if (TryRetargetTypeRefInArgument(arg.Argument, out var newArg))
|
|
{
|
|
arg.Argument = newArg;
|
|
anyChange = true;
|
|
}
|
|
return anyChange;
|
|
}
|
|
|
|
//public static bool ContainsContainsGenericParameter1(MethodDef method)
|
|
//{
|
|
// Assert.IsTrue(!(method.DeclaringType.ContainsGenericParameter || method.MethodSig.ContainsGenericParameter));
|
|
// return false;
|
|
//}
|
|
|
|
public static bool ContainsContainsGenericParameter1(MethodSpec methodSpec)
|
|
{
|
|
if (methodSpec.GenericInstMethodSig.ContainsGenericParameter)
|
|
{
|
|
return true;
|
|
}
|
|
IMethodDefOrRef method = methodSpec.Method;
|
|
if (method.IsMethodDef)
|
|
{
|
|
return false;// ContainsContainsGenericParameter1((MethodDef)method);
|
|
}
|
|
if (method.IsMemberRef)
|
|
{
|
|
return ContainsContainsGenericParameter1((MemberRef)method);
|
|
}
|
|
throw new Exception($"unknown method: {method}");
|
|
}
|
|
|
|
public static bool ContainsContainsGenericParameter1(MemberRef memberRef)
|
|
{
|
|
IMemberRefParent parent = memberRef.Class;
|
|
if (parent is TypeSpec typeSpec)
|
|
{
|
|
return typeSpec.ContainsGenericParameter;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool ContainsContainsGenericParameter(IMethod method)
|
|
{
|
|
Assert.IsTrue(method.IsMethod);
|
|
if (method is MethodDef methodDef)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (method is MethodSpec methodSpec)
|
|
{
|
|
return ContainsContainsGenericParameter1(methodSpec);
|
|
}
|
|
if (method is MemberRef memberRef)
|
|
{
|
|
return ContainsContainsGenericParameter1(memberRef);
|
|
}
|
|
throw new Exception($"unknown method: {method}");
|
|
}
|
|
|
|
|
|
|
|
public static TypeSig Inflate(TypeSig sig, GenericArgumentContext ctx)
|
|
{
|
|
if (!sig.ContainsGenericParameter)
|
|
{
|
|
return sig;
|
|
}
|
|
return ctx.Resolve(sig);
|
|
}
|
|
|
|
|
|
public static MethodSig InflateMethodSig(MethodSig methodSig, GenericArgumentContext genericArgumentContext)
|
|
{
|
|
var newReturnType = Inflate(methodSig.RetType, genericArgumentContext);
|
|
var newParams = new List<TypeSig>();
|
|
foreach (var param in methodSig.Params)
|
|
{
|
|
newParams.Add(Inflate(param, genericArgumentContext));
|
|
}
|
|
var newParamsAfterSentinel = new List<TypeSig>();
|
|
if (methodSig.ParamsAfterSentinel != null)
|
|
{
|
|
throw new NotSupportedException($"methodSig.ParamsAfterSentinel is not supported: {methodSig}");
|
|
//foreach (var param in methodSig.ParamsAfterSentinel)
|
|
//{
|
|
// newParamsAfterSentinel.Add(Inflate(param, genericArgumentContext));
|
|
//}
|
|
}
|
|
return new MethodSig(methodSig.CallingConvention, methodSig.GenParamCount, newReturnType, newParams, null);
|
|
}
|
|
|
|
public static IList<TypeSig> GetGenericArguments(IMemberRefParent type)
|
|
{
|
|
if (type is TypeDef typeDef)
|
|
{
|
|
return null;
|
|
}
|
|
if (type is TypeRef typeRef)
|
|
{
|
|
return null;
|
|
}
|
|
if (type is TypeSpec typeSpec)
|
|
{
|
|
GenericInstSig genericInstSig = typeSpec.TypeSig.ToGenericInstSig();
|
|
return genericInstSig?.GenericArguments;
|
|
}
|
|
throw new NotSupportedException($"type:{type}");
|
|
}
|
|
|
|
public static MethodSig GetInflatedMethodSig(IMethod method)
|
|
{
|
|
if (method is MethodDef methodDef)
|
|
{
|
|
return methodDef.MethodSig;
|
|
}
|
|
if (method is MemberRef memberRef)
|
|
{
|
|
return InflateMethodSig(memberRef.MethodSig, new GenericArgumentContext(GetGenericArguments(memberRef.Class), null));
|
|
}
|
|
if (method is MethodSpec methodSpec)
|
|
{
|
|
var genericInstMethodSig = methodSpec.GenericInstMethodSig;
|
|
if (methodSpec.Method is MethodDef methodDef2)
|
|
{
|
|
return InflateMethodSig(methodDef2.MethodSig, new GenericArgumentContext(null, genericInstMethodSig.GenericArguments));
|
|
}
|
|
if (methodSpec.Method is MemberRef memberRef2)
|
|
{
|
|
return InflateMethodSig(memberRef2.MethodSig, new GenericArgumentContext(GetGenericArguments(memberRef2.Class), genericInstMethodSig.GenericArguments));
|
|
}
|
|
|
|
}
|
|
throw new NotSupportedException($" method: {method}");
|
|
}
|
|
|
|
public static ThisArgType GetThisArgType(IMethod method)
|
|
{
|
|
if (!method.MethodSig.HasThis)
|
|
{
|
|
return ThisArgType.None;
|
|
}
|
|
if (method is MethodDef methodDef)
|
|
{
|
|
return methodDef.DeclaringType.IsValueType ? ThisArgType.ValueType : ThisArgType.Class;
|
|
}
|
|
if (method is MemberRef memberRef)
|
|
{
|
|
TypeDef typeDef = MetaUtil.GetMemberRefTypeDefParentOrNull(memberRef.Class);
|
|
if (typeDef == null)
|
|
{
|
|
return ThisArgType.Class;
|
|
}
|
|
return typeDef.IsValueType ? ThisArgType.ValueType : ThisArgType.Class;
|
|
}
|
|
if (method is MethodSpec methodSpec)
|
|
{
|
|
return GetThisArgType(methodSpec.Method);
|
|
}
|
|
throw new NotSupportedException($" method: {method}");
|
|
}
|
|
|
|
public static MethodSig ToSharedMethodSig(ICorLibTypes corTypes, MethodSig methodSig)
|
|
{
|
|
var newReturnType = methodSig.RetType;
|
|
var newParams = new List<TypeSig>();
|
|
foreach (var param in methodSig.Params)
|
|
{
|
|
newParams.Add(ToShareTypeSig(corTypes, param));
|
|
}
|
|
if (methodSig.ParamsAfterSentinel != null)
|
|
{
|
|
//foreach (var param in methodSig.ParamsAfterSentinel)
|
|
//{
|
|
// newParamsAfterSentinel.Add(ToShareTypeSig(corTypes, param));
|
|
//}
|
|
throw new NotSupportedException($"methodSig.ParamsAfterSentinel is not supported: {methodSig}");
|
|
}
|
|
return new MethodSig(methodSig.CallingConvention, methodSig.GenParamCount, newReturnType, newParams, null);
|
|
}
|
|
|
|
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 typeSig;
|
|
case ElementType.Array: return typeSig;
|
|
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;
|
|
}
|
|
// il2cpp will raise error when try to share generic value type
|
|
return typeSig;
|
|
//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 void AppendIl2CppStackTraceNameOfTypeSig(StringBuilder sb, TypeSig typeSig)
|
|
{
|
|
typeSig = typeSig.RemovePinnedAndModifiers();
|
|
|
|
switch (typeSig.ElementType)
|
|
{
|
|
case ElementType.Void: sb.Append("Void"); break;
|
|
case ElementType.Boolean: sb.Append("Boolean"); break;
|
|
case ElementType.Char: sb.Append("Char"); break;
|
|
case ElementType.I1: sb.Append("SByte"); break;
|
|
case ElementType.U1: sb.Append("Byte"); break;
|
|
case ElementType.I2: sb.Append("Int16"); break;
|
|
case ElementType.U2: sb.Append("UInt16"); break;
|
|
case ElementType.I4: sb.Append("Int32"); break;
|
|
case ElementType.U4: sb.Append("UInt32"); break;
|
|
case ElementType.I8: sb.Append("Int64"); break;
|
|
case ElementType.U8: sb.Append("UInt64"); break;
|
|
case ElementType.R4: sb.Append("Single"); break;
|
|
case ElementType.R8: sb.Append("Double"); break;
|
|
case ElementType.String: sb.Append("String"); break;
|
|
case ElementType.Ptr: AppendIl2CppStackTraceNameOfTypeSig(sb, typeSig.Next); sb.Append("*"); break;
|
|
case ElementType.ByRef: AppendIl2CppStackTraceNameOfTypeSig(sb, typeSig.Next); sb.Append("&"); break;
|
|
case ElementType.ValueType:
|
|
case ElementType.Class:
|
|
{
|
|
var classOrValueTypeSig = (ClassOrValueTypeSig)typeSig;
|
|
TypeDef typeDef = classOrValueTypeSig.TypeDefOrRef.ResolveTypeDef();
|
|
if (typeDef == null)
|
|
{
|
|
throw new Exception($"type:{classOrValueTypeSig} definition could not be found");
|
|
}
|
|
sb.Append(typeDef.Name);
|
|
break;
|
|
}
|
|
case ElementType.GenericInst:
|
|
{
|
|
var genericInstSig = (GenericInstSig)typeSig;
|
|
AppendIl2CppStackTraceNameOfTypeSig(sb, genericInstSig.GenericType);
|
|
break;
|
|
}
|
|
case ElementType.Var:
|
|
case ElementType.MVar:
|
|
{
|
|
var varSig = (GenericSig)typeSig;
|
|
sb.Append(varSig.GenericParam.Name);
|
|
break;
|
|
}
|
|
case ElementType.I: sb.Append("IntPtr"); break;
|
|
case ElementType.U: sb.Append("UIntPtr"); break;
|
|
case ElementType.FnPtr: sb.Append("IntPtr"); break;
|
|
case ElementType.Object: sb.Append("Object"); break;
|
|
case ElementType.SZArray:
|
|
{
|
|
var szArraySig = (SZArraySig)typeSig;
|
|
AppendIl2CppStackTraceNameOfTypeSig(sb, szArraySig.Next);
|
|
sb.Append("[]");
|
|
break;
|
|
}
|
|
case ElementType.Array:
|
|
{
|
|
var arraySig = (ArraySig)typeSig;
|
|
AppendIl2CppStackTraceNameOfTypeSig(sb, arraySig.Next);
|
|
sb.Append("[");
|
|
for (int i = 0; i < arraySig.Rank - 1; i++)
|
|
{
|
|
sb.Append(",");
|
|
}
|
|
sb.Append("]");
|
|
break;
|
|
}
|
|
default:
|
|
throw new NotSupportedException(typeSig.ToString());
|
|
}
|
|
}
|
|
|
|
public static TypeDef GetRootDeclaringType(TypeDef type)
|
|
{
|
|
TypeDef cur = type;
|
|
while (true)
|
|
{
|
|
TypeDef declaringType = cur.DeclaringType;
|
|
if (declaringType == null)
|
|
{
|
|
return cur;
|
|
}
|
|
cur = declaringType;
|
|
}
|
|
}
|
|
|
|
public static string CreateMethodDefIl2CppStackTraceSignature(MethodDef method)
|
|
{
|
|
var result = new StringBuilder();
|
|
TypeDef declaringType = method.DeclaringType;
|
|
|
|
string namespaze = GetRootDeclaringType(declaringType).Namespace;
|
|
if (!string.IsNullOrEmpty(namespaze))
|
|
{
|
|
result.Append(namespaze);
|
|
result.Append(".");
|
|
}
|
|
result.Append(declaringType.Name);
|
|
result.Append(":");
|
|
result.Append(method.Name);
|
|
result.Append("(");
|
|
|
|
int index = 0;
|
|
foreach (TypeSig p in method.GetParams())
|
|
{
|
|
if (index > 0)
|
|
{
|
|
result.Append(", ");
|
|
}
|
|
AppendIl2CppStackTraceNameOfTypeSig(result, p);
|
|
++index;
|
|
}
|
|
result.Append(")");
|
|
return result.ToString();
|
|
}
|
|
|
|
public static ObfuzScope? GetObfuzIgnoreScope(IHasCustomAttribute obj)
|
|
{
|
|
var ca = obj.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "Obfuz.ObfuzIgnoreAttribute");
|
|
if (ca == null)
|
|
{
|
|
return null;
|
|
}
|
|
var scope = (ObfuzScope)ca.ConstructorArguments[0].Value;
|
|
return scope;
|
|
}
|
|
|
|
public static ObfuzScope? GetSelfOrInheritObfuzIgnoreScope(TypeDef typeDef)
|
|
{
|
|
TypeDef cur = typeDef;
|
|
while (cur != null)
|
|
{
|
|
var ca = cur.CustomAttributes?.FirstOrDefault(ca => ca.AttributeType.FullName == "Obfuz.ObfuzIgnoreAttribute");
|
|
if (ca != null)
|
|
{
|
|
var scope = (ObfuzScope)ca.ConstructorArguments[0].Value;
|
|
CANamedArgument inheritByNestedTypesArg = ca.GetNamedArgument("InheritByNestedTypes", false);
|
|
bool inheritByNestedTypes = inheritByNestedTypesArg == null || (bool)inheritByNestedTypesArg.Value;
|
|
return cur == typeDef || inheritByNestedTypes ? scope : null;
|
|
}
|
|
cur = cur.DeclaringType;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
public static bool HasObfuzIgnoreScope(IHasCustomAttribute obj, ObfuzScope targetScope)
|
|
{
|
|
ObfuzScope? objScope = GetObfuzIgnoreScope(obj);
|
|
if (objScope == null)
|
|
{
|
|
return false;
|
|
}
|
|
return objScope != null && (objScope & targetScope) != 0;
|
|
}
|
|
|
|
public static bool HasSelfOrInheritObfuzIgnoreScope(IHasCustomAttribute obj, TypeDef declaringType, ObfuzScope targetScope)
|
|
{
|
|
ObfuzScope? objScope = GetObfuzIgnoreScope(obj);
|
|
if (objScope != null)
|
|
{
|
|
return (objScope & targetScope) != 0;
|
|
}
|
|
|
|
ObfuzScope? parentScope = GetSelfOrInheritObfuzIgnoreScope(declaringType);
|
|
return parentScope != null && (parentScope & targetScope) != 0;
|
|
}
|
|
|
|
public static bool HasCompilerGeneratedAttribute(IHasCustomAttribute obj)
|
|
{
|
|
return obj.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute");
|
|
}
|
|
|
|
public static bool HasEncryptFieldAttribute(IHasCustomAttribute obj)
|
|
{
|
|
return obj.CustomAttributes.Any(ca => ca.AttributeType.FullName == "Obfuz.EncryptFieldAttribute");
|
|
}
|
|
|
|
public static bool HasRuntimeInitializeOnLoadMethodAttribute(MethodDef method)
|
|
{
|
|
return method.CustomAttributes.Any(ca => ca.AttributeType.FullName == "UnityEngine.RuntimeInitializeOnLoadMethodAttribute");
|
|
}
|
|
}
|
|
}
|