修复生成的ProxyCall的this参数的Bug

backup
walon 2025-04-28 14:41:40 +08:00
parent f513b9f414
commit bcba063ff5
2 changed files with 76 additions and 4 deletions

View File

@ -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);
}
}
}

View File

@ -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);