RawImageBase.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. #pragma once
  2. #include "../CommonDef.h"
  3. #include "vm/String.h"
  4. #include "MetadataDef.h"
  5. #include "BlobReader.h"
  6. #include "MetadataUtil.h"
  7. namespace hybridclr
  8. {
  9. namespace metadata
  10. {
  11. enum class LoadImageErrorCode
  12. {
  13. OK = 0,
  14. BAD_IMAGE,
  15. NOT_IMPLEMENT,
  16. AOT_ASSEMBLY_NOT_FIND,
  17. HOMOLOGOUS_ONLY_SUPPORT_AOT_ASSEMBLY,
  18. HOMOLOGOUS_ASSEMBLY_HAS_BEEN_LOADED,
  19. INVALID_HOMOLOGOUS_MODE,
  20. PDB_BAD_FILE,
  21. };
  22. struct SectionHeader
  23. {
  24. uint32_t virtualAddressBegin;
  25. uint32_t virtualAddressEnd;
  26. uint32_t ptrRawDataRelatedToVirtualAddress;
  27. };
  28. class RawImageBase
  29. {
  30. public:
  31. RawImageBase() : _imageData(nullptr), _imageLength(0), _ptrRawDataEnd(nullptr),
  32. _streamStringHeap{}, _streamUS{}, _streamBlobHeap{}, _streamGuidHeap{}, _streamTables{},
  33. _4byteStringIndex(false), _4byteGUIDIndex(false), _4byteBlobIndex(false)
  34. {
  35. }
  36. virtual ~RawImageBase()
  37. {
  38. if (_imageData)
  39. {
  40. HYBRIDCLR_FREE((void*)_imageData);
  41. _imageData = nullptr;
  42. }
  43. }
  44. virtual LoadImageErrorCode Load(const void* imageData, size_t length);
  45. virtual LoadImageErrorCode PostLoadStreams() { return LoadImageErrorCode::OK; }
  46. virtual LoadImageErrorCode PostLoadTables() { return LoadImageErrorCode::OK; }
  47. virtual Il2CppString* GetUserStringBlogByIndex(uint32_t index) const = 0;
  48. virtual void DecryptMethodBodyIfNeed(const byte* methodBody, uint32_t methodBodySize) {}
  49. const char* GetStringFromRawIndex(StringIndex index) const
  50. {
  51. IL2CPP_ASSERT(DecodeImageIndex(index) == 0);
  52. IL2CPP_ASSERT(index >= 0 && (uint32_t)index < _streamStringHeap.size);
  53. return (const char*)(_streamStringHeap.data + index);
  54. }
  55. const byte* GetBlobFromRawIndex(StringIndex index) const
  56. {
  57. IL2CPP_ASSERT(DecodeImageIndex(index) == 0);
  58. IL2CPP_ASSERT(index == 0 || (index > 0 && (size_t)index < _streamBlobHeap.size));
  59. return _streamBlobHeap.data + index;
  60. }
  61. const uint8_t* GetFieldOrParameterDefalutValueByRawIndex(uint32_t index) const
  62. {
  63. return _imageData + index;
  64. }
  65. static BlobReader DecodeBlob(const byte* buf)
  66. {
  67. uint32_t sizeLength;
  68. uint32_t length = BlobReader::ReadCompressedUint32(buf, sizeLength);
  69. return BlobReader(buf + sizeLength, length);
  70. }
  71. BlobReader GetBlobReaderByRawIndex(uint32_t rawIndex) const
  72. {
  73. IL2CPP_ASSERT(DecodeImageIndex(rawIndex) == 0);
  74. const byte* buf = _streamBlobHeap.data + rawIndex;
  75. return DecodeBlob(buf);
  76. }
  77. uint32_t GetImageOffsetOfBlob(Il2CppTypeEnum type, uint32_t index) const
  78. {
  79. if (type != IL2CPP_TYPE_STRING)
  80. {
  81. return (uint32_t)(GetBlobReaderByRawIndex(index).GetData() - _imageData);
  82. }
  83. else
  84. {
  85. return (uint32_t)(_streamBlobHeap.data + index - _imageData);
  86. }
  87. }
  88. const byte* GetDataPtrByImageOffset(uint32_t imageOffset) const
  89. {
  90. IL2CPP_ASSERT(imageOffset < _imageLength);
  91. return _imageData + imageOffset;
  92. }
  93. uint32_t GetEntryPointToken() const
  94. {
  95. return _entryPointToken;
  96. }
  97. const Table& GetTable(TableType type) const
  98. {
  99. return _tables[(int)type];
  100. }
  101. uint32_t GetTableRowNum(TableType tableIndex) const
  102. {
  103. return _tables[(int)tableIndex].rowNum;
  104. }
  105. bool TranslateRVAToImageOffset(uint32_t rvaOffset, uint32_t& imageOffset) const
  106. {
  107. for (const SectionHeader& sh : _sections)
  108. {
  109. if (sh.virtualAddressBegin <= rvaOffset && rvaOffset < sh.virtualAddressEnd)
  110. {
  111. imageOffset = sh.ptrRawDataRelatedToVirtualAddress + rvaOffset;
  112. return true;
  113. }
  114. }
  115. return false;
  116. }
  117. LoadImageErrorCode LoadStreamHeaders(uint32_t metadataRva, uint32_t metadataSize);
  118. LoadImageErrorCode ValidateStreams();
  119. LoadImageErrorCode LoadTables();
  120. void BuildTableRowMetas();
  121. uint32_t ComputTableRowMetaDataSize(TableType tableIndex) const;
  122. uint32_t ComputStringIndexByte() const
  123. {
  124. return _4byteStringIndex ? 4 : 2;
  125. }
  126. uint32_t ComputGUIDIndexByte() const
  127. {
  128. return _4byteGUIDIndex ? 4 : 2;
  129. }
  130. uint32_t ComputBlobIndexByte() const
  131. {
  132. return _4byteBlobIndex ? 4 : 2;
  133. }
  134. uint32_t ComputTableIndexByte(TableType tableIndex) const
  135. {
  136. return _tables[(int)tableIndex].rowNum < 65536 ? 2 : 4;
  137. }
  138. uint32_t ComputIndexByte(uint32_t maxRowNum, uint32_t tagBitNum) const
  139. {
  140. return (maxRowNum << tagBitNum) < 65536 ? 2 : 4;
  141. }
  142. uint32_t ComputTableIndexByte(TableType t1, TableType t2, uint32_t tagBitNum) const
  143. {
  144. uint32_t n = GetTableRowNum(t1);
  145. n = std::max(n, GetTableRowNum(t2));
  146. return ComputIndexByte(n, tagBitNum);
  147. }
  148. uint32_t ComputTableIndexByte(TableType t1, TableType t2, TableType t3, uint32_t tagBitNum) const
  149. {
  150. uint32_t n = GetTableRowNum(t1);
  151. n = std::max(n, GetTableRowNum(t2));
  152. n = std::max(n, GetTableRowNum(t3));
  153. return ComputIndexByte(n, tagBitNum);
  154. }
  155. uint32_t ComputTableIndexByte(TableType t1, TableType t2, TableType t3, TableType t4, uint32_t tagBitNum) const
  156. {
  157. uint32_t n = GetTableRowNum(t1);
  158. n = std::max(n, GetTableRowNum(t2));
  159. n = std::max(n, GetTableRowNum(t3));
  160. n = std::max(n, GetTableRowNum(t4));
  161. return ComputIndexByte(n, tagBitNum);
  162. }
  163. uint32_t ComputTableIndexByte(TableType t1, TableType t2, TableType t3, TableType t4, TableType t5, uint32_t tagBitNum) const
  164. {
  165. uint32_t n = GetTableRowNum(t1);
  166. n = std::max(n, GetTableRowNum(t2));
  167. n = std::max(n, GetTableRowNum(t3));
  168. n = std::max(n, GetTableRowNum(t4));
  169. n = std::max(n, GetTableRowNum(t5));
  170. return ComputIndexByte(n, tagBitNum);
  171. }
  172. uint32_t ComputTableIndexByte(const TableType* ts, int num, uint32_t tagBitNum) const
  173. {
  174. uint32_t n = 0;
  175. for (int i = 0; i < num; i++)
  176. {
  177. n = std::max(n, GetTableRowNum(ts[i]));
  178. }
  179. return ComputIndexByte(n, tagBitNum);
  180. }
  181. protected:
  182. virtual LoadImageErrorCode LoadCLIHeader(uint32_t& entryPointToken, uint32_t& metadataRva, uint32_t& metadataSize) = 0;
  183. const byte* GetTableRowPtr(TableType type, uint32_t rawIndex) const
  184. {
  185. auto& tb = _tables[(int)type];
  186. IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= tb.rowNum);
  187. return tb.data + tb.rowMetaDataSize * (rawIndex - 1);
  188. }
  189. const std::vector<ColumnOffsetSize>& GetRowSchema(TableType type) const
  190. {
  191. return _tableRowMetas[(int)type];
  192. }
  193. uint32_t ReadColumn(const byte* rowPtr, const ColumnOffsetSize& columnMt) const
  194. {
  195. return ReadColumn(rowPtr, columnMt.offset, columnMt.size);
  196. }
  197. uint32_t ReadColumn(const byte* data, uint32_t offset, uint32_t size) const
  198. {
  199. IL2CPP_ASSERT(size == 2 || size == 4);
  200. return (size == 2 ? *(uint16_t*)(data + offset) : *(uint32_t*)(data + offset));
  201. }
  202. static Il2CppString* CreateUserString(const char* str, uint32_t length)
  203. {
  204. if (length == 0)
  205. {
  206. return il2cpp::vm::String::Empty();
  207. }
  208. else
  209. {
  210. IL2CPP_ASSERT(length % 2 == 1);
  211. UserStringEncoding charEncoding = (UserStringEncoding)str[length - 1];
  212. return il2cpp::vm::String::NewUtf16((const Il2CppChar*)str, (length - 1) / 2);
  213. }
  214. }
  215. public:
  216. #define TABLE_BEGIN(name, tableType) Tb##name Read##name(uint32_t rawIndex) \
  217. { \
  218. IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(tableType).rowNum); \
  219. const byte* rowPtr = GetTableRowPtr(tableType, rawIndex); \
  220. auto& rowSchema = GetRowSchema(tableType); \
  221. uint32_t __fieldIndex = 0; \
  222. Tb##name __r = {};
  223. #define __F(fieldName) const ColumnOffsetSize& col_##fieldName = rowSchema[__fieldIndex++]; \
  224. __r.fieldName = ReadColumn(rowPtr, col_##fieldName);
  225. #define TABLE_END return __r; \
  226. }
  227. #define TABLE1(name, tableType, f1) TABLE_BEGIN(name, tableType) \
  228. __F(f1) \
  229. TABLE_END
  230. #define TABLE2(name, tableType, f1, f2) TABLE_BEGIN(name, tableType) \
  231. __F(f1) \
  232. __F(f2) \
  233. TABLE_END
  234. #define TABLE3(name, tableType, f1, f2, f3) TABLE_BEGIN(name, tableType) \
  235. __F(f1) \
  236. __F(f2) \
  237. __F(f3) \
  238. TABLE_END
  239. #define TABLE4(name, tableType, f1, f2, f3, f4) TABLE_BEGIN(name, tableType) \
  240. __F(f1) \
  241. __F(f2) \
  242. __F(f3) \
  243. __F(f4) \
  244. TABLE_END
  245. #define TABLE5(name, tableType, f1, f2, f3, f4, f5) TABLE_BEGIN(name, tableType) \
  246. __F(f1) \
  247. __F(f2) \
  248. __F(f3) \
  249. __F(f4) \
  250. __F(f5) \
  251. TABLE_END
  252. #define TABLE6(name, tableType, f1, f2, f3, f4, f5, f6) TABLE_BEGIN(name, tableType) \
  253. __F(f1) \
  254. __F(f2) \
  255. __F(f3) \
  256. __F(f4) \
  257. __F(f5) \
  258. __F(f6) \
  259. TABLE_END
  260. TABLE5(Module, TableType::MODULE, generation, name, mvid, encid, encBaseId);
  261. TABLE3(TypeRef, TableType::TYPEREF, resolutionScope, typeName, typeNamespace)
  262. virtual TABLE6(TypeDef, TableType::TYPEDEF, flags, typeName, typeNamespace, extends, fieldList, methodList)
  263. TABLE1(TypeSpec, TableType::TYPESPEC, signature);
  264. TABLE3(Field, TableType::FIELD, flags, name, signature)
  265. TABLE4(GenericParam, TableType::GENERICPARAM, number, flags, owner, name)
  266. TABLE2(GenericParamConstraint, TableType::GENERICPARAMCONSTRAINT, owner, constraint)
  267. TABLE3(MemberRef, TableType::MEMBERREF, classIdx, name, signature)
  268. TABLE1(StandAloneSig, TableType::STANDALONESIG, signature)
  269. TABLE3(MethodImpl, TableType::METHODIMPL, classIdx, methodBody, methodDeclaration)
  270. TABLE2(FieldRVA, TableType::FIELDRVA, rva, field)
  271. TABLE2(FieldLayout, TableType::FIELDLAYOUT, offset, field)
  272. TABLE3(Constant, TableType::CONSTANT, type, parent, value)
  273. TABLE2(MethodSpec, TableType::METHODSPEC, method, instantiation)
  274. TABLE3(CustomAttribute, TableType::CUSTOMATTRIBUTE, parent, type, value)
  275. TABLE2(PropertyMap, TableType::PROPERTYMAP, parent, propertyList)
  276. TABLE3(Property, TableType::PROPERTY, flags, name, type)
  277. TABLE2(EventMap, TableType::EVENTMAP, parent, eventList)
  278. TABLE3(Event, TableType::EVENT, eventFlags, name, eventType)
  279. TABLE3(MethodSemantics, TableType::METHODSEMANTICS, semantics, method, association)
  280. TABLE2(NestedClass, TableType::NESTEDCLASS, nestedClass, enclosingClass)
  281. TABLE6(Method, TableType::METHOD, rva, implFlags, flags, name, signature, paramList)
  282. TABLE3(Param, TableType::PARAM, flags, sequence, name)
  283. TABLE3(ClassLayout, TableType::CLASSLAYOUT, packingSize, classSize, parent)
  284. TABLE2(InterfaceImpl, TableType::INTERFACEIMPL, classIdx, interfaceIdx)
  285. TABLE_BEGIN(Assembly, TableType::ASSEMBLY)
  286. __F(hashAlgId)
  287. __F(majorVersion)
  288. __F(minorVersion)
  289. __F(buildNumber)
  290. __F(revisionNumber)
  291. __F(flags)
  292. __F(publicKey)
  293. __F(name)
  294. __F(culture)
  295. TABLE_END
  296. TABLE_BEGIN(AssemblyRef, TableType::ASSEMBLYREF)
  297. __F(majorVersion)
  298. __F(minorVersion)
  299. __F(buildNumber)
  300. __F(revisionNumber)
  301. __F(flags)
  302. __F(publicKeyOrToken)
  303. __F(name)
  304. __F(culture)
  305. __F(hashValue)
  306. TABLE_END
  307. TABLE4(SymbolDocument, TableType::DOCUMENT, name, hashAlgorithm, hash, language)
  308. TABLE2(SymbolMethodBody, TableType::METHODBODY, document, sequencePoints)
  309. TABLE6(SymbolLocalScope, TableType::LOCALSCOPE, method, importScope, variables, constants, startOffset, length)
  310. TABLE3(SymbolLocalVariable, TableType::LOCALVARIABLE, attributes, index, name)
  311. TABLE2(SymbolConstant, TableType::LOCALCONSTANT, name, signature)
  312. TABLE2(SymbolImportScope, TableType::IMPORTSCOPE, parent, imports)
  313. TABLE2(SymbolStateMachineMethod, TableType::STATEMACHINEMETHOD, moveNextMethod, kickoffMethod)
  314. TABLE3(SymbolCustomDebugInformation, TableType::CUSTOMDEBUGINFORMATION, parent, kind, value)
  315. protected:
  316. const byte* _imageData;
  317. uint32_t _imageLength;
  318. const byte* _ptrRawDataEnd;
  319. std::vector<SectionHeader> _sections;
  320. uint32_t _entryPointToken;
  321. CliStream _streamStringHeap;
  322. CliStream _streamUS;
  323. CliStream _streamBlobHeap;
  324. CliStream _streamGuidHeap;
  325. CliStream _streamTables;
  326. bool _4byteStringIndex;
  327. bool _4byteGUIDIndex;
  328. bool _4byteBlobIndex;
  329. Table _tables[TABLE_NUM];
  330. std::vector<ColumnOffsetSize> _tableRowMetas[TABLE_NUM];
  331. };
  332. }
  333. }