- 修复EvalStackCalculator计算Ref类型栈变量全部归结来IntPtr类型,导致il2cpp生成代码出错的bug

- 修复MethodControlFlowCalculator将box后的值类型变量类型定义为值类型的bug,正确应该是object
main
walon 2025-08-12 12:46:34 +08:00
parent 87cd3caf44
commit 0889f730fd
3 changed files with 86 additions and 18 deletions

View File

@ -124,7 +124,7 @@ namespace Obfuz.Emit
case ElementType.Ptr:
case ElementType.FnPtr:
case ElementType.ByRef:
datas.Add(new EvalDataTypeWithSig(EvalDataType.I, null));
datas.Add(new EvalDataTypeWithSig(EvalDataType.I, type));
break;
case ElementType.String:
case ElementType.Class:
@ -205,11 +205,21 @@ namespace Obfuz.Emit
datas.Add(type);
}
private void PushStackObject(List<EvalDataTypeWithSig> datas)
private void PushStackObject(List<EvalDataTypeWithSig> datas, TypeSig type)
{
datas.Add(new EvalDataTypeWithSig(EvalDataType.Ref, _method.Module.CorLibTypes.Object));
PushStack(datas, new EvalDataTypeWithSig(EvalDataType.Ref, type));
}
private void PushStackPointer(List<EvalDataTypeWithSig> datas, TypeSig type)
{
PushStack(datas, new EvalDataTypeWithSig(EvalDataType.I, type));
}
//private void PushStackObject(List<EvalDataTypeWithSig> datas)
//{
// datas.Add(new EvalDataTypeWithSig(EvalDataType.Ref, _method.Module.CorLibTypes.Object));
//}
private EvalDataType CalcBasicBinOpRetType(EvalDataType op1, EvalDataType op2)
{
switch (op1)
@ -282,7 +292,7 @@ namespace Obfuz.Emit
var inputStackDatas = _blockEvalStackStates[bb].inputStackDatas;
if (inputStackDatas.Count == 0)
{
inputStackDatas.Add(new EvalDataTypeWithSig(EvalDataType.Ref, handler.CatchType.ToTypeSig()));
PushStackObject(inputStackDatas, handler.CatchType.ToTypeSig());
}
}
if (handler.IsCatch || handler.IsFilter)
@ -291,7 +301,7 @@ namespace Obfuz.Emit
var inputStackDatas = _blockEvalStackStates[bb].inputStackDatas;
if (inputStackDatas.Count == 0)
{
inputStackDatas.Add(new EvalDataTypeWithSig(EvalDataType.Ref, handler.CatchType.ToTypeSig()));
PushStackObject(inputStackDatas, handler.CatchType.ToTypeSig());
}
}
}
@ -375,7 +385,7 @@ namespace Obfuz.Emit
}
case Code.Ldnull:
{
PushStackObject(newPushedDatas);
PushStackObject(newPushedDatas, corLibTypes.Object);
break;
}
case Code.Ldc_I4_M1:
@ -518,7 +528,7 @@ namespace Obfuz.Emit
case Code.Ldind_Ref:
{
Assert.IsTrue(stackSize > 0);
PushStackObject(newPushedDatas);
PushStackObject(newPushedDatas, stackDatas[stackSize - 1].typeSig?.RemovePinnedAndModifiers().Next ?? corLibTypes.Object);
break;
}
case Code.Ldind_R4:
@ -701,7 +711,7 @@ namespace Obfuz.Emit
}
case Code.Ldstr:
{
PushStack(newPushedDatas, new EvalDataTypeWithSig(EvalDataType.Ref, corLibTypes.String));
PushStackObject(newPushedDatas, corLibTypes.String);
break;
}
case Code.Newobj:
@ -714,22 +724,22 @@ namespace Obfuz.Emit
{
Assert.IsTrue(stackSize > 0);
var obj = stackDatas[stackSize - 1];
Assert.IsTrue(obj.type == EvalDataType.Ref);
PushStack(newPushedDatas, new EvalDataTypeWithSig(EvalDataType.Ref, ((ITypeDefOrRef)inst.Operand).ToTypeSig()));
//Assert.IsTrue(obj.type == EvalDataType.Ref);
PushStackObject(newPushedDatas, ((ITypeDefOrRef)inst.Operand).ToTypeSig());
break;
}
case Code.Isinst:
{
Assert.IsTrue(stackSize > 0);
var obj = stackDatas[stackSize - 1];
Assert.IsTrue(obj.type == EvalDataType.Ref);
PushStack(newPushedDatas, new EvalDataTypeWithSig(EvalDataType.Ref, ((ITypeDefOrRef)inst.Operand).ToTypeSig()));
//Assert.IsTrue(obj.type == EvalDataType.Ref);
PushStackObject(newPushedDatas, ((ITypeDefOrRef)inst.Operand).ToTypeSig());
break;
}
case Code.Unbox:
{
Assert.IsTrue(stackSize > 0);
PushStack(newPushedDatas, EvalDataType.I);
PushStackPointer(newPushedDatas, corLibTypes.IntPtr);
break;
}
case Code.Unbox_Any:
@ -741,7 +751,8 @@ namespace Obfuz.Emit
case Code.Box:
{
Assert.IsTrue(stackSize > 0);
PushStackObject(newPushedDatas);
//PushStack(newPushedDatas, (ITypeDefOrRef)inst.Operand);
PushStackObject(newPushedDatas, ((ITypeDefOrRef)inst.Operand).ToTypeSig());
break;
}
case Code.Throw:
@ -829,7 +840,7 @@ namespace Obfuz.Emit
case Code.Ldelem_Ref:
{
Assert.IsTrue(stackSize >= 2);
PushStackObject(newPushedDatas);
PushStackObject(newPushedDatas, stackDatas[stackSize - 2].typeSig.RemovePinnedAndModifiers().Next ?? corLibTypes.Object);
break;
}
case Code.Ldelem:

View File

@ -34,15 +34,16 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
private TypeSig GetLocalTypeSig(ICorLibTypes corLibTypes, EvalDataTypeWithSig type)
{
TypeSig typeSig = type.typeSig;
switch (type.type)
{
case EvalDataType.Int32: return corLibTypes.Int32;
case EvalDataType.Int64: return corLibTypes.Int64;
case EvalDataType.Float: return corLibTypes.Single;
case EvalDataType.Double: return corLibTypes.Double;
case EvalDataType.I: return corLibTypes.IntPtr;
case EvalDataType.Ref: Assert.IsNotNull(type.typeSig); return type.typeSig;
case EvalDataType.ValueType: Assert.IsNotNull(type.typeSig); return type.typeSig;
case EvalDataType.I: return typeSig ?? corLibTypes.IntPtr;
case EvalDataType.Ref: return typeSig == null || MetaUtil.IsValueType(typeSig) ? corLibTypes.Object : typeSig;
case EvalDataType.ValueType: Assert.IsNotNull(typeSig); return typeSig;
case EvalDataType.Token: throw new System.NotSupportedException("Token type is not supported in BasicBlockInputOutputArguments");
default: throw new System.NotSupportedException("not supported EvalDataType");
}

View File

@ -254,6 +254,62 @@ namespace Obfuz.Utils
}
return false;
}
public static bool IsValueType(TypeSig typeSig)
{
var a = typeSig.RemovePinnedAndModifiers();
switch (a.ElementType)
{
case ElementType.Void: return false;
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: return true;
case ElementType.String: return true;
case ElementType.TypedByRef: return false;
case ElementType.I: return true;
case ElementType.U: return true;
case ElementType.Object: return false;
case ElementType.Sentinel: return false;
case ElementType.Ptr: return true;
case ElementType.ByRef: return true;
case ElementType.SZArray: return false;
case ElementType.Array: return false;
case ElementType.ValueType:
{
return true;
}
case ElementType.Var:
case ElementType.MVar: return true;
case ElementType.Class: return false;
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 true;
}
return typeDef.IsValueType;
}
case ElementType.FnPtr: return true;
case ElementType.ValueArray: return true;
case ElementType.Module: return false;
default:
throw new NotSupportedException(typeSig.ToString());
}
}
public static bool MayRenameCustomDataType(ElementType type)
{