#include "MetadataUtil.h"
|
|
#include "vm/GlobalMetadata.h"
|
#include "vm/GlobalMetadataFileInternals.h"
|
#include "vm/Type.h"
|
#include "vm/GlobalMetadata.h"
|
#include "vm/Class.h"
|
#include "metadata/Il2CppTypeCompare.h"
|
#include "metadata/GenericMetadata.h"
|
|
#include "Image.h"
|
|
namespace hybridclr
|
{
|
namespace metadata
|
{
|
const uint32_t kMetadataImageIndexExtraShiftBitsArr[4] =
|
{
|
kMetadataImageIndexExtraShiftBitsA,
|
kMetadataImageIndexExtraShiftBitsB,
|
kMetadataImageIndexExtraShiftBitsC,
|
kMetadataImageIndexExtraShiftBitsD,
|
};
|
|
const uint32_t kMetadataIndexMaskArr[4] =
|
{
|
kMetadataIndexMaskA,
|
kMetadataIndexMaskB,
|
kMetadataIndexMaskC,
|
kMetadataIndexMaskD,
|
};
|
|
|
uint32_t GetNotZeroBitCount(uint64_t x)
|
{
|
uint32_t count = 0;
|
for (int i = 0; i < 64; i++)
|
{
|
if (x & ((uint64_t)1 << i))
|
{
|
++count;
|
}
|
}
|
return count;
|
}
|
|
int32_t GetTypeValueSize(const Il2CppType* type)
|
{
|
if (type->byref)
|
{
|
return PTR_SIZE;
|
}
|
switch (type->type)
|
{
|
case IL2CPP_TYPE_BOOLEAN:
|
case IL2CPP_TYPE_I1:
|
case IL2CPP_TYPE_U1:
|
return 1;
|
case IL2CPP_TYPE_CHAR:
|
case IL2CPP_TYPE_I2:
|
case IL2CPP_TYPE_U2:
|
return 2;
|
case IL2CPP_TYPE_I4:
|
case IL2CPP_TYPE_U4:
|
case IL2CPP_TYPE_R4:
|
return 4;
|
case IL2CPP_TYPE_I8:
|
case IL2CPP_TYPE_U8:
|
case IL2CPP_TYPE_R8:
|
return 8;
|
case IL2CPP_TYPE_I:
|
case IL2CPP_TYPE_U:
|
case IL2CPP_TYPE_FNPTR:
|
case IL2CPP_TYPE_PTR:
|
case IL2CPP_TYPE_BYREF:
|
case IL2CPP_TYPE_STRING:
|
case IL2CPP_TYPE_ARRAY:
|
case IL2CPP_TYPE_SZARRAY:
|
case IL2CPP_TYPE_OBJECT:
|
return PTR_SIZE;
|
case IL2CPP_TYPE_TYPEDBYREF:
|
return sizeof(Il2CppTypedRef);
|
case IL2CPP_TYPE_CLASS:
|
{
|
IL2CPP_ASSERT(!IS_CLASS_VALUE_TYPE(il2cpp::vm::Class::FromIl2CppType(type)));
|
return PTR_SIZE;
|
}
|
case IL2CPP_TYPE_VALUETYPE:
|
{
|
Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
|
IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
|
return il2cpp::vm::Class::GetValueSize(klass, nullptr);
|
}
|
case IL2CPP_TYPE_GENERICINST:
|
{
|
Il2CppGenericClass* genericClass = type->data.generic_class;
|
if (genericClass->type->type == IL2CPP_TYPE_CLASS)
|
{
|
IL2CPP_ASSERT(!IS_CLASS_VALUE_TYPE(il2cpp::vm::Class::FromIl2CppType(type)));
|
return PTR_SIZE;
|
}
|
else
|
{
|
Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
|
IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
|
return il2cpp::vm::Class::GetValueSize(klass, nullptr);
|
}
|
}
|
default:
|
{
|
TEMP_FORMAT(errMsg, "GetTypeValueSize unknown type:%d", (int)type->type);
|
RaiseExecutionEngineException(errMsg);
|
return -1;
|
}
|
}
|
}
|
|
bool IsValueType(const Il2CppType* type)
|
{
|
switch (type->type)
|
{
|
case IL2CPP_TYPE_BOOLEAN:
|
case IL2CPP_TYPE_I1:
|
case IL2CPP_TYPE_U1:
|
case IL2CPP_TYPE_CHAR:
|
case IL2CPP_TYPE_I2:
|
case IL2CPP_TYPE_U2:
|
case IL2CPP_TYPE_I4:
|
case IL2CPP_TYPE_U4:
|
case IL2CPP_TYPE_R4:
|
case IL2CPP_TYPE_I8:
|
case IL2CPP_TYPE_U8:
|
case IL2CPP_TYPE_R8:
|
case IL2CPP_TYPE_I:
|
case IL2CPP_TYPE_U:
|
case IL2CPP_TYPE_TYPEDBYREF:
|
case IL2CPP_TYPE_VALUETYPE: return true;
|
case IL2CPP_TYPE_GENERICINST: return type->data.generic_class->type->type == IL2CPP_TYPE_VALUETYPE;
|
default: return false;
|
}
|
}
|
|
bool IsTypeSameByTypeIndex(TypeIndex t1, TypeIndex t2)
|
{
|
const Il2CppType* srcParamType = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(t1);
|
IL2CPP_ASSERT(srcParamType);
|
const Il2CppType* dstParamType = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(t2);
|
IL2CPP_ASSERT(dstParamType);
|
return il2cpp::metadata::Il2CppTypeEqualityComparer::AreEqual(srcParamType, dstParamType);
|
}
|
|
bool IsTypeEqual(const Il2CppType* t1, const Il2CppType* t2)
|
{
|
return il2cpp::metadata::Il2CppTypeEqualityComparer::AreEqual(t1, t2);
|
}
|
|
bool IsTypeGenericCompatible(const Il2CppType* typeTo, const Il2CppType* typeFrom)
|
{
|
if (typeTo->type != typeFrom->type)
|
{
|
return false;
|
}
|
switch (typeTo->type)
|
{
|
case IL2CPP_TYPE_VALUETYPE:
|
{
|
Il2CppClass* klass1 = il2cpp::vm::Class::FromIl2CppType(typeTo);
|
Il2CppClass* klass2 = il2cpp::vm::Class::FromIl2CppType(typeFrom);
|
return klass1->instance_size == klass2->instance_size;
|
}
|
case IL2CPP_TYPE_CLASS:
|
{
|
Il2CppClass* klass1 = il2cpp::vm::Class::FromIl2CppType(typeTo);
|
Il2CppClass* klass2 = il2cpp::vm::Class::FromIl2CppType(typeFrom);
|
return il2cpp::vm::Class::IsAssignableFrom(klass1, klass2);
|
}
|
case IL2CPP_TYPE_GENERICINST:
|
{
|
Il2CppClass* klass1 = il2cpp::vm::Class::FromIl2CppType(typeTo);
|
Il2CppClass* klass2 = il2cpp::vm::Class::FromIl2CppType(typeFrom);
|
if (IS_CLASS_VALUE_TYPE(klass1) != IS_CLASS_VALUE_TYPE(klass2))
|
{
|
return false;
|
}
|
if (IS_CLASS_VALUE_TYPE(klass1))
|
{
|
return klass1->instance_size == klass2->instance_size;
|
}
|
else
|
{
|
return il2cpp::vm::Class::IsAssignableFrom(klass1, klass2);
|
}
|
break;
|
}
|
default: return true;
|
}
|
return true;
|
}
|
|
const Il2CppType* TryInflateIfNeed(const Il2CppType* selfType, const Il2CppGenericContext* genericContext, bool inflateMethodVars)
|
{
|
// FIXME mEMORY LEAK
|
return genericContext ? il2cpp::metadata::GenericMetadata::InflateIfNeeded(selfType, genericContext, inflateMethodVars) : selfType;
|
}
|
|
const Il2CppType* TryInflateIfNeed(const Il2CppType* containerType, const Il2CppType* selfType)
|
{
|
if (IsGenericIns(containerType) /* && IsGenericIns(selfType)*/)
|
{
|
// TOTO memory leak
|
return il2cpp::metadata::GenericMetadata::InflateIfNeeded(selfType, &containerType->data.generic_class->context, true);
|
}
|
else
|
{
|
return selfType;
|
}
|
}
|
|
bool IsSameOverrideType(const Il2CppType* t1, const Il2CppType* t2)
|
{
|
if (t1->type != t2->type)
|
{
|
return false;
|
}
|
|
if (t1->byref != t2->byref)
|
{
|
return false;
|
}
|
|
switch (t1->type)
|
{
|
case IL2CPP_TYPE_VALUETYPE:
|
case IL2CPP_TYPE_CLASS:
|
return t1->data.typeHandle == t2->data.typeHandle;
|
case IL2CPP_TYPE_PTR:
|
case IL2CPP_TYPE_SZARRAY:
|
return IsSameOverrideType(t1->data.type, t2->data.type);
|
|
case IL2CPP_TYPE_ARRAY:
|
{
|
if (t1->data.array->rank < t2->data.array->rank)
|
{
|
return false;
|
}
|
return IsSameOverrideType(t1->data.array->etype, t2->data.array->etype);
|
}
|
case IL2CPP_TYPE_GENERICINST:
|
{
|
const Il2CppGenericInst* i1 = t1->data.generic_class->context.class_inst;
|
const Il2CppGenericInst* i2 = t2->data.generic_class->context.class_inst;
|
|
// this happens when maximum generic recursion is hit
|
if (i1 == NULL || i2 == NULL)
|
{
|
return i1 == i2;
|
}
|
|
if (i1->type_argc != i2->type_argc)
|
return false;
|
|
if (!IsSameOverrideType(t1->data.generic_class->type, t2->data.generic_class->type))
|
return false;
|
|
/* FIXME: we should probably just compare the instance pointers directly. */
|
for (uint32_t i = 0; i < i1->type_argc; ++i)
|
{
|
if (!IsSameOverrideType(i1->type_argv[i], i2->type_argv[i]))
|
{
|
return false;
|
}
|
}
|
|
return true;
|
}
|
case IL2CPP_TYPE_VAR:
|
{
|
return t1->data.genericParameterHandle == t2->data.genericParameterHandle;
|
}
|
case IL2CPP_TYPE_MVAR:
|
{
|
const Il2CppGenericParameter* gp1 = (const Il2CppGenericParameter*)t1->data.genericParameterHandle;
|
const Il2CppGenericParameter* gp2 = (const Il2CppGenericParameter*)t2->data.genericParameterHandle;
|
return gp1->num == gp2->num;
|
}
|
default:
|
return true;
|
}
|
RaiseExecutionEngineException("");
|
return false;
|
}
|
|
static bool IsGenericMethodSameGenericParamCount(const Il2CppMethodDefinition* method1, const Il2CppMethodDefinition* method2)
|
{
|
if (method1->genericContainerIndex == kGenericContainerIndexInvalid)
|
{
|
return method2->genericContainerIndex == kGenericContainerIndexInvalid;
|
}
|
else
|
{
|
if (method2->genericContainerIndex == kGenericContainerIndexInvalid)
|
{
|
return false;
|
}
|
else
|
{
|
Il2CppGenericContainer* genericContainer1 = (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(method1->genericContainerIndex);
|
Il2CppGenericContainer* genericContainer2 = (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(method2->genericContainerIndex);
|
return genericContainer1->type_argc == genericContainer2->type_argc;
|
}
|
}
|
}
|
|
bool IsOverrideMethodIgnoreName(const Il2CppType* type1, const Il2CppMethodDefinition* methodDef1, const Il2CppType* type2, const Il2CppMethodDefinition* methodDef2)
|
{
|
if (methodDef1->parameterCount != methodDef2->parameterCount)
|
{
|
return false;
|
}
|
if (!IsGenericMethodSameGenericParamCount(methodDef1, methodDef2))
|
{
|
return false;
|
}
|
|
const Il2CppType* returnType1 = TryInflateIfNeed(type1, il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(methodDef1->returnType));
|
const Il2CppType* returnType2 = TryInflateIfNeed(type2, il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(methodDef2->returnType));
|
|
|
if (!IsSameOverrideType(returnType1, returnType2))
|
{
|
return false;
|
}
|
|
for (uint32_t i = 0; i < methodDef1->parameterCount; i++)
|
{
|
const Il2CppParameterDefinition* srcParam = (const Il2CppParameterDefinition*)il2cpp::vm::GlobalMetadata::GetParameterDefinitionFromIndex(methodDef1, methodDef1->parameterStart + i);
|
IL2CPP_ASSERT(srcParam);
|
const Il2CppParameterDefinition* dstParam = (const Il2CppParameterDefinition*)il2cpp::vm::GlobalMetadata::GetParameterDefinitionFromIndex(methodDef2, methodDef2->parameterStart + i);
|
IL2CPP_ASSERT(dstParam);
|
|
const Il2CppType* paramType1 = TryInflateIfNeed(type1, il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(srcParam->typeIndex));
|
const Il2CppType* paramType2 = TryInflateIfNeed(type2, il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(dstParam->typeIndex));
|
|
if (!IsSameOverrideType(paramType1, paramType2))
|
{
|
return false;
|
}
|
}
|
return true;
|
}
|
|
bool IsOverrideMethod(const Il2CppType* type1, const Il2CppMethodDefinition* methodDef1, const Il2CppType* type2, const Il2CppMethodDefinition* methodDef2)
|
{
|
const char* name1 = il2cpp::vm::GlobalMetadata::GetStringFromIndex(methodDef1->nameIndex);
|
const char* name2 = il2cpp::vm::GlobalMetadata::GetStringFromIndex(methodDef2->nameIndex);
|
if (std::strcmp(name1, name2))
|
{
|
return false;
|
}
|
return IsOverrideMethodIgnoreName(type1, methodDef1, type2, methodDef2);
|
}
|
|
bool IsMatchSigType(const Il2CppType* dstType, const Il2CppType* sigType, const Il2CppGenericContainer* klassGenericContainer, const Il2CppGenericContainer* methodGenericContainer)
|
{
|
if (dstType->type != sigType->type)
|
{
|
return false;
|
}
|
|
if (dstType->byref != sigType->byref)
|
{
|
return false;
|
}
|
|
switch (dstType->type)
|
{
|
case IL2CPP_TYPE_VALUETYPE:
|
case IL2CPP_TYPE_CLASS:
|
return dstType->data.typeHandle == sigType->data.typeHandle;
|
case IL2CPP_TYPE_PTR:
|
case IL2CPP_TYPE_SZARRAY:
|
return IsMatchSigType(dstType->data.type, sigType->data.type, klassGenericContainer, methodGenericContainer);
|
|
case IL2CPP_TYPE_ARRAY:
|
{
|
if (dstType->data.array->rank < sigType->data.array->rank)
|
{
|
return false;
|
}
|
return IsMatchSigType(dstType->data.array->etype, sigType->data.array->etype, klassGenericContainer, methodGenericContainer);
|
}
|
case IL2CPP_TYPE_GENERICINST:
|
{
|
const Il2CppGenericInst* i1 = dstType->data.generic_class->context.class_inst;
|
const Il2CppGenericInst* i2 = sigType->data.generic_class->context.class_inst;
|
|
// this happens when maximum generic recursion is hit
|
if (i1 == NULL || i2 == NULL)
|
{
|
return i1 == i2;
|
}
|
|
if (i1->type_argc != i2->type_argc)
|
return false;
|
|
if (!IsMatchSigType(dstType->data.generic_class->type, sigType->data.generic_class->type, klassGenericContainer, methodGenericContainer))
|
return false;
|
|
/* FIXME: we should probably just compare the instance pointers directly. */
|
for (uint32_t i = 0; i < i1->type_argc; ++i)
|
{
|
if (!IsMatchSigType(i1->type_argv[i], i2->type_argv[i], klassGenericContainer, methodGenericContainer))
|
{
|
return false;
|
}
|
}
|
|
return true;
|
}
|
case IL2CPP_TYPE_VAR:
|
{
|
if ((int32_t)sigType->data.__genericParameterIndex >= klassGenericContainer->type_argc)
|
{
|
return false;
|
}
|
Il2CppMetadataGenericParameterHandle sigGph = il2cpp::vm::GlobalMetadata::GetGenericParameterFromIndex(
|
(Il2CppMetadataGenericContainerHandle)klassGenericContainer, sigType->data.__genericParameterIndex);
|
return dstType->data.genericParameterHandle == sigGph;
|
}
|
case IL2CPP_TYPE_MVAR:
|
{
|
if ((int32_t)sigType->data.__genericParameterIndex >= methodGenericContainer->type_argc)
|
{
|
return false;
|
}
|
Il2CppMetadataGenericParameterHandle sigGph = il2cpp::vm::GlobalMetadata::GetGenericParameterFromIndex(
|
(Il2CppMetadataGenericContainerHandle)methodGenericContainer, sigType->data.__genericParameterIndex);
|
return dstType->data.genericParameterHandle == sigGph;
|
}
|
default:
|
return true;
|
}
|
RaiseExecutionEngineException("");
|
return false;
|
}
|
|
bool IsMatchSigType(const Il2CppType* dstType, const Il2CppType* sigType, const Il2CppType** klassInstArgv, const Il2CppType** methodInstArgv)
|
{
|
if (dstType->byref != sigType->byref)
|
{
|
return false;
|
}
|
|
if (sigType->type == IL2CPP_TYPE_VAR)
|
{
|
sigType = klassInstArgv[sigType->data.__genericParameterIndex];
|
}
|
else if (sigType->type == IL2CPP_TYPE_MVAR)
|
{
|
sigType = methodInstArgv[sigType->data.__genericParameterIndex];
|
}
|
|
if (dstType->type != sigType->type)
|
{
|
return false;
|
}
|
switch (sigType->type)
|
{
|
case IL2CPP_TYPE_VALUETYPE:
|
case IL2CPP_TYPE_CLASS:
|
return dstType->data.typeHandle == sigType->data.typeHandle;
|
case IL2CPP_TYPE_PTR:
|
case IL2CPP_TYPE_SZARRAY:
|
return IsMatchSigType(dstType->data.type, sigType->data.type, klassInstArgv, methodInstArgv);
|
|
case IL2CPP_TYPE_ARRAY:
|
{
|
if (dstType->data.array->rank < sigType->data.array->rank)
|
{
|
return false;
|
}
|
return IsMatchSigType(dstType->data.array->etype, sigType->data.array->etype, klassInstArgv, methodInstArgv);
|
}
|
case IL2CPP_TYPE_GENERICINST:
|
{
|
const Il2CppGenericInst* i1 = dstType->data.generic_class->context.class_inst;
|
const Il2CppGenericInst* i2 = sigType->data.generic_class->context.class_inst;
|
|
// this happens when maximum generic recursion is hit
|
if (i1 == NULL || i2 == NULL)
|
{
|
return i1 == i2;
|
}
|
|
if (i1->type_argc != i2->type_argc)
|
return false;
|
|
if (!IsMatchSigType(dstType->data.generic_class->type, sigType->data.generic_class->type, klassInstArgv, methodInstArgv))
|
return false;
|
|
/* FIXME: we should probably just compare the instance pointers directly. */
|
for (uint32_t i = 0; i < i1->type_argc; ++i)
|
{
|
if (!IsMatchSigType(i1->type_argv[i], i2->type_argv[i], klassInstArgv, methodInstArgv))
|
{
|
return false;
|
}
|
}
|
|
return true;
|
}
|
case IL2CPP_TYPE_VAR:
|
{
|
/*Il2CppMetadataGenericParameterHandle sigGph = il2cpp::vm::GlobalMetadata::GetGenericParameterFromIndex(
|
(Il2CppMetadataGenericContainerHandle)klassGenericContainer, sigType->data.__genericParameterIndex);
|
return dstType->data.genericParameterHandle == sigType->data.__genericParameterIndex;*/
|
RaiseNotSupportedException("");
|
break;
|
}
|
case IL2CPP_TYPE_MVAR:
|
{
|
/*Il2CppMetadataGenericParameterHandle sigGph = il2cpp::vm::GlobalMetadata::GetGenericParameterFromIndex(
|
(Il2CppMetadataGenericContainerHandle)methodGenericContainer, sigType->data.__genericParameterIndex);
|
return dstType->data.genericParameterHandle == sigGph;*/
|
RaiseNotSupportedException("");
|
break;
|
}
|
default: return true;
|
}
|
RaiseExecutionEngineException("");
|
return false;
|
}
|
|
bool IsMatchMethodSig(const Il2CppMethodDefinition* methodDef, const MethodRefSig& resolveSig, const Il2CppGenericContainer* klassGenericContainer)
|
{
|
if (methodDef->parameterCount != (uint16_t)resolveSig.params.size())
|
{
|
return false;
|
}
|
Il2CppGenericContainer* methodGenericContainer = nullptr;
|
// if generic param not match. return false
|
if (methodDef->genericContainerIndex == kGenericContainerIndexInvalid)
|
{
|
if (resolveSig.genericParamCount)
|
{
|
return false;
|
}
|
}
|
else
|
{
|
methodGenericContainer = (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(methodDef->genericContainerIndex);
|
if (resolveSig.genericParamCount != methodGenericContainer->type_argc)
|
{
|
return false;
|
}
|
}
|
|
const Il2CppType* returnType1 = &resolveSig.returnType;
|
const Il2CppType* returnType2 = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(methodDef->returnType);
|
if (!IsMatchSigType(returnType2, returnType1, klassGenericContainer, methodGenericContainer))
|
{
|
return false;
|
}
|
for (uint32_t i = 0; i < methodDef->parameterCount; i++)
|
{
|
const Il2CppType* paramType1 = &resolveSig.params[i];
|
const Il2CppParameterDefinition* dstParam = (const Il2CppParameterDefinition*)il2cpp::vm::GlobalMetadata::GetParameterDefinitionFromIndex(methodDef, methodDef->parameterStart + i);
|
IL2CPP_ASSERT(dstParam);
|
const Il2CppType* paramType2 = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(dstParam->typeIndex);
|
if (!IsMatchSigType(paramType2, paramType1, klassGenericContainer, methodGenericContainer))
|
{
|
return false;
|
}
|
}
|
return true;
|
}
|
|
|
bool IsMatchMethodSig(const MethodInfo* methodDef, const MethodRefSig& resolveSig, const Il2CppGenericContainer* klassGenericContainer)
|
{
|
if (methodDef->parameters_count != (uint16_t)resolveSig.params.size())
|
{
|
return false;
|
}
|
const Il2CppGenericContainer* methodGenericContainer = GetGenericContainer(methodDef);
|
if (methodGenericContainer)
|
{
|
if (methodGenericContainer->type_argc != resolveSig.genericParamCount)
|
{
|
return false;
|
}
|
}
|
else
|
{
|
if (resolveSig.genericParamCount)
|
{
|
return false;
|
}
|
}
|
const Il2CppType* returnType1 = &resolveSig.returnType;
|
const Il2CppType* returnType2 = methodDef->return_type;
|
if (!IsMatchSigType(returnType2, returnType1, klassGenericContainer, methodGenericContainer))
|
{
|
return false;
|
}
|
for (uint32_t i = 0; i < methodDef->parameters_count; i++)
|
{
|
const Il2CppType* paramType1 = &resolveSig.params[i];
|
const Il2CppType* paramType2 = GET_METHOD_PARAMETER_TYPE(methodDef->parameters[i]);
|
if (!IsMatchSigType(paramType2, paramType1, klassGenericContainer, methodGenericContainer))
|
{
|
return false;
|
}
|
}
|
return true;
|
}
|
|
bool IsMatchMethodSig(const MethodInfo* methodDef, const MethodRefSig& resolveSig, const Il2CppType** klassInstArgv, const Il2CppType** methodInstArgv)
|
{
|
if (methodDef->parameters_count != (uint16_t)resolveSig.params.size())
|
{
|
return false;
|
}
|
const Il2CppGenericContainer* methodGenericContainer = GetGenericContainer(methodDef);
|
if (methodGenericContainer)
|
{
|
if (methodGenericContainer->type_argc != resolveSig.genericParamCount)
|
{
|
return false;
|
}
|
}
|
else
|
{
|
if (resolveSig.genericParamCount)
|
{
|
return false;
|
}
|
}
|
const Il2CppType* returnType1 = &resolveSig.returnType;
|
const Il2CppType* returnType2 = methodDef->return_type;
|
if (!IsMatchSigType(returnType2, returnType1, klassInstArgv, methodInstArgv))
|
{
|
return false;
|
}
|
for (uint32_t i = 0; i < methodDef->parameters_count; i++)
|
{
|
const Il2CppType* paramType1 = &resolveSig.params[i];
|
const Il2CppType* paramType2 = GET_METHOD_PARAMETER_TYPE(methodDef->parameters[i]);
|
if (!IsMatchSigType(paramType2, paramType1, klassInstArgv, methodInstArgv))
|
{
|
return false;
|
}
|
}
|
return true;
|
}
|
|
|
const Il2CppMethodDefinition* ResolveMethodDefinition(const Il2CppType* type, const char* resolveMethodName, const MethodRefSig& resolveSig)
|
{
|
const Il2CppTypeDefinition* typeDef = GetUnderlyingTypeDefinition(type);
|
const Il2CppGenericContainer* klassGenericContainer = GetGenericContainerFromIl2CppType(type);
|
const char* typeName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(typeDef->nameIndex);
|
for (uint32_t i = 0; i < typeDef->method_count; i++)
|
{
|
const Il2CppMethodDefinition* methodDef = il2cpp::vm::GlobalMetadata::GetMethodDefinitionFromIndex(typeDef->methodStart + i);
|
const char* methodName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(methodDef->nameIndex);
|
if (std::strcmp(resolveMethodName, methodName) == 0 && IsMatchMethodSig(methodDef, resolveSig, klassGenericContainer))
|
{
|
return methodDef;
|
}
|
}
|
RaiseMethodNotFindException(type, resolveMethodName);
|
return nullptr;
|
}
|
|
const MethodInfo* GetMethodInfoFromMethodDef(const Il2CppType* type, const Il2CppMethodDefinition* methodDef)
|
{
|
Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
|
il2cpp::vm::Class::SetupMethods(klass);
|
void* iter = nullptr;
|
for (const MethodInfo* cur = nullptr; (cur = il2cpp::vm::Class::GetMethods(klass, &iter)) != nullptr; )
|
{
|
if (!cur->is_inflated)
|
{
|
if ((const Il2CppMethodDefinition*)cur->methodMetadataHandle == methodDef)
|
{
|
return cur;
|
}
|
}
|
else
|
{
|
if ((const Il2CppMethodDefinition*)cur->genericMethod->methodDefinition->methodMetadataHandle == methodDef)
|
{
|
return cur;
|
}
|
}
|
}
|
RaiseMethodNotFindException(type, il2cpp::vm::GlobalMetadata::GetStringFromIndex(methodDef->nameIndex));
|
return nullptr;
|
}
|
|
bool ResolveField(const Il2CppType* type, const char* resolveFieldName, Il2CppType* resolveFieldType, const Il2CppFieldDefinition*& retFieldDef)
|
{
|
const Il2CppTypeDefinition* typeDef = GetUnderlyingTypeDefinition(type);
|
const Il2CppGenericContainer* klassGenericContainer = GetGenericContainerFromIl2CppType(type);
|
for (uint16_t i = 0; i < typeDef->field_count; i++)
|
{
|
const Il2CppFieldDefinition* fieldDef = il2cpp::vm::GlobalMetadata::GetFieldDefinitionFromTypeDefAndFieldIndex(typeDef, i);
|
const char* fieldName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(fieldDef->nameIndex);
|
const Il2CppType* fieldType = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(fieldDef->typeIndex);
|
if (std::strcmp(resolveFieldName, fieldName) == 0 && IsMatchSigType(fieldType, resolveFieldType, klassGenericContainer, nullptr))
|
{
|
retFieldDef = fieldDef;
|
return true;
|
}
|
}
|
retFieldDef = nullptr;
|
return false;
|
}
|
|
const Il2CppGenericContainer* GetGenericContainerFromIl2CppType(const Il2CppType* type)
|
{
|
switch (type->type)
|
{
|
case IL2CPP_TYPE_GENERICINST:
|
{
|
return (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromGenericClass(type->data.generic_class);
|
}
|
case IL2CPP_TYPE_VALUETYPE:
|
case IL2CPP_TYPE_CLASS:
|
{
|
return (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(((Il2CppTypeDefinition*)type->data.typeHandle)->genericContainerIndex);
|
}
|
default:
|
{
|
return nullptr;
|
}
|
}
|
}
|
|
const Il2CppGenericInst* TryInflateGenericInst(const Il2CppGenericInst* inst, const Il2CppGenericContext* genericContext)
|
{
|
IL2CPP_ASSERT(inst->type_argc > 0);
|
const Il2CppType** argv = (const Il2CppType**)alloca(sizeof(Il2CppType*) * inst->type_argc);
|
for (uint32_t i = 0; i < inst->type_argc; i++)
|
{
|
argv[i] = TryInflateIfNeed(inst->type_argv[i], genericContext, true);
|
}
|
return il2cpp::vm::MetadataCache::GetGenericInst(argv, inst->type_argc);
|
}
|
}
|
}
|