#include "SuperSetAOTHomologousImage.h"
|
|
#include "vm/MetadataLock.h"
|
#include "vm/GlobalMetadata.h"
|
#include "vm/Class.h"
|
#include "vm/Image.h"
|
#include "vm/Exception.h"
|
#include "vm/MetadataCache.h"
|
#include "metadata/GenericMetadata.h"
|
|
namespace hybridclr
|
{
|
namespace metadata
|
{
|
|
void SuperSetAOTHomologousImage::InitRuntimeMetadatas()
|
{
|
_defaultIl2CppType = il2cpp_defaults.missing_class->byval_arg;
|
|
InitTypes0();
|
InitNestedClass();
|
InitTypes1();
|
InitMethods();
|
InitFields();
|
}
|
|
void SuperSetAOTHomologousImage::InitTypes0()
|
{
|
const Table& typeDefTb = _rawImage.GetTable(TableType::TYPEDEF);
|
uint32_t typeCount = typeDefTb.rowNum;
|
_typeDefs.resize(typeCount);
|
_aotTypeIndex2TypeDefs.resize(typeCount);
|
|
Il2CppImage* image = _aotAssembly->image;
|
for (uint32_t index = 0; index < typeCount; index++)
|
{
|
SuperSetTypeDefDetail& td = _typeDefs[index];
|
uint32_t rowIndex = index + 1;
|
TbTypeDef data = _rawImage.ReadTypeDef(rowIndex);
|
|
td.inited = false;
|
td.homoParentRowIndex = 0;
|
td.homoRowIndex = rowIndex;
|
td.homoMethodStartIndex = data.methodList;
|
td.homoFieldStartIndex = data.fieldList;
|
|
td.name = _rawImage.GetStringFromRawIndex(data.typeName);
|
td.namespaze = _rawImage.GetStringFromRawIndex(data.typeNamespace);
|
td.aotTypeIndex = kInvalidIndex;
|
td.aotIl2CppType = nullptr;
|
td.aotTypeDef = nullptr;
|
}
|
}
|
|
void SuperSetAOTHomologousImage::InitNestedClass()
|
{
|
const Table& nestedClassTb = _rawImage.GetTable(TableType::NESTEDCLASS);
|
for (uint32_t i = 0; i < nestedClassTb.rowNum; i++)
|
{
|
TbNestedClass data = _rawImage.ReadNestedClass(i + 1);
|
SuperSetTypeDefDetail& nestedType = _typeDefs[data.nestedClass - 1];
|
nestedType.homoParentRowIndex = data.enclosingClass;
|
}
|
}
|
|
void SuperSetAOTHomologousImage::InitType(SuperSetTypeDefDetail& type)
|
{
|
if (type.inited)
|
{
|
return;
|
}
|
type.inited = true;
|
if (type.homoParentRowIndex)
|
{
|
SuperSetTypeDefDetail& parent = _typeDefs[type.homoParentRowIndex - 1];
|
InitType(parent);
|
const Il2CppTypeDefinition* parentTypeDef = parent.aotTypeDef;
|
if (parentTypeDef == nullptr)
|
{
|
goto labelInitDefault;
|
}
|
|
void* iter = nullptr;
|
for (const Il2CppTypeDefinition* nextTypeDef; (nextTypeDef = (const Il2CppTypeDefinition*)il2cpp::vm::GlobalMetadata::GetNestedTypes((Il2CppMetadataTypeHandle)parentTypeDef, &iter));)
|
{
|
const char* nestedTypeName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(nextTypeDef->nameIndex);
|
IL2CPP_ASSERT(nestedTypeName);
|
if (!std::strcmp(type.name, nestedTypeName))
|
{
|
type.aotTypeDef = nextTypeDef;
|
type.aotTypeIndex = nextTypeDef->byvalTypeIndex;
|
type.aotIl2CppType = il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(nextTypeDef->byvalTypeIndex);
|
type.aotKlass = il2cpp::vm::GlobalMetadata::GetTypeInfoFromHandle((Il2CppMetadataTypeHandle)nextTypeDef);
|
_aotTypeIndex2TypeDefs[il2cpp::vm::GlobalMetadata::GetIndexForTypeDefinition(type.aotKlass)] = &type;
|
return;
|
}
|
}
|
}
|
else
|
{
|
Il2CppClass* klass = il2cpp::vm::Image::ClassFromName(_aotAssembly->image, type.namespaze, type.name);
|
if (klass)
|
{
|
type.aotTypeDef = (const Il2CppTypeDefinition*)klass->typeMetadataHandle;
|
type.aotIl2CppType = &klass->byval_arg;
|
type.aotTypeIndex = type.aotTypeDef->byvalTypeIndex;
|
type.aotKlass = klass;
|
_aotTypeIndex2TypeDefs[il2cpp::vm::GlobalMetadata::GetIndexForTypeDefinition(type.aotKlass)] = &type;
|
return;
|
}
|
}
|
labelInitDefault:
|
type.aotIl2CppType = &_defaultIl2CppType;
|
//TEMP_FORMAT(msg, "type: %s::%s can't find homologous type in assembly:%s", type.namespaze, type.name, _aotAssembly->aname.name);
|
//RaiseExecutionEngineException(msg);
|
}
|
|
void SuperSetAOTHomologousImage::InitTypes1()
|
{
|
for (SuperSetTypeDefDetail& td : _typeDefs)
|
{
|
InitType(td);
|
}
|
}
|
|
static const Il2CppMethodDefinition* FindMatchMethod(const Il2CppClass* klass1, const SuperSetMethodDefDetail& method2)
|
{
|
il2cpp::vm::Class::SetupMethods(const_cast<Il2CppClass*>(klass1));
|
const Il2CppGenericContainer* klassGenContainer = klass1->is_generic ? GetGenericContainerFromIl2CppType(&klass1->byval_arg) : nullptr;
|
for (uint16_t i = 0; i < klass1->method_count; i++)
|
{
|
const MethodInfo* method1 = klass1->methods[i];
|
if (std::strcmp(method1->name, method2.name))
|
{
|
continue;
|
}
|
if (IsMatchMethodSig(method1, method2.signature, klassGenContainer))
|
{
|
return (const Il2CppMethodDefinition*)method1->methodMetadataHandle;
|
}
|
}
|
return nullptr;
|
}
|
|
void SuperSetAOTHomologousImage::InitMethods()
|
{
|
const Table& methodTb = _rawImage.GetTable(TableType::METHOD);
|
uint32_t methodCount = methodTb.rowNum;
|
_methodDefs.resize(methodCount);
|
_token2MethodDefs.resize(methodCount * 2);
|
uint32_t typeCount = (uint32_t)_typeDefs.size();
|
for (SuperSetTypeDefDetail& type : _typeDefs)
|
{
|
uint32_t nextTypeMethodStartIndex = type.homoRowIndex < typeCount ? _typeDefs[type.homoRowIndex].homoMethodStartIndex : methodCount + 1;
|
|
|
for (uint32_t i = type.homoMethodStartIndex; i < nextTypeMethodStartIndex ; i++)
|
{
|
SuperSetMethodDefDetail& method = _methodDefs[i - 1];
|
method.homoRowIndex = i;
|
TbMethod data = _rawImage.ReadMethod(i);
|
method.declaringTypeDef = type.aotTypeDef;
|
method.name = _rawImage.GetStringFromRawIndex(data.name);
|
if (type.aotTypeDef == nullptr)
|
{
|
continue;
|
}
|
method.signature.flags = data.flags;
|
BlobReader methodSigReader = _rawImage.GetBlobReaderByRawIndex(data.signature);
|
ReadMethodDefSig(methodSigReader, method.signature);
|
method.aotMethodDef = FindMatchMethod(type.aotKlass, method);
|
if (method.aotMethodDef)
|
{
|
_token2MethodDefs[method.aotMethodDef->token] = &method;
|
}
|
}
|
}
|
}
|
|
void SuperSetAOTHomologousImage::ReadMethodDefSig(BlobReader& reader, MethodRefSig& method)
|
{
|
uint8_t rawSigFlags = reader.ReadByte();
|
|
if (rawSigFlags & (uint8_t)MethodSigFlags::GENERIC)
|
{
|
//IL2CPP_ASSERT(false);
|
method.genericParamCount = reader.ReadCompressedUint32();
|
IL2CPP_ASSERT(method.genericParamCount > 0);
|
}
|
uint32_t paramCount = reader.ReadCompressedUint32();
|
//IL2CPP_ASSERT(paramCount >= methodDef.parameterCount);
|
|
method.returnType = {};
|
ReadType(reader, nullptr, nullptr, method.returnType);
|
|
int readParamNum = 0;
|
for (; reader.NonEmpty(); )
|
{
|
Il2CppType paramType = {};
|
ReadType(reader, nullptr, nullptr, paramType);
|
method.params.push_back(paramType);
|
++readParamNum;
|
}
|
IL2CPP_ASSERT(readParamNum == (int)paramCount);
|
}
|
|
|
const Il2CppFieldDefinition* FindMatchField(const Il2CppClass* klass1, const SuperSetFieldDefDetail& field2)
|
{
|
il2cpp::vm::Class::SetupFields(const_cast<Il2CppClass*>(klass1));
|
const Il2CppGenericContainer* klassGenContainer = klass1->is_generic ? GetGenericContainerFromIl2CppType(&klass1->byval_arg) : nullptr;
|
for (uint16_t i = 0; i < klass1->field_count; i++)
|
{
|
const FieldInfo* field1 = klass1->fields + i;
|
if (std::strcmp(field1->name, field2.name))
|
{
|
continue;
|
}
|
if (IsMatchSigType(field1->type, &field2.type, klassGenContainer, nullptr))
|
{
|
return il2cpp::vm::GlobalMetadata::GetFieldDefinitionFromTypeDefAndFieldIndex((const Il2CppTypeDefinition*)klass1->typeMetadataHandle, i);
|
}
|
}
|
return nullptr;
|
}
|
|
void SuperSetAOTHomologousImage::InitFields()
|
{
|
const Table& fieldTb = _rawImage.GetTable(TableType::FIELD);
|
uint32_t fieldCount = fieldTb.rowNum;
|
_fields.resize(fieldTb.rowNum);
|
|
uint32_t typeCount = (uint32_t)_typeDefs.size();
|
for (SuperSetTypeDefDetail& type : _typeDefs)
|
{
|
uint32_t nextTypeFieldStartIndex = type.homoRowIndex < typeCount ? _typeDefs[type.homoRowIndex].homoFieldStartIndex : fieldCount + 1;
|
for (uint32_t i = type.homoFieldStartIndex; i < nextTypeFieldStartIndex; i++)
|
{
|
SuperSetFieldDefDetail& field = _fields[i - 1];
|
field.homoRowIndex = i;
|
TbField data = _rawImage.ReadField(i);
|
field.name = _rawImage.GetStringFromRawIndex(data.name);
|
|
field.declaringTypeDef = type.aotTypeDef;
|
field.declaringIl2CppType = type.aotIl2CppType;
|
if (type.aotTypeDef == nullptr)
|
{
|
continue;
|
}
|
|
BlobReader br = _rawImage.GetBlobReaderByRawIndex(data.signature);
|
FieldRefSig frs;
|
ReadFieldRefSig(br, nullptr, frs);
|
frs.type.attrs = data.flags;
|
field.type = frs.type;
|
|
field.aotFieldDef = FindMatchField(type.aotKlass, field);
|
}
|
}
|
}
|
|
MethodBody* SuperSetAOTHomologousImage::GetMethodBody(uint32_t token)
|
{
|
auto it = _token2MethodDefs.find(token);
|
if (it == _token2MethodDefs.end())
|
{
|
return nullptr;
|
}
|
SuperSetMethodDefDetail* method = it->second;
|
if (!method->body)
|
{
|
uint32_t rowIndex = method->homoRowIndex;
|
TbMethod methodData = _rawImage.ReadMethod(rowIndex);
|
MethodBody* body = new (HYBRIDCLR_MALLOC_ZERO(sizeof(MethodBody))) MethodBody();
|
ReadMethodBody(*method->aotMethodDef, methodData, *body);
|
method->body = body;
|
}
|
return method->body;
|
}
|
|
const Il2CppType* SuperSetAOTHomologousImage::GetIl2CppTypeFromRawTypeDefIndex(uint32_t index)
|
{
|
IL2CPP_ASSERT((size_t)index < _typeDefs.size());
|
return _typeDefs[index].aotIl2CppType;
|
}
|
|
Il2CppGenericContainer* SuperSetAOTHomologousImage::GetGenericContainerByRawIndex(uint32_t index)
|
{
|
return (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(index);
|
}
|
|
Il2CppGenericContainer* SuperSetAOTHomologousImage::GetGenericContainerByTypeDefRawIndex(int32_t typeDefIndex)
|
{
|
auto it = _aotTypeIndex2TypeDefs.find(typeDefIndex);
|
if (it == _aotTypeIndex2TypeDefs.end())
|
{
|
return nullptr;
|
}
|
const Il2CppTypeDefinition* type = it->second->aotTypeDef;
|
if (type == nullptr)
|
{
|
return nullptr;
|
}
|
return (Il2CppGenericContainer*)il2cpp::vm::GlobalMetadata::GetGenericContainerFromIndex(type->genericContainerIndex);
|
}
|
|
const Il2CppMethodDefinition* SuperSetAOTHomologousImage::GetMethodDefinitionFromRawIndex(uint32_t index)
|
{
|
IL2CPP_ASSERT((size_t)index < _methodDefs.size());
|
SuperSetMethodDefDetail& method = _methodDefs[index];
|
const Il2CppMethodDefinition* methodDef = method.aotMethodDef;
|
if (!methodDef)
|
{
|
TEMP_FORMAT(errMsg, "method:%s rowIndex:%d not exist", method.name, method.homoRowIndex);
|
RaiseExecutionEngineException("find");
|
}
|
return methodDef;
|
}
|
|
void SuperSetAOTHomologousImage::ReadFieldRefInfoFromFieldDefToken(uint32_t rowIndex, FieldRefInfo& ret)
|
{
|
IL2CPP_ASSERT(rowIndex > 0);
|
SuperSetFieldDefDetail& fd = _fields[rowIndex - 1];
|
ret.containerType = *fd.declaringIl2CppType;
|
ret.field = fd.aotFieldDef;
|
}
|
|
void SuperSetAOTHomologousImage::ReadTypeFromResolutionScope(uint32_t scope, uint32_t typeNamespace, uint32_t typeName, Il2CppType& type)
|
{
|
TableType tokenType;
|
uint32_t rawIndex;
|
DecodeResolutionScopeCodedIndex(scope, tokenType, rawIndex);
|
switch (tokenType)
|
{
|
case TableType::MODULE:
|
{
|
if (!GetModuleIl2CppType(type, rawIndex, typeNamespace, typeName, false))
|
{
|
type = _defaultIl2CppType;
|
}
|
break;
|
}
|
case TableType::MODULEREF:
|
{
|
RaiseNotSupportedException("Image::ReadTypeFromResolutionScope not support ResolutionScore.MODULEREF");
|
break;
|
}
|
case TableType::ASSEMBLYREF:
|
{
|
TbAssemblyRef assRef = _rawImage.ReadAssemblyRef(rawIndex);
|
const Il2CppType* refType = GetIl2CppType(rawIndex, typeNamespace, typeName, false);
|
if (refType)
|
{
|
type.type = refType->type;
|
type.data = refType->data;
|
}
|
else
|
{
|
type = _defaultIl2CppType;
|
}
|
break;
|
}
|
case TableType::TYPEREF:
|
{
|
Il2CppType enClosingType = {};
|
ReadTypeFromTypeRef(rawIndex, enClosingType);
|
IL2CPP_ASSERT(typeNamespace == 0);
|
const char* name = _rawImage.GetStringFromRawIndex(typeName);
|
|
void* iter = nullptr;
|
Il2CppMetadataTypeHandle enclosingTypeDef = enClosingType.data.typeHandle;
|
if (!enclosingTypeDef)
|
{
|
//TEMP_FORMAT(errMsg, "Image::ReadTypeFromResolutionScope ReadTypeFromResolutionScope.TYPEREF enclosingType:%s", name);
|
//RaiseExecutionEngineException(errMsg);
|
type = _defaultIl2CppType;
|
break;
|
}
|
bool find = false;
|
for (const Il2CppTypeDefinition* nextTypeDef; (nextTypeDef = (const Il2CppTypeDefinition*)il2cpp::vm::GlobalMetadata::GetNestedTypes(enclosingTypeDef, &iter));)
|
{
|
const char* nestedTypeName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(nextTypeDef->nameIndex);
|
IL2CPP_ASSERT(nestedTypeName);
|
if (!std::strcmp(name, nestedTypeName))
|
{
|
GetIl2CppTypeFromTypeDefinition(nextTypeDef, type);
|
find = true;
|
break;
|
}
|
}
|
if (!find)
|
{
|
//std::string enclosingTypeName = GetKlassCStringFullName(&enClosingType);
|
//TEMP_FORMAT(errMsg, "Image::ReadTypeFromResolutionScope ReadTypeFromResolutionScope.TYPEREF fail. type:%s.%s", enclosingTypeName.c_str(), name);
|
//RaiseExecutionEngineException(errMsg);
|
type = _defaultIl2CppType;
|
break;
|
}
|
break;
|
}
|
default:
|
{
|
RaiseBadImageException("Image::ReadTypeFromResolutionScope invaild TableType");
|
}
|
}
|
IL2CPP_ASSERT(type.data.typeHandle);
|
}
|
}
|
}
|