#include "il2cpp-config.h" #include #include "gc/GarbageCollector.h" #include "icalls/mscorlib/System.Reflection/MonoField.h" #include "utils/StringUtils.h" #include "vm/Class.h" #include "vm/Field.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/Type.h" #include "vm/Exception.h" #include "il2cpp-class-internals.h" #include "il2cpp-tabledefs.h" #include "vm-utils/BlobReader.h" #include "hybridclr/metadata/MetadataUtil.h" using il2cpp::utils::StringUtils; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppReflectionType * MonoField::GetParentType(Il2CppReflectionField * field, bool declaring) { Il2CppClass *parent; parent = declaring ? field->field->parent : field->klass; return il2cpp::vm::Reflection::GetTypeObject(&parent->byval_arg); } int32_t MonoField::GetFieldOffset(Il2CppReflectionField * field) { return field->field->offset - sizeof(Il2CppObject); } Il2CppObject* MonoField::GetValueInternal(Il2CppReflectionField * field, Il2CppObject * obj) { return vm::Field::GetValueObject(field->field, obj); } void MonoField::SetValueInternal(Il2CppReflectionField* field, Il2CppObject* obj, Il2CppObject* value) { ::FieldInfo* fieldInfo = field->field; Il2CppClass* fieldType = vm::Class::FromIl2CppType(fieldInfo->type); vm::Class::Init(fieldType); uint8_t* fieldAddress; if (fieldInfo->type->attrs & FIELD_ATTRIBUTE_STATIC) { if (fieldInfo->offset == THREAD_STATIC_FIELD_OFFSET) { IL2CPP_NOT_IMPLEMENTED(Field::StaticSetValue); } vm::Runtime::ClassInit(fieldInfo->parent); fieldAddress = static_cast(fieldInfo->parent->static_fields) + fieldInfo->offset; } else { IL2CPP_ASSERT(obj); fieldAddress = reinterpret_cast(obj) + fieldInfo->offset; } if (fieldType->valuetype) { if (!vm::Class::IsNullable(fieldType)) { uint32_t fieldSize = vm::Class::GetInstanceSize(fieldType) - sizeof(Il2CppObject); if (value != NULL) { memcpy(fieldAddress, vm::Object::Unbox(value), fieldSize); } else { // Setting value type to null is defined to zero it out memset(fieldAddress, 0, fieldSize); } il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)fieldAddress, fieldSize); } else { Il2CppClass* nullableArg = vm::Class::GetNullableArgument(fieldType); uint32_t valueSize = vm::Class::GetInstanceSize(nullableArg) - sizeof(Il2CppObject); if (value != NULL) { memcpy(fieldAddress, vm::Object::Unbox(value), valueSize); *(fieldAddress + valueSize) = true; } else { *(fieldAddress + valueSize) = false; } il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)fieldAddress, valueSize); } } else { memcpy(fieldAddress, &value, sizeof(Il2CppObject*)); il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)fieldAddress); } } Il2CppObject* MonoField::GetRawConstantValue(Il2CppReflectionField* field) { ::FieldInfo* fieldInfo = field->field; if (!(fieldInfo->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) vm::Exception::Raise(vm::Exception::GetInvalidOperationException(NULL)); const Il2CppType* type = NULL; const char* data = vm::Class::GetFieldDefaultValue(fieldInfo, &type); bool useCompressBlobSize = hybridclr::metadata::IsInterpreterType(fieldInfo->parent); switch (type->type) { case IL2CPP_TYPE_U1: case IL2CPP_TYPE_I1: case IL2CPP_TYPE_BOOLEAN: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_CHAR: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_R4: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_I8: case IL2CPP_TYPE_R8: { Il2CppObject* obj = vm::Object::New(vm::Class::FromIl2CppType(type)); utils::BlobReader::GetConstantValueFromBlob(type->type, data, vm::Object::Unbox(obj), useCompressBlobSize); return obj; } case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_GENERICINST: { Il2CppObject* obj = NULL; utils::BlobReader::GetConstantValueFromBlob(type->type, data, &obj, useCompressBlobSize); return obj; } default: vm::Exception::Raise(vm::Exception::GetInvalidOperationException(StringUtils::Printf("Attempting to get raw constant value for field of type %d", type).c_str())); } return NULL; } int32_t MonoField::get_core_clr_security_level(Il2CppObject* _this) { IL2CPP_NOT_IMPLEMENTED_ICALL(MonoField::get_core_clr_security_level); IL2CPP_UNREACHABLE; return 0; } Il2CppObject* MonoField::ResolveType(Il2CppObject* _this) { IL2CPP_NOT_IMPLEMENTED_ICALL(MonoField::ResolveType); IL2CPP_UNREACHABLE; return NULL; } } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */