BlobReader.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include "il2cpp-config.h"
  2. #if !RUNTIME_TINY
  3. #include <stdint.h>
  4. #include "BlobReader.h"
  5. #include "gc/GarbageCollector.h"
  6. #include "metadata/CustomAttributeDataReader.h"
  7. #include "vm/Array.h"
  8. #include "vm/Class.h"
  9. #include "vm/Object.h"
  10. #include "vm/MetadataCache.h"
  11. #include "vm/Reflection.h"
  12. #include "vm/String.h"
  13. #include "utils/MemoryRead.h"
  14. #include "il2cpp-object-internals.h"
  15. const uint8_t kArrayTypeWithSameElements = 0;
  16. const uint8_t kArrayTypeWithDifferentElements = 1;
  17. namespace il2cpp
  18. {
  19. namespace utils
  20. {
  21. bool BlobReader::GetConstantValueFromBlob(const Il2CppImage* image, Il2CppTypeEnum type, const char* blob, void* value)
  22. {
  23. return GetConstantValueFromBlob(image, type, &blob, value, true);
  24. }
  25. bool BlobReader::GetConstantValueFromBlob(const Il2CppImage* image, Il2CppTypeEnum type, const char **blob, void *value, bool deserializeManagedObjects)
  26. {
  27. switch (type)
  28. {
  29. case IL2CPP_TYPE_BOOLEAN:
  30. case IL2CPP_TYPE_U1:
  31. case IL2CPP_TYPE_I1:
  32. *(uint8_t*)value = Read8(blob);
  33. break;
  34. case IL2CPP_TYPE_CHAR:
  35. *(Il2CppChar*)value = ReadChar(blob);
  36. break;
  37. case IL2CPP_TYPE_U2:
  38. case IL2CPP_TYPE_I2:
  39. *(uint16_t*)value = Read16(blob);
  40. break;
  41. case IL2CPP_TYPE_U4:
  42. *(uint32_t*)value = ReadCompressedUInt32(blob);
  43. break;
  44. case IL2CPP_TYPE_I4:
  45. *(int32_t*)value = ReadCompressedInt32(blob);
  46. break;
  47. case IL2CPP_TYPE_U8:
  48. case IL2CPP_TYPE_I8:
  49. *(uint64_t*)value = Read64(blob);
  50. break;
  51. case IL2CPP_TYPE_R4:
  52. *(float*)value = ReadFloat(blob);
  53. break;
  54. case IL2CPP_TYPE_R8:
  55. *(double*)value = ReadDouble(blob);
  56. break;
  57. case IL2CPP_TYPE_STRING:
  58. {
  59. *(void**)value = NULL;
  60. if (*blob != NULL)
  61. {
  62. // int32_t length followed by non-null terminated utf-8 byte stream
  63. int32_t length = ReadCompressedInt32(blob);
  64. // A length of -1 is a null string
  65. if (length != -1)
  66. {
  67. if (deserializeManagedObjects)
  68. {
  69. *(Il2CppString**)value = il2cpp::vm::String::NewLen(*blob, length);
  70. il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)value);
  71. }
  72. *blob += length;
  73. }
  74. }
  75. break;
  76. }
  77. case IL2CPP_TYPE_SZARRAY:
  78. {
  79. if (*blob == NULL)
  80. {
  81. *(void**)value = NULL;
  82. return true;
  83. }
  84. int32_t arrayLen = ReadCompressedInt32(blob);
  85. if (arrayLen == -1)
  86. {
  87. // A length of -1 is a null array
  88. *(void**)value = NULL;
  89. return true;
  90. }
  91. Il2CppClass* arrayElementClass;
  92. Il2CppTypeEnum arrayElementType = ReadEncodedTypeEnum(image, blob, &arrayElementClass);
  93. uint8_t arrayElementsAreDifferent = Read8(blob);
  94. IL2CPP_ASSERT(arrayElementClass);
  95. IL2CPP_ASSERT(arrayElementsAreDifferent != kArrayTypeWithDifferentElements || arrayElementType == IL2CPP_TYPE_OBJECT);
  96. Il2CppArray* arr = NULL;
  97. if (deserializeManagedObjects)
  98. arr = il2cpp::vm::Array::New(arrayElementClass, arrayLen);
  99. for (int32_t i = 0; i < arrayLen; i++)
  100. {
  101. Il2CppClass* elementClass = NULL;
  102. Il2CppTypeEnum elementType = arrayElementType;
  103. if (arrayElementsAreDifferent == kArrayTypeWithDifferentElements)
  104. elementType = ReadEncodedTypeEnum(image, blob, &elementClass);
  105. // Assumption: The array code is only called for custom attribute data
  106. il2cpp::metadata::CustomAttributeDataStorage dataBuffer;
  107. IL2CPP_ASSERT(arrayElementClass->element_size <= sizeof(il2cpp::metadata::CustomAttributeDataStorage));
  108. if (!GetConstantValueFromBlob(image, elementType, blob, &dataBuffer, deserializeManagedObjects))
  109. return false;
  110. if (deserializeManagedObjects)
  111. {
  112. if (elementType != arrayElementType)
  113. {
  114. IL2CPP_ASSERT(arrayElementType == IL2CPP_TYPE_OBJECT);
  115. IL2CPP_ASSERT(elementClass);
  116. il2cpp_array_setref(arr, i, il2cpp::vm::Object::Box(elementClass, &dataBuffer));
  117. }
  118. else
  119. {
  120. il2cpp_array_setrefwithsize(arr, arr->klass->element_size, i, &dataBuffer);
  121. }
  122. }
  123. }
  124. *(Il2CppArray**)value = arr;
  125. il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)value);
  126. break;
  127. }
  128. case IL2CPP_TYPE_CLASS:
  129. case IL2CPP_TYPE_OBJECT:
  130. case IL2CPP_TYPE_GENERICINST:
  131. IL2CPP_ASSERT(*blob == NULL);
  132. *(void**)value = NULL;
  133. break;
  134. case IL2CPP_TYPE_IL2CPP_TYPE_INDEX:
  135. {
  136. TypeIndex typeIndex = ReadCompressedInt32(blob);
  137. if (typeIndex == -1)
  138. {
  139. *(void**)value = NULL;
  140. }
  141. else if (deserializeManagedObjects)
  142. {
  143. Il2CppClass* klass = il2cpp::vm::MetadataCache::GetTypeInfoFromTypeIndex(image, typeIndex);
  144. *(Il2CppReflectionType**)value = il2cpp::vm::Reflection::GetTypeObject(&klass->byval_arg);
  145. il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)value);
  146. }
  147. break;
  148. }
  149. default:
  150. IL2CPP_ASSERT(0);
  151. return false;
  152. }
  153. return true;
  154. }
  155. Il2CppTypeEnum BlobReader::ReadEncodedTypeEnum(const Il2CppImage* image, const char** blob, Il2CppClass** klass)
  156. {
  157. Il2CppTypeEnum type = (Il2CppTypeEnum)Read8(blob);
  158. if (type == IL2CPP_TYPE_ENUM)
  159. {
  160. TypeIndex enumTypeIndex = ReadCompressedInt32(blob);
  161. *klass = il2cpp::vm::MetadataCache::GetTypeInfoFromTypeIndex(image, enumTypeIndex);
  162. type = il2cpp::vm::Class::GetEnumBaseType(*klass)->type;
  163. }
  164. else if (type == IL2CPP_TYPE_SZARRAY)
  165. {
  166. // Array class is good enough for this call
  167. // An array with specific element types will be created if needed
  168. *klass = il2cpp_defaults.array_class;
  169. }
  170. else
  171. {
  172. *klass = il2cpp::vm::Class::FromIl2CppTypeEnum(type);
  173. }
  174. return type;
  175. }
  176. } /* utils */
  177. } /* il2cpp */
  178. #endif