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

View File

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

View File

@ -254,6 +254,62 @@ namespace Obfuz.Utils
} }
return false; 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) public static bool MayRenameCustomDataType(ElementType type)
{ {