1

我正在使用 Mono.Ceil 打包 C# 代码,以便在函数中插入代码存根。这是我的代码

对于枚举类型,即 ValueType,我使用 OpCodes.box 将其装箱为对象。如果不使用 il2cpp(形式 Unity3D)翻译成 C++ 代码,它就可以工作。

它生成不正确(var L_3 未装箱),

// System.Void ToBePatched::FuncWithEnum(ToBePatched/MyEnum)
extern Il2CppClass* ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var;
extern Il2CppClass* Exception_t1145979430_il2cpp_TypeInfo_var;
extern const MethodInfo* ToBePatched_FuncWithEnum_m3969224534_MethodInfo_var;
extern Il2CppCodeGenString* _stringLiteral880614685;
extern Il2CppCodeGenString* _stringLiteral2366206808;
extern const uint32_t ToBePatched_FuncWithEnum_m3969224534_MetadataUsageId;
extern "C"  void ToBePatched_FuncWithEnum_m3969224534 (ToBePatched_t3077132781 * __this, int32_t ___a0, const MethodInfo* method)
{
    static bool s_Il2CppMethodIntialized;
    if (!s_Il2CppMethodIntialized)
    {
        il2cpp_codegen_initialize_method (ToBePatched_FuncWithEnum_m3969224534_MetadataUsageId);
        s_Il2CppMethodIntialized = true;
    }
    ObjectU5BU5D_t3632007997* V_0 = NULL;
    Il2CppObject * V_1 = NULL;
    {
        MethodBase_t591550820 * L_0 = MethodBase_GetMethodFromHandle_m3983882276(NULL /*static, unused*/, LoadMethodToken(ToBePatched_FuncWithEnum_m3969224534_MethodInfo_var), /*hidden argument*/NULL);
        ObjectU5BU5D_t3632007997* L_1 = ((ObjectU5BU5D_t3632007997*)SZArrayNew(ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var, (uint32_t)((int32_t)1)));
        V_0 = L_1;
        ObjectU5BU5D_t3632007997* L_2 = L_1;
        int32_t L_3 = ___a0; // L_3 not boxed
        NullCheck(L_2);
        IL2CPP_ARRAY_BOUNDS_CHECK(L_2, ((int32_t)0));
        ArrayElementTypeCheck (L_2, L_3); // error here
        (L_2)->SetAt(static_cast<il2cpp_array_size_t>(((int32_t)0)), (Il2CppObject *)L_3);
        bool L_4 = LuaHotPatchLoader_Hub_m392557439(NULL /*static, unused*/, _stringLiteral880614685, L_0, __this, (&V_1), L_2, /*hidden argument*/NULL);
        if (!L_4)
        {
            goto IL_0038;
        }
    }
    {
        return;
    }

IL_0038:
    {
        Exception_t1145979430 * L_5 = (Exception_t1145979430 *)il2cpp_codegen_object_new(Exception_t1145979430_il2cpp_TypeInfo_var);
        Exception__ctor_m485833136(L_5, _stringLiteral2366206808, /*hidden argument*/NULL);
        IL2CPP_RAISE_MANAGED_EXCEPTION(L_5);
    }
}

但是对于未修补枚举的 func,它生成正确,(var L_3 boxed)

// System.Void ToBePatched::TestEnum(ToBePatched/MyEnum)
extern Il2CppClass* ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var;
extern Il2CppClass* Int32_t1448170597_il2cpp_TypeInfo_var;
extern const uint32_t ToBePatched_TestEnum_m1559027260_MetadataUsageId;
extern "C"  void ToBePatched_TestEnum_m1559027260 (ToBePatched_t3077132781 * __this, int32_t ___m0, const MethodInfo* method)
{
    static bool s_Il2CppMethodIntialized;
    if (!s_Il2CppMethodIntialized)
    {
        il2cpp_codegen_initialize_method (ToBePatched_TestEnum_m1559027260_MetadataUsageId);
        s_Il2CppMethodIntialized = true;
    }
    Il2CppObject * V_0 = NULL;
    {
        ObjectU5BU5D_t3632007997* L_0 = ((ObjectU5BU5D_t3632007997*)SZArrayNew(ObjectU5BU5D_t3632007997_il2cpp_TypeInfo_var, (uint32_t)1));
        int32_t L_1 = ___m0;
        int32_t L_2 = ((int32_t)L_1);
        Il2CppObject * L_3 = Box(Int32_t1448170597_il2cpp_TypeInfo_var, &L_2);
        NullCheck(L_0);
        IL2CPP_ARRAY_BOUNDS_CHECK(L_0, 0);
        ArrayElementTypeCheck (L_0, L_3);
        (L_0)->SetAt(static_cast<il2cpp_array_size_t>(0), (Il2CppObject *)L_3);
        ToBePatched_TestEnum2_m129206415(__this, (&V_0), L_0, /*hidden argument*/NULL);
        return;
    }
}

它们具有相同的(至少对我而言)IL 代码(IL_0013 ~ IL_001d),

.method public hidebysig 
    instance void FuncWithEnum (
        valuetype ToBePatched/MyEnum a
    ) cil managed 
{
    // Method begins at RVA 0x7ac0
    // Code size 59 (0x3b)
    .maxstack 8
    .locals (
        [0] object[],
        [1] object
    )

    IL_0000: ldstr "System.Void ToBePatched::FuncWithEnum(ToBePatched/MyEnum)"
    IL_0005: ldtoken method instance void ToBePatched::FuncWithEnum(valuetype ToBePatched/MyEnum)
    IL_000a: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
    IL_000f: ldarg.0
    IL_0010: ldloca.s 1
    IL_0012: ldc.i4.1
    IL_0013: newarr [mscorlib]System.Object
    IL_0018: dup
    IL_0019: stloc.0
    IL_001a: dup
    IL_001b: ldc.i4.0
    IL_001c: ldarg.1
    IL_001d: box ToBePatched/MyEnum
    IL_0022: stelem.ref
    IL_0023: call bool ['Assembly-CSharp-firstpass']lua.hotpatch.LuaHotPatchLoader::Hub(string, class [mscorlib]System.Reflection.MethodBase, object, object&, object[])
    IL_0028: brfalse IL_002f

    IL_002d: nop
    IL_002e: ret

    IL_002f: nop
    IL_0030: ldstr "not patched"
    IL_0035: newobj instance void [mscorlib]System.Exception::.ctor(string)
    IL_003a: throw
} // end of method ToBePatched::FuncWithEnum

和 (IL_0004 ~ IL_000c)

.method public hidebysig 
    instance void TestEnum (
        valuetype ToBePatched/MyEnum m
    ) cil managed 
{
    // Method begins at RVA 0x7bf4
    // Code size 24 (0x18)
    .maxstack 7
    .locals init (
        [0] object
    )

    IL_0000: ldarg.0
    IL_0001: ldloca.s 0
    IL_0003: ldc.i4.1
    IL_0004: newarr [mscorlib]System.Object
    IL_0009: dup
    IL_000a: ldc.i4.0
    IL_000b: ldarg.1
    IL_000c: box [mscorlib]System.Int32
    IL_0011: stelem.ref
    IL_0012: call instance void ToBePatched::TestEnum2(object&, object[])
    IL_0017: ret
} // end of method ToBePatched::TestEnum

我想念什么?

附加信息,我发现对于其他非原始值类型(结构值),它有同样的问题,L_4 装箱为 L_5,但 L_7 没有装箱。

Il2CppObject * V_8 = NULL;
{
    MethodBase_t3461000640 * L_0 = MethodBase_GetMethodFromHandle_m3548347628(NULL /*static, unused*/, LoadMethodToken(ObjectFactory_CreateBattlePawn_m252190338_MethodInfo_var), /*hidden argument*/NULL);
    ObjectU5BU5D_t11523773* L_1 = ((ObjectU5BU5D_t11523773*)SZArrayNew(ObjectU5BU5D_t11523773_il2cpp_TypeInfo_var, (uint32_t)((int32_t)3)));
    V_7 = L_1;
    ObjectU5BU5D_t11523773* L_2 = L_1;
    int32_t L_3 = ___soldierId0;  // primitive value type
    int32_t L_4 = L_3;
    Il2CppObject * L_5 = Box(Int32_t2847414787_il2cpp_TypeInfo_var, &L_4); // boxed
    NullCheck(L_2);
    IL2CPP_ARRAY_BOUNDS_CHECK(L_2, ((int32_t)0));
    ArrayElementTypeCheck (L_2, L_5);
    (L_2)->SetAt(static_cast<il2cpp_array_size_t>(((int32_t)0)), (Il2CppObject *)L_5);
    ObjectU5BU5D_t11523773* L_6 = L_2;
    Vector3_t3525329789  L_7 = ___position1; // non-primitive value type, a struct value
    NullCheck(L_6);
    IL2CPP_ARRAY_BOUNDS_CHECK(L_6, ((int32_t)1));
    ArrayElementTypeCheck (L_6, L_7); // error here
    (L_6)->SetAt(static_cast<il2cpp_array_size_t>(((int32_t)1)), (Il2CppObject *)L_7);
4

0 回答 0