暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

BlobReader.cpp 7.1KB

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