修复生成的ProxyCall的this参数的Bug
parent
f513b9f414
commit
bcba063ff5
|
@ -56,11 +56,18 @@ namespace Obfuz.Emit
|
|||
|
||||
|
||||
const int maxProxyMethodPerDispatchMethod = 1000;
|
||||
|
||||
class CallInfo
|
||||
{
|
||||
public IMethod method;
|
||||
public bool callVir;
|
||||
}
|
||||
|
||||
class DispatchMethodInfo
|
||||
{
|
||||
public MethodDef methodDef;
|
||||
public int secret;
|
||||
public List<IMethod> methods = new List<IMethod>();
|
||||
public List<CallInfo> methods = new List<CallInfo>();
|
||||
}
|
||||
|
||||
private readonly Dictionary<MethodSig, List<DispatchMethodInfo>> _dispatchMethods = new Dictionary<MethodSig, List<DispatchMethodInfo>>(SignatureEqualityComparer.Instance);
|
||||
|
@ -100,9 +107,23 @@ namespace Obfuz.Emit
|
|||
private MethodSig CreateDispatchMethodSig(IMethod method)
|
||||
{
|
||||
MethodSig methodSig = MetaUtil.ToSharedMethodSig(_module.CorLibTypes, MetaUtil.GetInflatedMethodSig(method));
|
||||
//methodSig.Params
|
||||
switch(MetaUtil.GetThisArgType(method))
|
||||
{
|
||||
case ThisArgType.Class:
|
||||
{
|
||||
methodSig.Params.Insert(0, _module.CorLibTypes.Object);
|
||||
break;
|
||||
}
|
||||
case ThisArgType.ValueType:
|
||||
{
|
||||
methodSig.Params.Insert(0, _module.CorLibTypes.UIntPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// extra param for secret
|
||||
methodSig.Params.Add(_module.CorLibTypes.Int32);
|
||||
return methodSig;
|
||||
return MethodSig.CreateStatic(methodSig.RetType, methodSig.Params.ToArray());
|
||||
}
|
||||
|
||||
private DispatchMethodInfo GetDispatchMethod(IMethod method)
|
||||
|
@ -136,7 +157,7 @@ namespace Obfuz.Emit
|
|||
proxyMethod = methodDispatcher.methodDef,
|
||||
secret = methodDispatcher.methods.Count,
|
||||
};
|
||||
methodDispatcher.methods.Add(method);
|
||||
methodDispatcher.methods.Add(new CallInfo { method = method, callVir = callVir});
|
||||
_methodProxys.Add(key, proxyInfo);
|
||||
}
|
||||
return new ProxyCallMethodData { proxyMethod = proxyInfo.proxyMethod, secret = proxyInfo.secret };
|
||||
|
@ -154,7 +175,24 @@ namespace Obfuz.Emit
|
|||
var body = new CilBody();
|
||||
methodDef.Body = body;
|
||||
var ins = body.Instructions;
|
||||
ins.Add(Instruction.Create(OpCodes.Ret));
|
||||
|
||||
foreach (Parameter param in methodDef.Parameters)
|
||||
{
|
||||
ins.Add(Instruction.Create(OpCodes.Ldarg, param));
|
||||
}
|
||||
|
||||
var switchCases = new List<Instruction>();
|
||||
var switchInst = Instruction.Create(OpCodes.Switch, switchCases);
|
||||
ins.Add(switchInst);
|
||||
var ret = Instruction.Create(OpCodes.Ret);
|
||||
foreach (CallInfo ci in dispatchMethod.methods)
|
||||
{
|
||||
var callTargetMethod = Instruction.Create(ci.callVir ? OpCodes.Callvirt : OpCodes.Call, ci.method);
|
||||
switchCases.Add(callTargetMethod);
|
||||
ins.Add(callTargetMethod);
|
||||
ins.Add(Instruction.Create(OpCodes.Br, ret));
|
||||
}
|
||||
ins.Add(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,17 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Obfuz.Utils
|
||||
{
|
||||
public enum ThisArgType
|
||||
{
|
||||
None,
|
||||
ValueType,
|
||||
Class,
|
||||
}
|
||||
|
||||
public static class MetaUtil
|
||||
{
|
||||
public static string GetModuleNameWithoutExt(string moduleName)
|
||||
|
@ -551,6 +559,32 @@ namespace Obfuz.Utils
|
|||
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 = ToShareTypeSig(corTypes, methodSig.RetType);
|
||||
|
|
Loading…
Reference in New Issue