PageRenderTime 210ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 2ms

/mono/metadata/metadata.c

https://bitbucket.org/danipen/mono
C | 6275 lines | 4101 code | 755 blank | 1419 comment | 812 complexity | bf8f29fef60437e41ff09079d207fef3 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. /*
  2. * metadata.c: Routines for accessing the metadata
  3. *
  4. * Authors:
  5. * Miguel de Icaza (miguel@ximian.com)
  6. * Paolo Molaro (lupus@ximian.com)
  7. *
  8. * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  9. * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  10. */
  11. #include <config.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <glib.h>
  16. #include "metadata.h"
  17. #include "tabledefs.h"
  18. #include "mono-endian.h"
  19. #include "cil-coff.h"
  20. #include "tokentype.h"
  21. #include "metadata-internals.h"
  22. #include "class-internals.h"
  23. #include "verify-internals.h"
  24. #include "class.h"
  25. #include "marshal.h"
  26. #include "debug-helpers.h"
  27. #include <mono/utils/mono-error-internals.h>
  28. /* Auxiliary structure used for caching inflated signatures */
  29. typedef struct {
  30. MonoMethodSignature *sig;
  31. MonoGenericContext context;
  32. } MonoInflatedMethodSignature;
  33. static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
  34. const char *ptr, const char **rptr);
  35. static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
  36. static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
  37. static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
  38. static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
  39. gboolean signature_only);
  40. static void free_generic_inst (MonoGenericInst *ginst);
  41. static void free_generic_class (MonoGenericClass *ginst);
  42. static void free_inflated_method (MonoMethodInflated *method);
  43. static void free_inflated_signature (MonoInflatedMethodSignature *sig);
  44. static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
  45. /*
  46. * This enumeration is used to describe the data types in the metadata
  47. * tables
  48. */
  49. enum {
  50. MONO_MT_END,
  51. /* Sized elements */
  52. MONO_MT_UINT32,
  53. MONO_MT_UINT16,
  54. MONO_MT_UINT8,
  55. /* Index into Blob heap */
  56. MONO_MT_BLOB_IDX,
  57. /* Index into String heap */
  58. MONO_MT_STRING_IDX,
  59. /* GUID index */
  60. MONO_MT_GUID_IDX,
  61. /* Pointer into a table */
  62. MONO_MT_TABLE_IDX,
  63. /* HasConstant:Parent pointer (Param, Field or Property) */
  64. MONO_MT_CONST_IDX,
  65. /* HasCustomAttribute index. Indexes any table except CustomAttribute */
  66. MONO_MT_HASCAT_IDX,
  67. /* CustomAttributeType encoded index */
  68. MONO_MT_CAT_IDX,
  69. /* HasDeclSecurity index: TypeDef Method or Assembly */
  70. MONO_MT_HASDEC_IDX,
  71. /* Implementation coded index: File, Export AssemblyRef */
  72. MONO_MT_IMPL_IDX,
  73. /* HasFieldMarshal coded index: Field or Param table */
  74. MONO_MT_HFM_IDX,
  75. /* MemberForwardedIndex: Field or Method */
  76. MONO_MT_MF_IDX,
  77. /* TypeDefOrRef coded index: typedef, typeref, typespec */
  78. MONO_MT_TDOR_IDX,
  79. /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
  80. MONO_MT_MRP_IDX,
  81. /* MethodDefOrRef coded index: Method or Member Ref table */
  82. MONO_MT_MDOR_IDX,
  83. /* HasSemantic coded index: Event or Property */
  84. MONO_MT_HS_IDX,
  85. /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
  86. MONO_MT_RS_IDX
  87. };
  88. const static unsigned char TableSchemas [] = {
  89. #define ASSEMBLY_SCHEMA_OFFSET 0
  90. MONO_MT_UINT32, /* "HashId" }, */
  91. MONO_MT_UINT16, /* "Major" }, */
  92. MONO_MT_UINT16, /* "Minor" }, */
  93. MONO_MT_UINT16, /* "BuildNumber" }, */
  94. MONO_MT_UINT16, /* "RevisionNumber" }, */
  95. MONO_MT_UINT32, /* "Flags" }, */
  96. MONO_MT_BLOB_IDX, /* "PublicKey" }, */
  97. MONO_MT_STRING_IDX, /* "Name" }, */
  98. MONO_MT_STRING_IDX, /* "Culture" }, */
  99. MONO_MT_END,
  100. #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
  101. MONO_MT_UINT32, /* "OSPlatformID" }, */
  102. MONO_MT_UINT32, /* "OSMajor" }, */
  103. MONO_MT_UINT32, /* "OSMinor" }, */
  104. MONO_MT_END,
  105. #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
  106. MONO_MT_UINT32, /* "Processor" }, */
  107. MONO_MT_END,
  108. #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
  109. MONO_MT_UINT16, /* "Major" }, */
  110. MONO_MT_UINT16, /* "Minor" }, */
  111. MONO_MT_UINT16, /* "Build" }, */
  112. MONO_MT_UINT16, /* "Revision" }, */
  113. MONO_MT_UINT32, /* "Flags" }, */
  114. MONO_MT_BLOB_IDX, /* "PublicKeyOrToken" }, */
  115. MONO_MT_STRING_IDX, /* "Name" }, */
  116. MONO_MT_STRING_IDX, /* "Culture" }, */
  117. MONO_MT_BLOB_IDX, /* "HashValue" }, */
  118. MONO_MT_END,
  119. #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
  120. MONO_MT_UINT32, /* "OSPlatformID" }, */
  121. MONO_MT_UINT32, /* "OSMajorVersion" }, */
  122. MONO_MT_UINT32, /* "OSMinorVersion" }, */
  123. MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
  124. MONO_MT_END,
  125. #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
  126. MONO_MT_UINT32, /* "Processor" }, */
  127. MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
  128. MONO_MT_END,
  129. #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
  130. MONO_MT_UINT16, /* "PackingSize" }, */
  131. MONO_MT_UINT32, /* "ClassSize" }, */
  132. MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
  133. MONO_MT_END,
  134. #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
  135. MONO_MT_UINT8, /* "Type" }, */
  136. MONO_MT_UINT8, /* "PaddingZero" }, */
  137. MONO_MT_CONST_IDX, /* "Parent" }, */
  138. MONO_MT_BLOB_IDX, /* "Value" }, */
  139. MONO_MT_END,
  140. #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
  141. MONO_MT_HASCAT_IDX, /* "Parent" }, */
  142. MONO_MT_CAT_IDX, /* "Type" }, */
  143. MONO_MT_BLOB_IDX, /* "Value" }, */
  144. MONO_MT_END,
  145. #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
  146. MONO_MT_UINT16, /* "Action" }, */
  147. MONO_MT_HASDEC_IDX, /* "Parent" }, */
  148. MONO_MT_BLOB_IDX, /* "PermissionSet" }, */
  149. MONO_MT_END,
  150. #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
  151. MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
  152. MONO_MT_TABLE_IDX, /* "EventList:Event" }, */
  153. MONO_MT_END,
  154. #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
  155. MONO_MT_UINT16, /* "EventFlags#EventAttribute" }, */
  156. MONO_MT_STRING_IDX, /* "Name" }, */
  157. MONO_MT_TDOR_IDX, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
  158. MONO_MT_END,
  159. #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
  160. MONO_MT_TABLE_IDX, /* "Event" }, */
  161. MONO_MT_END,
  162. #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
  163. MONO_MT_UINT32, /* "Flags" }, */
  164. MONO_MT_TABLE_IDX, /* "TypeDefId" }, */
  165. MONO_MT_STRING_IDX, /* "TypeName" }, */
  166. MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
  167. MONO_MT_IMPL_IDX, /* "Implementation" }, */
  168. MONO_MT_END,
  169. #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
  170. MONO_MT_UINT16, /* "Flags" }, */
  171. MONO_MT_STRING_IDX, /* "Name" }, */
  172. MONO_MT_BLOB_IDX, /* "Signature" }, */
  173. MONO_MT_END,
  174. #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
  175. MONO_MT_UINT32, /* "Offset" }, */
  176. MONO_MT_TABLE_IDX, /* "Field:Field" }, */
  177. MONO_MT_END,
  178. #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
  179. MONO_MT_HFM_IDX, /* "Parent" }, */
  180. MONO_MT_BLOB_IDX, /* "NativeType" }, */
  181. MONO_MT_END,
  182. #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
  183. MONO_MT_UINT32, /* "RVA" }, */
  184. MONO_MT_TABLE_IDX, /* "Field:Field" }, */
  185. MONO_MT_END,
  186. #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
  187. MONO_MT_TABLE_IDX, /* "Field" }, */
  188. MONO_MT_END,
  189. #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
  190. MONO_MT_UINT32, /* "Flags" }, */
  191. MONO_MT_STRING_IDX, /* "Name" }, */
  192. MONO_MT_BLOB_IDX, /* "Value" }, */
  193. MONO_MT_END,
  194. #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
  195. MONO_MT_UINT16, /* "MappingFlag" }, */
  196. MONO_MT_MF_IDX, /* "MemberForwarded" }, */
  197. MONO_MT_STRING_IDX, /* "ImportName" }, */
  198. MONO_MT_TABLE_IDX, /* "ImportScope:ModuleRef" }, */
  199. MONO_MT_END,
  200. #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
  201. MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
  202. MONO_MT_TDOR_IDX, /* "Interface=TypeDefOrRef" }, */
  203. MONO_MT_END,
  204. #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
  205. MONO_MT_UINT32, /* "Offset" }, */
  206. MONO_MT_UINT32, /* "Flags" }, */
  207. MONO_MT_STRING_IDX, /* "Name" }, */
  208. MONO_MT_IMPL_IDX, /* "Implementation" }, */
  209. MONO_MT_END,
  210. #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
  211. MONO_MT_MRP_IDX, /* "Class" }, */
  212. MONO_MT_STRING_IDX, /* "Name" }, */
  213. MONO_MT_BLOB_IDX, /* "Signature" }, */
  214. MONO_MT_END,
  215. #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
  216. MONO_MT_UINT32, /* "RVA" }, */
  217. MONO_MT_UINT16, /* "ImplFlags#MethodImplAttributes" }, */
  218. MONO_MT_UINT16, /* "Flags#MethodAttribute" }, */
  219. MONO_MT_STRING_IDX, /* "Name" }, */
  220. MONO_MT_BLOB_IDX, /* "Signature" }, */
  221. MONO_MT_TABLE_IDX, /* "ParamList:Param" }, */
  222. MONO_MT_END,
  223. #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
  224. MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
  225. MONO_MT_MDOR_IDX, /* "MethodBody" }, */
  226. MONO_MT_MDOR_IDX, /* "MethodDeclaration" }, */
  227. MONO_MT_END,
  228. #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
  229. MONO_MT_UINT16, /* "MethodSemantic" }, */
  230. MONO_MT_TABLE_IDX, /* "Method:Method" }, */
  231. MONO_MT_HS_IDX, /* "Association" }, */
  232. MONO_MT_END,
  233. #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
  234. MONO_MT_TABLE_IDX, /* "Method" }, */
  235. MONO_MT_END,
  236. #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
  237. MONO_MT_UINT16, /* "Generation" }, */
  238. MONO_MT_STRING_IDX, /* "Name" }, */
  239. MONO_MT_GUID_IDX, /* "MVID" }, */
  240. MONO_MT_GUID_IDX, /* "EncID" }, */
  241. MONO_MT_GUID_IDX, /* "EncBaseID" }, */
  242. MONO_MT_END,
  243. #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
  244. MONO_MT_STRING_IDX, /* "Name" }, */
  245. MONO_MT_END,
  246. #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
  247. MONO_MT_TABLE_IDX, /* "NestedClass:TypeDef" }, */
  248. MONO_MT_TABLE_IDX, /* "EnclosingClass:TypeDef" }, */
  249. MONO_MT_END,
  250. #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
  251. MONO_MT_UINT16, /* "Flags" }, */
  252. MONO_MT_UINT16, /* "Sequence" }, */
  253. MONO_MT_STRING_IDX, /* "Name" }, */
  254. MONO_MT_END,
  255. #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
  256. MONO_MT_TABLE_IDX, /* "Param" }, */
  257. MONO_MT_END,
  258. #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
  259. MONO_MT_UINT16, /* "Flags" }, */
  260. MONO_MT_STRING_IDX, /* "Name" }, */
  261. MONO_MT_BLOB_IDX, /* "Type" }, */
  262. MONO_MT_END,
  263. #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
  264. MONO_MT_TABLE_IDX, /* "Property" }, */
  265. MONO_MT_END,
  266. #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
  267. MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
  268. MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */
  269. MONO_MT_END,
  270. #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
  271. MONO_MT_BLOB_IDX, /* "Signature" }, */
  272. MONO_MT_END,
  273. #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
  274. MONO_MT_UINT32, /* "Flags" }, */
  275. MONO_MT_STRING_IDX, /* "Name" }, */
  276. MONO_MT_STRING_IDX, /* "Namespace" }, */
  277. MONO_MT_TDOR_IDX, /* "Extends" }, */
  278. MONO_MT_TABLE_IDX, /* "FieldList:Field" }, */
  279. MONO_MT_TABLE_IDX, /* "MethodList:Method" }, */
  280. MONO_MT_END,
  281. #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
  282. MONO_MT_RS_IDX, /* "ResolutionScope=ResolutionScope" }, */
  283. MONO_MT_STRING_IDX, /* "Name" }, */
  284. MONO_MT_STRING_IDX, /* "Namespace" }, */
  285. MONO_MT_END,
  286. #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
  287. MONO_MT_BLOB_IDX, /* "Signature" }, */
  288. MONO_MT_END,
  289. #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
  290. MONO_MT_UINT16, /* "Number" }, */
  291. MONO_MT_UINT16, /* "Flags" }, */
  292. MONO_MT_TABLE_IDX, /* "Owner" }, TypeDef or MethodDef */
  293. MONO_MT_STRING_IDX, /* "Name" }, */
  294. MONO_MT_END,
  295. #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
  296. MONO_MT_MDOR_IDX, /* "Method" }, */
  297. MONO_MT_BLOB_IDX, /* "Signature" }, */
  298. MONO_MT_END,
  299. #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
  300. MONO_MT_TABLE_IDX, /* "GenericParam" }, */
  301. MONO_MT_TDOR_IDX, /* "Constraint" }, */
  302. MONO_MT_END,
  303. #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
  304. MONO_MT_END
  305. };
  306. /* Must be the same order as MONO_TABLE_* */
  307. const static unsigned char
  308. table_description [] = {
  309. MODULE_SCHEMA_OFFSET,
  310. TYPEREF_SCHEMA_OFFSET,
  311. TYPEDEF_SCHEMA_OFFSET,
  312. FIELD_POINTER_SCHEMA_OFFSET,
  313. FIELD_SCHEMA_OFFSET,
  314. METHOD_POINTER_SCHEMA_OFFSET,
  315. METHOD_SCHEMA_OFFSET,
  316. PARAM_POINTER_SCHEMA_OFFSET,
  317. PARAM_SCHEMA_OFFSET,
  318. IFACEMAP_SCHEMA_OFFSET,
  319. MEMBERREF_SCHEMA_OFFSET, /* 0xa */
  320. CONSTANT_SCHEMA_OFFSET,
  321. CUSTOM_ATTR_SCHEMA_OFFSET,
  322. FIELD_MARSHAL_SCHEMA_OFFSET,
  323. DECL_SEC_SCHEMA_OFFSET,
  324. CLASS_LAYOUT_SCHEMA_OFFSET,
  325. FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
  326. STDALON_SIG_SCHEMA_OFFSET,
  327. EVENTMAP_SCHEMA_OFFSET,
  328. EVENT_POINTER_SCHEMA_OFFSET,
  329. EVENT_SCHEMA_OFFSET,
  330. PROPERTY_MAP_SCHEMA_OFFSET,
  331. PROPERTY_POINTER_SCHEMA_OFFSET,
  332. PROPERTY_SCHEMA_OFFSET,
  333. METHOD_SEMA_SCHEMA_OFFSET,
  334. METHOD_IMPL_SCHEMA_OFFSET,
  335. MODULEREF_SCHEMA_OFFSET, /* 0x1a */
  336. TYPESPEC_SCHEMA_OFFSET,
  337. IMPLMAP_SCHEMA_OFFSET,
  338. FIELD_RVA_SCHEMA_OFFSET,
  339. NULL_SCHEMA_OFFSET,
  340. NULL_SCHEMA_OFFSET,
  341. ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
  342. ASSEMBLYPROC_SCHEMA_OFFSET,
  343. ASSEMBLYOS_SCHEMA_OFFSET,
  344. ASSEMBLYREF_SCHEMA_OFFSET,
  345. ASSEMBLYREFPROC_SCHEMA_OFFSET,
  346. ASSEMBLYREFOS_SCHEMA_OFFSET,
  347. FILE_SCHEMA_OFFSET,
  348. EXPORTED_TYPE_SCHEMA_OFFSET,
  349. MANIFEST_SCHEMA_OFFSET,
  350. NESTED_CLASS_SCHEMA_OFFSET,
  351. GENPARAM_SCHEMA_OFFSET, /* 0x2a */
  352. METHOD_SPEC_SCHEMA_OFFSET,
  353. GEN_CONSTRAINT_SCHEMA_OFFSET
  354. };
  355. #ifdef HAVE_ARRAY_ELEM_INIT
  356. #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
  357. #define MSGSTRFIELD1(line) str##line
  358. static const struct msgstr_t {
  359. #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
  360. #include "mono/cil/tables.def"
  361. #undef TABLEDEF
  362. } tablestr = {
  363. #define TABLEDEF(a,b) b,
  364. #include "mono/cil/tables.def"
  365. #undef TABLEDEF
  366. };
  367. static const gint16 tableidx [] = {
  368. #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
  369. #include "mono/cil/tables.def"
  370. #undef TABLEDEF
  371. };
  372. #else
  373. #define TABLEDEF(a,b) b,
  374. static const char* const
  375. mono_tables_names [] = {
  376. #include "mono/cil/tables.def"
  377. NULL
  378. };
  379. #endif
  380. /**
  381. * mono_meta_table_name:
  382. * @table: table index
  383. *
  384. * Returns the name of the given ECMA metadata logical format table
  385. * as described in ECMA 335, Partition II, Section 22.
  386. *
  387. * Returns: the name for the @table index
  388. */
  389. const char *
  390. mono_meta_table_name (int table)
  391. {
  392. if ((table < 0) || (table > MONO_TABLE_LAST))
  393. return "";
  394. #ifdef HAVE_ARRAY_ELEM_INIT
  395. return (const char*)&tablestr + tableidx [table];
  396. #else
  397. return mono_tables_names [table];
  398. #endif
  399. }
  400. /* The guy who wrote the spec for this should not be allowed near a
  401. * computer again.
  402. If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
  403. then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
  404. rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
  405. finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
  406. inverse of this mapping.
  407. */
  408. #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
  409. #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
  410. /* Reference: Partition II - 23.2.6 */
  411. /*
  412. * mono_metadata_compute_size:
  413. * @meta: metadata context
  414. * @tableindex: metadata table number
  415. * @result_bitfield: pointer to guint32 where to store additional info
  416. *
  417. * mono_metadata_compute_size() computes the lenght in bytes of a single
  418. * row in a metadata table. The size of each column is encoded in the
  419. * @result_bitfield return value along with the number of columns in the table.
  420. * the resulting bitfield should be handed to the mono_metadata_table_size()
  421. * and mono_metadata_table_count() macros.
  422. * This is a Mono runtime internal only function.
  423. */
  424. int
  425. mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
  426. {
  427. guint32 bitfield = 0;
  428. int size = 0, field_size = 0;
  429. int i, n, code;
  430. int shift = 0;
  431. const unsigned char *description = TableSchemas + table_description [tableindex];
  432. for (i = 0; (code = description [i]) != MONO_MT_END; i++){
  433. switch (code){
  434. case MONO_MT_UINT32:
  435. field_size = 4; break;
  436. case MONO_MT_UINT16:
  437. field_size = 2; break;
  438. case MONO_MT_UINT8:
  439. field_size = 1; break;
  440. case MONO_MT_BLOB_IDX:
  441. field_size = meta->idx_blob_wide ? 4 : 2; break;
  442. case MONO_MT_STRING_IDX:
  443. field_size = meta->idx_string_wide ? 4 : 2; break;
  444. case MONO_MT_GUID_IDX:
  445. field_size = meta->idx_guid_wide ? 4 : 2; break;
  446. case MONO_MT_TABLE_IDX:
  447. /* Uhm, a table index can point to other tables besides the current one
  448. * so, it's not correct to use the rowcount of the current table to
  449. * get the size for this column - lupus
  450. */
  451. switch (tableindex) {
  452. case MONO_TABLE_ASSEMBLYREFOS:
  453. g_assert (i == 3);
  454. field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
  455. case MONO_TABLE_ASSEMBLYREFPROCESSOR:
  456. g_assert (i == 1);
  457. field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
  458. case MONO_TABLE_CLASSLAYOUT:
  459. g_assert (i == 2);
  460. field_size = idx_size (MONO_TABLE_TYPEDEF); break;
  461. case MONO_TABLE_EVENTMAP:
  462. g_assert (i == 0 || i == 1);
  463. field_size = i ? idx_size (MONO_TABLE_EVENT):
  464. idx_size(MONO_TABLE_TYPEDEF);
  465. break;
  466. case MONO_TABLE_EVENT_POINTER:
  467. g_assert (i == 0);
  468. field_size = idx_size (MONO_TABLE_EVENT); break;
  469. case MONO_TABLE_EXPORTEDTYPE:
  470. g_assert (i == 1);
  471. /* the index is in another metadata file, so it must be 4 */
  472. field_size = 4; break;
  473. case MONO_TABLE_FIELDLAYOUT:
  474. g_assert (i == 1);
  475. field_size = idx_size (MONO_TABLE_FIELD); break;
  476. case MONO_TABLE_FIELDRVA:
  477. g_assert (i == 1);
  478. field_size = idx_size (MONO_TABLE_FIELD); break;
  479. case MONO_TABLE_FIELD_POINTER:
  480. g_assert (i == 0);
  481. field_size = idx_size (MONO_TABLE_FIELD); break;
  482. case MONO_TABLE_IMPLMAP:
  483. g_assert (i == 3);
  484. field_size = idx_size (MONO_TABLE_MODULEREF); break;
  485. case MONO_TABLE_INTERFACEIMPL:
  486. g_assert (i == 0);
  487. field_size = idx_size (MONO_TABLE_TYPEDEF); break;
  488. case MONO_TABLE_METHOD:
  489. g_assert (i == 5);
  490. field_size = idx_size (MONO_TABLE_PARAM); break;
  491. case MONO_TABLE_METHODIMPL:
  492. g_assert (i == 0);
  493. field_size = idx_size (MONO_TABLE_TYPEDEF); break;
  494. case MONO_TABLE_METHODSEMANTICS:
  495. g_assert (i == 1);
  496. field_size = idx_size (MONO_TABLE_METHOD); break;
  497. case MONO_TABLE_METHOD_POINTER:
  498. g_assert (i == 0);
  499. field_size = idx_size (MONO_TABLE_METHOD); break;
  500. case MONO_TABLE_NESTEDCLASS:
  501. g_assert (i == 0 || i == 1);
  502. field_size = idx_size (MONO_TABLE_TYPEDEF); break;
  503. case MONO_TABLE_PARAM_POINTER:
  504. g_assert (i == 0);
  505. field_size = idx_size (MONO_TABLE_PARAM); break;
  506. case MONO_TABLE_PROPERTYMAP:
  507. g_assert (i == 0 || i == 1);
  508. field_size = i ? idx_size (MONO_TABLE_PROPERTY):
  509. idx_size(MONO_TABLE_TYPEDEF);
  510. break;
  511. case MONO_TABLE_PROPERTY_POINTER:
  512. g_assert (i == 0);
  513. field_size = idx_size (MONO_TABLE_PROPERTY); break;
  514. case MONO_TABLE_TYPEDEF:
  515. g_assert (i == 4 || i == 5);
  516. field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
  517. idx_size(MONO_TABLE_METHOD);
  518. break;
  519. case MONO_TABLE_GENERICPARAM:
  520. g_assert (i == 2);
  521. n = MAX (meta->tables [MONO_TABLE_METHOD].rows, meta->tables [MONO_TABLE_TYPEDEF].rows);
  522. /*This is a coded token for 2 tables, so takes 1 bit */
  523. field_size = rtsize (n, 16 - MONO_TYPEORMETHOD_BITS);
  524. break;
  525. case MONO_TABLE_GENERICPARAMCONSTRAINT:
  526. g_assert (i == 0);
  527. field_size = idx_size (MONO_TABLE_GENERICPARAM);
  528. break;
  529. default:
  530. g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
  531. }
  532. break;
  533. /*
  534. * HasConstant: ParamDef, FieldDef, Property
  535. */
  536. case MONO_MT_CONST_IDX:
  537. n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
  538. meta->tables [MONO_TABLE_FIELD].rows);
  539. n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
  540. /* 2 bits to encode tag */
  541. field_size = rtsize (n, 16-2);
  542. break;
  543. /*
  544. * HasCustomAttribute: points to any table but
  545. * itself.
  546. */
  547. case MONO_MT_HASCAT_IDX:
  548. /*
  549. * We believe that since the signature and
  550. * permission are indexing the Blob heap,
  551. * we should consider the blob size first
  552. */
  553. /* I'm not a believer - lupus
  554. if (meta->idx_blob_wide){
  555. field_size = 4;
  556. break;
  557. }*/
  558. n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
  559. meta->tables [MONO_TABLE_FIELD].rows);
  560. n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
  561. n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
  562. n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
  563. n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
  564. n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
  565. n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
  566. n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
  567. n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
  568. n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
  569. n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
  570. n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
  571. n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
  572. n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
  573. n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
  574. n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
  575. n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
  576. n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
  577. /* 5 bits to encode */
  578. field_size = rtsize (n, 16-5);
  579. break;
  580. /*
  581. * CustomAttributeType: TypeDef, TypeRef, MethodDef,
  582. * MemberRef and String.
  583. */
  584. case MONO_MT_CAT_IDX:
  585. /* String is a heap, if it is wide, we know the size */
  586. /* See above, nope.
  587. if (meta->idx_string_wide){
  588. field_size = 4;
  589. break;
  590. }*/
  591. n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
  592. meta->tables [MONO_TABLE_TYPEDEF].rows);
  593. n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
  594. n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
  595. /* 3 bits to encode */
  596. field_size = rtsize (n, 16-3);
  597. break;
  598. /*
  599. * HasDeclSecurity: Typedef, MethodDef, Assembly
  600. */
  601. case MONO_MT_HASDEC_IDX:
  602. n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
  603. meta->tables [MONO_TABLE_METHOD].rows);
  604. n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
  605. /* 2 bits to encode */
  606. field_size = rtsize (n, 16-2);
  607. break;
  608. /*
  609. * Implementation: File, AssemblyRef, ExportedType
  610. */
  611. case MONO_MT_IMPL_IDX:
  612. n = MAX (meta->tables [MONO_TABLE_FILE].rows,
  613. meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
  614. n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
  615. /* 2 bits to encode tag */
  616. field_size = rtsize (n, 16-2);
  617. break;
  618. /*
  619. * HasFieldMarshall: FieldDef, ParamDef
  620. */
  621. case MONO_MT_HFM_IDX:
  622. n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
  623. meta->tables [MONO_TABLE_PARAM].rows);
  624. /* 1 bit used to encode tag */
  625. field_size = rtsize (n, 16-1);
  626. break;
  627. /*
  628. * MemberForwarded: FieldDef, MethodDef
  629. */
  630. case MONO_MT_MF_IDX:
  631. n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
  632. meta->tables [MONO_TABLE_METHOD].rows);
  633. /* 1 bit used to encode tag */
  634. field_size = rtsize (n, 16-1);
  635. break;
  636. /*
  637. * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
  638. * LAMESPEC
  639. * It is TypeDef, _TypeRef_, TypeSpec, instead.
  640. */
  641. case MONO_MT_TDOR_IDX:
  642. n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
  643. meta->tables [MONO_TABLE_TYPEREF].rows);
  644. n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
  645. /* 2 bits to encode */
  646. field_size = rtsize (n, 16-2);
  647. break;
  648. /*
  649. * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
  650. */
  651. case MONO_MT_MRP_IDX:
  652. n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
  653. meta->tables [MONO_TABLE_TYPEREF].rows);
  654. n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
  655. n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
  656. n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
  657. /* 3 bits to encode */
  658. field_size = rtsize (n, 16 - 3);
  659. break;
  660. /*
  661. * MethodDefOrRef: MethodDef, MemberRef
  662. */
  663. case MONO_MT_MDOR_IDX:
  664. n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
  665. meta->tables [MONO_TABLE_MEMBERREF].rows);
  666. /* 1 bit used to encode tag */
  667. field_size = rtsize (n, 16-1);
  668. break;
  669. /*
  670. * HasSemantics: Property, Event
  671. */
  672. case MONO_MT_HS_IDX:
  673. n = MAX (meta->tables [MONO_TABLE_PROPERTY].rows,
  674. meta->tables [MONO_TABLE_EVENT].rows);
  675. /* 1 bit used to encode tag */
  676. field_size = rtsize (n, 16-1);
  677. break;
  678. /*
  679. * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
  680. */
  681. case MONO_MT_RS_IDX:
  682. n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
  683. meta->tables [MONO_TABLE_MODULEREF].rows);
  684. n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
  685. n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
  686. /* 2 bits used to encode tag (ECMA spec claims 3) */
  687. field_size = rtsize (n, 16 - 2);
  688. break;
  689. }
  690. /*
  691. * encode field size as follows (we just need to
  692. * distinguish them).
  693. *
  694. * 4 -> 3
  695. * 2 -> 1
  696. * 1 -> 0
  697. */
  698. bitfield |= (field_size-1) << shift;
  699. shift += 2;
  700. size += field_size;
  701. /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
  702. }
  703. *result_bitfield = (i << 24) | bitfield;
  704. return size;
  705. }
  706. /**
  707. * mono_metadata_compute_table_bases:
  708. * @meta: metadata context to compute table values
  709. *
  710. * Computes the table bases for the metadata structure.
  711. * This is an internal function used by the image loader code.
  712. */
  713. void
  714. mono_metadata_compute_table_bases (MonoImage *meta)
  715. {
  716. int i;
  717. const char *base = meta->tables_base;
  718. for (i = 0; i < MONO_TABLE_NUM; i++) {
  719. MonoTableInfo *table = &meta->tables [i];
  720. if (table->rows == 0)
  721. continue;
  722. table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
  723. table->base = base;
  724. base += table->rows * table->row_size;
  725. }
  726. }
  727. /**
  728. * mono_metadata_locate:
  729. * @meta: metadata context
  730. * @table: table code.
  731. * @idx: index of element to retrieve from @table.
  732. *
  733. * Returns: a pointer to the @idx element in the metadata table
  734. * whose code is @table.
  735. */
  736. const char *
  737. mono_metadata_locate (MonoImage *meta, int table, int idx)
  738. {
  739. /* idx == 0 refers always to NULL */
  740. g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
  741. return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
  742. }
  743. /**
  744. * mono_metadata_locate_token:
  745. * @meta: metadata context
  746. * @token: metadata token
  747. *
  748. * Returns: a pointer to the data in the metadata represented by the
  749. * token #token.
  750. */
  751. const char *
  752. mono_metadata_locate_token (MonoImage *meta, guint32 token)
  753. {
  754. return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
  755. }
  756. /**
  757. * mono_metadata_string_heap:
  758. * @meta: metadata context
  759. * @index: index into the string heap.
  760. *
  761. * Returns: an in-memory pointer to the @index in the string heap.
  762. */
  763. const char *
  764. mono_metadata_string_heap (MonoImage *meta, guint32 index)
  765. {
  766. g_assert (index < meta->heap_strings.size);
  767. g_return_val_if_fail (index < meta->heap_strings.size, "");
  768. return meta->heap_strings.data + index;
  769. }
  770. /**
  771. * mono_metadata_user_string:
  772. * @meta: metadata context
  773. * @index: index into the user string heap.
  774. *
  775. * Returns: an in-memory pointer to the @index in the user string heap ("#US").
  776. */
  777. const char *
  778. mono_metadata_user_string (MonoImage *meta, guint32 index)
  779. {
  780. g_assert (index < meta->heap_us.size);
  781. g_return_val_if_fail (index < meta->heap_us.size, "");
  782. return meta->heap_us.data + index;
  783. }
  784. /**
  785. * mono_metadata_blob_heap:
  786. * @meta: metadata context
  787. * @index: index into the blob.
  788. *
  789. * Returns: an in-memory pointer to the @index in the Blob heap.
  790. */
  791. const char *
  792. mono_metadata_blob_heap (MonoImage *meta, guint32 index)
  793. {
  794. g_assert (index < meta->heap_blob.size);
  795. g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
  796. return meta->heap_blob.data + index;
  797. }
  798. /**
  799. * mono_metadata_guid_heap:
  800. * @meta: metadata context
  801. * @index: index into the guid heap.
  802. *
  803. * Returns: an in-memory pointer to the @index in the guid heap.
  804. */
  805. const char *
  806. mono_metadata_guid_heap (MonoImage *meta, guint32 index)
  807. {
  808. --index;
  809. index *= 16; /* adjust for guid size and 1-based index */
  810. g_return_val_if_fail (index < meta->heap_guid.size, "");
  811. return meta->heap_guid.data + index;
  812. }
  813. static const unsigned char *
  814. dword_align (const unsigned char *ptr)
  815. {
  816. #if SIZEOF_VOID_P == 8
  817. return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
  818. #else
  819. return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
  820. #endif
  821. }
  822. /**
  823. * mono_metadata_decode_row:
  824. * @t: table to extract information from.
  825. * @idx: index in table.
  826. * @res: array of @res_size cols to store the results in
  827. *
  828. * This decompresses the metadata element @idx in table @t
  829. * into the guint32 @res array that has res_size elements
  830. */
  831. void
  832. mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
  833. {
  834. guint32 bitfield = t->size_bitfield;
  835. int i, count = mono_metadata_table_count (bitfield);
  836. const char *data;
  837. g_assert (idx < t->rows);
  838. g_assert (idx >= 0);
  839. data = t->base + idx * t->row_size;
  840. g_assert (res_size == count);
  841. for (i = 0; i < count; i++) {
  842. int n = mono_metadata_table_size (bitfield, i);
  843. switch (n){
  844. case 1:
  845. res [i] = *data; break;
  846. case 2:
  847. res [i] = read16 (data); break;
  848. case 4:
  849. res [i] = read32 (data); break;
  850. default:
  851. g_assert_not_reached ();
  852. }
  853. data += n;
  854. }
  855. }
  856. /**
  857. * mono_metadata_decode_row_col:
  858. * @t: table to extract information from.
  859. * @idx: index for row in table.
  860. * @col: column in the row.
  861. *
  862. * This function returns the value of column @col from the @idx
  863. * row in the table @t.
  864. */
  865. guint32
  866. mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
  867. {
  868. guint32 bitfield = t->size_bitfield;
  869. int i;
  870. register const char *data;
  871. register int n;
  872. g_assert (idx < t->rows);
  873. g_assert (col < mono_metadata_table_count (bitfield));
  874. data = t->base + idx * t->row_size;
  875. n = mono_metadata_table_size (bitfield, 0);
  876. for (i = 0; i < col; ++i) {
  877. data += n;
  878. n = mono_metadata_table_size (bitfield, i + 1);
  879. }
  880. switch (n) {
  881. case 1:
  882. return *data;
  883. case 2:
  884. return read16 (data);
  885. case 4:
  886. return read32 (data);
  887. default:
  888. g_assert_not_reached ();
  889. }
  890. return 0;
  891. }
  892. /**
  893. * mono_metadata_decode_blob_size:
  894. * @ptr: pointer to a blob object
  895. * @rptr: the new position of the pointer
  896. *
  897. * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
  898. *
  899. * Returns: the size of the blob object
  900. */
  901. guint32
  902. mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
  903. {
  904. const unsigned char *ptr = (const unsigned char *)xptr;
  905. guint32 size;
  906. if ((*ptr & 0x80) == 0){
  907. size = ptr [0] & 0x7f;
  908. ptr++;
  909. } else if ((*ptr & 0x40) == 0){
  910. size = ((ptr [0] & 0x3f) << 8) + ptr [1];
  911. ptr += 2;
  912. } else {
  913. size = ((ptr [0] & 0x1f) << 24) +
  914. (ptr [1] << 16) +
  915. (ptr [2] << 8) +
  916. ptr [3];
  917. ptr += 4;
  918. }
  919. if (rptr)
  920. *rptr = (char*)ptr;
  921. return size;
  922. }
  923. /**
  924. * mono_metadata_decode_value:
  925. * @ptr: pointer to decode from
  926. * @rptr: the new position of the pointer
  927. *
  928. * This routine decompresses 32-bit values as specified in the "Blob and
  929. * Signature" section (22.2)
  930. *
  931. * Returns: the decoded value
  932. */
  933. guint32
  934. mono_metadata_decode_value (const char *_ptr, const char **rptr)
  935. {
  936. const unsigned char *ptr = (const unsigned char *) _ptr;
  937. unsigned char b = *ptr;
  938. guint32 len;
  939. if ((b & 0x80) == 0){
  940. len = b;
  941. ++ptr;
  942. } else if ((b & 0x40) == 0){
  943. len = ((b & 0x3f) << 8 | ptr [1]);
  944. ptr += 2;
  945. } else {
  946. len = ((b & 0x1f) << 24) |
  947. (ptr [1] << 16) |
  948. (ptr [2] << 8) |
  949. ptr [3];
  950. ptr += 4;
  951. }
  952. if (rptr)
  953. *rptr = (char*)ptr;
  954. return len;
  955. }
  956. /**
  957. * mono_metadata_decode_signed_value:
  958. * @ptr: pointer to decode from
  959. * @rptr: the new position of the pointer
  960. *
  961. * This routine decompresses 32-bit signed values
  962. * (not specified in the spec)
  963. *
  964. * Returns: the decoded value
  965. */
  966. gint32
  967. mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
  968. {
  969. guint32 uval = mono_metadata_decode_value (ptr, rptr);
  970. gint32 ival = uval >> 1;
  971. if (!(uval & 1))
  972. return ival;
  973. /* ival is a truncated 2's complement negative number. */
  974. if (ival < 0x40)
  975. /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
  976. return ival - 0x40;
  977. if (ival < 0x2000)
  978. /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
  979. return ival - 0x2000;
  980. if (ival < 0x10000000)
  981. /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
  982. return ival - 0x10000000;
  983. g_assert (ival < 0x20000000);
  984. g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
  985. return ival - 0x20000000;
  986. }
  987. /*
  988. * Translates the given 1-based index into the Method, Field, Event, or Param tables
  989. * using the *Ptr tables in uncompressed metadata, if they are available.
  990. *
  991. * FIXME: The caller is not forced to call this function, which is error-prone, since
  992. * forgetting to call it would only show up as a bug on uncompressed metadata.
  993. */
  994. guint32
  995. mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
  996. {
  997. if (!image->uncompressed_metadata)
  998. return idx;
  999. switch (table) {
  1000. case MONO_TABLE_METHOD:
  1001. if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
  1002. return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
  1003. else
  1004. return idx;
  1005. case MONO_TABLE_FIELD:
  1006. if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
  1007. return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
  1008. else
  1009. return idx;
  1010. case MONO_TABLE_EVENT:
  1011. if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
  1012. return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
  1013. else
  1014. return idx;
  1015. case MONO_TABLE_PROPERTY:
  1016. if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
  1017. return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
  1018. else
  1019. return idx;
  1020. case MONO_TABLE_PARAM:
  1021. if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
  1022. return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
  1023. else
  1024. return idx;
  1025. default:
  1026. return idx;
  1027. }
  1028. }
  1029. /**
  1030. * mono_metadata_decode_table_row:
  1031. *
  1032. * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
  1033. * uncompressed metadata into account, so it should be used to access the
  1034. * Method, Field, Param and Event tables when the access is made from metadata, i.e.
  1035. * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
  1036. */
  1037. void
  1038. mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
  1039. {
  1040. if (image->uncompressed_metadata)
  1041. idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
  1042. mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
  1043. }
  1044. /**
  1045. * mono_metadata_decode_table_row_col:
  1046. *
  1047. * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
  1048. * uncompressed metadata into account, so it should be used to access the
  1049. * Method, Field, Param and Event tables.
  1050. */
  1051. guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
  1052. {
  1053. if (image->uncompressed_metadata)
  1054. idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
  1055. return mono_metadata_decode_row_col (&image->tables [table], idx, col);
  1056. }
  1057. /*
  1058. * mono_metadata_parse_typedef_or_ref:
  1059. * @m: a metadata context.
  1060. * @ptr: a pointer to an encoded TypedefOrRef in @m
  1061. * @rptr: pointer updated to match the end of the decoded stream
  1062. *
  1063. * Returns: a token valid in the @m metadata decoded from
  1064. * the compressed representation.
  1065. */
  1066. guint32
  1067. mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
  1068. {
  1069. guint32 token;
  1070. token = mono_metadata_decode_value (ptr, &ptr);
  1071. if (rptr)
  1072. *rptr = ptr;
  1073. return mono_metadata_token_from_dor (token);
  1074. }
  1075. /*
  1076. * mono_metadata_parse_custom_mod:
  1077. * @m: a metadata context.
  1078. * @dest: storage where the info about the custom modifier is stored (may be NULL)
  1079. * @ptr: a pointer to (possibly) the start of a custom modifier list
  1080. * @rptr: pointer updated to match the end of the decoded stream
  1081. *
  1082. * Checks if @ptr points to a type custom modifier compressed representation.
  1083. *
  1084. * Returns: #TRUE if a custom modifier was found, #FALSE if not.
  1085. */
  1086. int
  1087. mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
  1088. {
  1089. MonoCustomMod local;
  1090. if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
  1091. if (!dest)
  1092. dest = &local;
  1093. dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
  1094. dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
  1095. return TRUE;
  1096. }
  1097. return FALSE;
  1098. }
  1099. /*
  1100. * mono_metadata_parse_array_internal:
  1101. * @m: a metadata context.
  1102. * @transient: whenever to allocate data from the heap
  1103. * @ptr: a pointer to an encoded array description.
  1104. * @rptr: pointer updated to match the end of the decoded stream
  1105. *
  1106. * Decodes the compressed array description found in the metadata @m at @ptr.
  1107. *
  1108. * Returns: a #MonoArrayType structure describing the array type
  1109. * and dimensions. Memory is allocated from the heap or from the image mempool, depending
  1110. * on the value of @transient.
  1111. *
  1112. * LOCKING: Acquires the loader lock
  1113. */
  1114. static MonoArrayType *
  1115. mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
  1116. gboolean transient, const char *ptr, const char **rptr)
  1117. {
  1118. int i;
  1119. MonoArrayType *array;
  1120. MonoType *etype;
  1121. array = transient ? g_malloc0 (sizeof (MonoArrayType)) : mono_image_alloc0 (m, sizeof (MonoArrayType));
  1122. etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
  1123. if (!etype)
  1124. return NULL;
  1125. array->eklass = mono_class_from_mono_type (etype);
  1126. array->rank = mono_metadata_decode_value (ptr, &ptr);
  1127. array->numsizes = mono_metadata_decode_value (ptr, &ptr);
  1128. if (array->numsizes)
  1129. array->sizes = transient ? g_malloc0 (sizeof (int) * array->numsizes) : mono_image_alloc0 (m, sizeof (int) * array->numsizes);
  1130. for (i = 0; i < array->numsizes; ++i)
  1131. array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
  1132. array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
  1133. if (array->numlobounds)
  1134. array->lobounds = transient ? g_malloc0 (sizeof (int) * array->numlobounds) : mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
  1135. for (i = 0; i < array->numlobounds; ++i)
  1136. array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
  1137. if (rptr)
  1138. *rptr = ptr;
  1139. return array;
  1140. }
  1141. MonoArrayType *
  1142. mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
  1143. const char *ptr, const char **rptr)
  1144. {
  1145. return mono_metadata_parse_array_internal (m, container, FALSE, ptr, rptr);
  1146. }
  1147. MonoArrayType *
  1148. mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
  1149. {
  1150. return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
  1151. }
  1152. /*
  1153. * mono_metadata_free_array:
  1154. * @array: array description
  1155. *
  1156. * Frees the array description returned from mono_metadata_parse_array().
  1157. */
  1158. void
  1159. mono_metadata_free_array (MonoArrayType *array)
  1160. {
  1161. g_free (array->sizes);
  1162. g_free (array->lobounds);
  1163. g_free (array);
  1164. }
  1165. /*
  1166. * need to add common field and param attributes combinations:
  1167. * [out] param
  1168. * public static
  1169. * public static literal
  1170. * private
  1171. * private static
  1172. * private static literal
  1173. */
  1174. static const MonoType
  1175. builtin_types[] = {
  1176. /* data, attrs, type, nmods, byref, pinned */
  1177. {{NULL}, 0, MONO_TYPE_VOID, 0, 0, 0},
  1178. {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 0, 0},
  1179. {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 1, 0},
  1180. {{NULL}, 0, MONO_TYPE_CHAR, 0, 0, 0},
  1181. {{NULL}, 0, MONO_TYPE_CHAR, 0, 1, 0},
  1182. {{NULL}, 0, MONO_TYPE_I1, 0, 0, 0},
  1183. {{NULL}, 0, MONO_TYPE_I1, 0, 1, 0},
  1184. {{NULL}, 0, MONO_TYPE_U1, 0, 0, 0},
  1185. {{NULL}, 0, MONO_TYPE_U1, 0, 1, 0},
  1186. {{NULL}, 0, MONO_TYPE_I2, 0, 0, 0},
  1187. {{NULL}, 0, MONO_TYPE_I2, 0, 1, 0},
  1188. {{NULL}, 0, MONO_TYPE_U2, 0, 0, 0},
  1189. {{NULL}, 0, MONO_TYPE_U2, 0, 1, 0},
  1190. {{NULL}, 0, MONO_TYPE_I4, 0, 0, 0},
  1191. {{NULL}, 0, MONO_TYPE_I4, 0, 1, 0},
  1192. {{NULL}, 0, MONO_TYPE_U4, 0, 0, 0},
  1193. {{NULL}, 0, MONO_TYPE_U4, 0, 1, 0},
  1194. {{NULL}, 0, MONO_TYPE_I8, 0, 0, 0},
  1195. {{NULL}, 0, MONO_TYPE_I8, 0, 1, 0},
  1196. {{NULL}, 0, MONO_TYPE_U8, 0, 0, 0},
  1197. {{NULL}, 0, MONO_TYPE_U8, 0, 1, 0},
  1198. {{NULL}, 0, MONO_TYPE_R4, 0, 0, 0},
  1199. {{NULL}, 0, MONO_TYPE_R4, 0, 1, 0},
  1200. {{NULL}, 0, MONO_TYPE_R8, 0, 0, 0},
  1201. {{NULL}, 0, MONO_TYPE_R8, 0, 1, 0},
  1202. {{NULL}, 0, MONO_TYPE_STRING, 0, 0, 0},
  1203. {{NULL}, 0, MONO_TYPE_STRING, 0, 1, 0},
  1204. {{NULL}, 0, MONO_TYPE_OBJECT, 0, 0, 0},
  1205. {{NULL}, 0, MONO_TYPE_OBJECT, 0, 1, 0},
  1206. {{NULL}, 0, MONO_TYPE_TYPEDBYREF, 0, 0, 0},
  1207. {{NULL}, 0, MONO_TYPE_I, 0, 0, 0},
  1208. {{NULL}, 0, MONO_TYPE_I, 0, 1, 0},
  1209. {{NULL}, 0, MONO_TYPE_U, 0, 0, 0},
  1210. {{NULL}, 0, MONO_TYPE_U, 0, 1, 0},
  1211. };
  1212. #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
  1213. static GHashTable *type_cache = NULL;
  1214. static int next_generic_inst_id = 0;
  1215. static MonoImageSet *mscorlib_image_set;
  1216. static GPtrArray *image_sets;
  1217. static guint mono_generic_class_hash (gconstpointer data);
  1218. /*
  1219. * MonoTypes with modifies are never cached, so we never check or use that field.
  1220. */
  1221. static guint
  1222. mono_type_hash (gconstpointer data)
  1223. {
  1224. const MonoType *type = (const MonoType *) data;
  1225. if (type->type == MONO_TYPE_GENERICINST)
  1226. return mono_generic_class_hash (type->data.generic_class);
  1227. else
  1228. return type->type | (type->byref << 8) | (type->attrs << 9);
  1229. }
  1230. static gint
  1231. mono_type_equal (gconstpointer ka, gconstpointer kb)
  1232. {
  1233. const MonoType *a = (const MonoType *) ka;
  1234. const MonoType *b = (const MonoType *) kb;
  1235. if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
  1236. return 0;
  1237. /* need other checks */
  1238. return 1;
  1239. }
  1240. guint
  1241. mono_metadata_generic_inst_hash (gconstpointer data)
  1242. {
  1243. const MonoGenericInst *ginst = (const MonoGenericInst *) data;
  1244. guint hash = 0;
  1245. int i;
  1246. for (i = 0; i < ginst->type_argc; ++i) {
  1247. hash *= 13;
  1248. hash += mono_metadata_type_hash (ginst->type_argv [i]);
  1249. }
  1250. return hash ^ (ginst->is_open << 8);
  1251. }
  1252. static gboolean
  1253. mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
  1254. {
  1255. int i;
  1256. #ifndef MONO_SMALL_CONFIG
  1257. if (a->id && b->id) {
  1258. if (a->id == b->id)
  1259. return TRUE;
  1260. if (!signature_only)
  1261. return FALSE;
  1262. }
  1263. #endif
  1264. if (a->is_open != b->is_open || a->type_argc != b->type_argc)
  1265. return FALSE;
  1266. for (i = 0; i < a->type_argc; ++i) {
  1267. if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
  1268. return FALSE;
  1269. }
  1270. return TRUE;
  1271. }
  1272. gboolean
  1273. mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
  1274. {
  1275. const MonoGenericInst *a = (const MonoGenericInst *) ka;
  1276. const MonoGenericInst *b = (const MonoGenericInst *) kb;
  1277. return mono_generic_inst_equal_full (a, b, FALSE);
  1278. }
  1279. static guint
  1280. mono_generic_class_hash (gconstpointer data)
  1281. {
  1282. const MonoGenericClass *gclass = (const MonoGenericClass *) data;
  1283. guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
  1284. hash *= 13;
  1285. hash += gclass->is_tb_open;
  1286. hash += mono_metadata_generic_context_hash (&gclass->context);
  1287. return hash;
  1288. }
  1289. static gboolean
  1290. mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
  1291. {
  1292. const MonoGenericClass *a = (const MonoGenericClass *) ka;
  1293. const MonoGenericClass *b = (const MonoGenericClass *) kb;
  1294. return _mono_metadata_generic_class_equal (a, b, FALSE);
  1295. }
  1296. /**
  1297. * mono_metadata_init:
  1298. *
  1299. * Initialize the global variables of this module.
  1300. * This is a Mono runtime internal function.
  1301. */
  1302. void
  1303. mono_metadata_init (void)
  1304. {
  1305. int i;
  1306. type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
  1307. for (i = 0; i < NBUILTIN_TYPES (); ++i)
  1308. g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
  1309. }
  1310. /**
  1311. * mono_metadata_cleanup:
  1312. *
  1313. * Free all resources used by this module.
  1314. * This is a Mono runtime internal function.
  1315. */
  1316. void
  1317. mono_metadata_cleanup (void)
  1318. {
  1319. g_hash_table_destroy (type_cache);
  1320. type_cache = NULL;
  1321. g_ptr_array_free (image_sets, TRUE);
  1322. image_sets = NULL;
  1323. }
  1324. /**
  1325. * mono_metadata_parse_type:
  1326. * @m: metadata context
  1327. * @mode: king of type that may be found at @ptr
  1328. * @opt_attrs: optional attributes to store in the returned type
  1329. * @ptr: pointer to the type representation
  1330. * @rptr: pointer updated to match the end of the decoded stream
  1331. * @transient: whenever to allocate the result from the heap or from a mempool
  1332. *
  1333. * Decode a compressed type description found at @ptr in @m.
  1334. * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
  1335. * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
  1336. * This function can be used to decode type descriptions in method signatures,
  1337. * field signatures, locals signatures etc.
  1338. *
  1339. * To parse a generic type, `generic_container' points to the current class'es
  1340. * (the `generic_container' field in the MonoClass) or the current generic method's
  1341. * (stored in image->property_hash) generic container.
  1342. * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
  1343. * this MonoGenericContainer.
  1344. *
  1345. * LOCKING: Acquires the loader lock.
  1346. *
  1347. * Returns: a #MonoType structure representing the decoded type.
  1348. */
  1349. static MonoType*
  1350. mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
  1351. short opt_attrs, gboolean transient, const char *ptr, const char **rptr)
  1352. {
  1353. MonoType *type, *cached;
  1354. MonoType stype;
  1355. gboolean byref = FALSE;
  1356. gboolean pinned = FALSE;
  1357. const char *tmp_ptr;
  1358. int count = 0;
  1359. gboolean found;
  1360. /*
  1361. * According to the spec, custom modifiers should come before the byref
  1362. * flag, but the IL produced by ilasm from the following signature:
  1363. * object modopt(...) &
  1364. * starts with a byref flag, followed by the modifiers. (bug #49802)
  1365. * Also, this type seems to be different from 'object & modopt(...)'. Maybe
  1366. * it would be better to treat byref as real type constructor instead of
  1367. * a modifier...
  1368. * Also, pinned should come before anything else, but some MSV++ produced
  1369. * assemblies violate this (#bug 61990).
  1370. */
  1371. /* Count the modifiers first */
  1372. tmp_ptr = ptr;
  1373. found = TRUE;
  1374. while (found) {
  1375. switch (*tmp_ptr) {
  1376. case MONO_TYPE_PINNED:
  1377. case MONO_TYPE_BYREF:
  1378. ++tmp_ptr;
  1379. break;
  1380. case MONO_TYPE_CMOD_REQD:
  1381. case MONO_TYPE_CMOD_OPT:
  1382. count ++;
  1383. mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
  1384. break;
  1385. default:
  1386. found = FALSE;
  1387. }
  1388. }
  1389. if (count) {
  1390. int size;
  1391. size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
  1392. type = transient ? g_malloc0 (size) : mono_image_alloc0 (m, size);
  1393. type->num_mods = count;
  1394. if (count > 64)
  1395. g_warning ("got more than 64 modifiers in type");
  1396. } else {
  1397. type = &stype;
  1398. memset (type, 0, MONO_SIZEOF_TYPE);
  1399. }
  1400. /* Parse pinned, byref and custom modifiers */
  1401. found = TRUE;
  1402. count = 0;
  1403. while (found) {
  1404. switch (*ptr) {
  1405. case MONO_TYPE_PINNED:
  1406. pinned = TRUE;
  1407. ++ptr;
  1408. break;
  1409. case MONO_TYPE_BYREF:
  1410. byref = TRUE;
  1411. ++ptr;
  1412. break;
  1413. case MONO_TYPE_CMOD_REQD:
  1414. case MONO_TYPE_CMOD_OPT:
  1415. mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
  1416. count ++;
  1417. break;
  1418. default:
  1419. found = FALSE;
  1420. }
  1421. }
  1422. type->attrs = opt_attrs;
  1423. type->byref = byref;
  1424. type->pinned = pinned ? 1 : 0;
  1425. if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr)) {
  1426. return NULL;
  1427. }
  1428. if (rptr)
  1429. *rptr = ptr;
  1430. if (!type->num_mods && !transient) {
  1431. /* no need to free type here, because it is on the stack */
  1432. if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
  1433. MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
  1434. /* Consider the case:
  1435. class Foo<T> { class Bar {} }
  1436. class Test : Foo<Test>.Bar {}
  1437. When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
  1438. a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
  1439. We ensure that the MonoClass is in a state that we can canonicalize to:
  1440. klass->byval_arg.data.klass == klass
  1441. klass->this_arg.data.klass == klass
  1442. If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
  1443. LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
  1444. of a MonoClass which currently holds the loader lock. 'type' is local.
  1445. */
  1446. if (ret->data.klass == type->data.klass) {
  1447. return ret;
  1448. }
  1449. }
  1450. /* No need to use locking since nobody is modifying the hash table */
  1451. if ((cached = g_hash_table_lookup (type_cache, type))) {
  1452. return cached;
  1453. }
  1454. }
  1455. /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
  1456. if (type == &stype) {
  1457. type = transient ? g_malloc (MONO_SIZEOF_TYPE) : mono_image_alloc (m, MONO_SIZEOF_TYPE);
  1458. memcpy (type, &stype, MONO_SIZEOF_TYPE);
  1459. }
  1460. return type;
  1461. }
  1462. MonoType*
  1463. mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
  1464. short opt_attrs, const char *ptr, const char **rptr)
  1465. {
  1466. return mono_metadata_parse_type_internal (m, container, mode, opt_attrs, FALSE, ptr, rptr);
  1467. }
  1468. /*
  1469. * LOCKING: Acquires the loader lock.
  1470. */
  1471. MonoType*
  1472. mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
  1473. const char *ptr, const char **rptr)
  1474. {
  1475. return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
  1476. }
  1477. gboolean
  1478. mono_metadata_method_has_param_attrs (MonoImage *m, int def)
  1479. {
  1480. MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
  1481. MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
  1482. guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
  1483. if (def < methodt->rows)
  1484. lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
  1485. else
  1486. lastp = m->tables [MONO_TABLE_PARAM].rows + 1;
  1487. for (i = param_index; i < lastp; ++i) {
  1488. guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS);
  1489. if (flags)
  1490. return TRUE;
  1491. }
  1492. return FALSE;
  1493. }
  1494. /*
  1495. * mono_metadata_get_param_attrs:
  1496. *
  1497. * @m The image to loader parameter attributes from
  1498. * @def method def token (one based)
  1499. * @param_count number of params to decode including the return value
  1500. *
  1501. * Return the parameter attributes for the method whose MethodDef index is DEF. The
  1502. * returned memory needs to be freed by the caller. If all the param attributes are
  1503. * 0, then NULL is returned.
  1504. */
  1505. int*
  1506. mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
  1507. {
  1508. MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
  1509. MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
  1510. guint32 cols [MONO_PARAM_SIZE];
  1511. guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
  1512. int *pattrs = NULL;
  1513. if (def < methodt->rows)
  1514. lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
  1515. else
  1516. lastp = paramt->rows + 1;
  1517. for (i = param_index; i < lastp; ++i) {
  1518. mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
  1519. if (cols [MONO_PARAM_FLAGS]) {
  1520. if (!pattrs)
  1521. pattrs = g_new0 (int, param_count);
  1522. /* at runtime we just ignore this kind of malformed file:
  1523. * the verifier can signal the error to the user
  1524. */
  1525. if (cols [MONO_PARAM_SEQUENCE] >= param_count)
  1526. continue;
  1527. pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
  1528. }
  1529. }
  1530. return pattrs;
  1531. }
  1532. /*
  1533. * mono_metadata_parse_signature_full:
  1534. * @image: metadata context
  1535. * @generic_container: generic container
  1536. * @toke: metadata token
  1537. *
  1538. * Decode a method signature stored in the STANDALONESIG table
  1539. *
  1540. * LOCKING: Assumes the loader lock is held.
  1541. *
  1542. * Returns: a MonoMethodSignature describing the signature.
  1543. */
  1544. MonoMethodSignature*
  1545. mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
  1546. {
  1547. MonoTableInfo *tables = image->tables;
  1548. guint32 idx = mono_metadata_token_index (token);
  1549. guint32 sig;
  1550. const char *ptr;
  1551. if (image->dynamic)
  1552. return mono_lookup_dynamic_token (image, token, NULL);
  1553. g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
  1554. sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
  1555. ptr = mono_metadata_blob_heap (image, sig);
  1556. mono_metadata_decode_blob_size (ptr, &ptr);
  1557. return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL);
  1558. }
  1559. /*
  1560. * mono_metadata_parse_signature:
  1561. * @image: metadata context
  1562. * @toke: metadata token
  1563. *
  1564. * Decode a method signature stored in the STANDALONESIG table
  1565. *
  1566. * Returns: a MonoMethodSignature describing the signature.
  1567. */
  1568. MonoMethodSignature*
  1569. mono_metadata_parse_signature (MonoImage *image, guint32 token)
  1570. {
  1571. return mono_metadata_parse_signature_full (image, NULL, token);
  1572. }
  1573. /*
  1574. * mono_metadata_signature_alloc:
  1575. * @image: metadata context
  1576. * @nparmas: number of parameters in the signature
  1577. *
  1578. * Allocate a MonoMethodSignature structure with the specified number of params.
  1579. * The return type and the params types need to be filled later.
  1580. * This is a Mono runtime internal function.
  1581. *
  1582. * LOCKING: Assumes the loader lock is held.
  1583. *
  1584. * Returns: the new MonoMethodSignature structure.
  1585. */
  1586. MonoMethodSignature*
  1587. mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
  1588. {
  1589. MonoMethodSignature *sig;
  1590. sig = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
  1591. sig->param_count = nparams;
  1592. sig->sentinelpos = -1;
  1593. return sig;
  1594. }
  1595. static MonoMethodSignature*
  1596. mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
  1597. {
  1598. int sigsize;
  1599. MonoMethodSignature *ret;
  1600. sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
  1601. if (image) {
  1602. ret = mono_image_alloc (image, sigsize);
  1603. } else if (mp) {
  1604. ret = mono_mempool_alloc (mp, sigsize);
  1605. } else {
  1606. ret = g_malloc (sigsize);
  1607. }
  1608. memcpy (ret, sig, sigsize);
  1609. return ret;
  1610. }
  1611. MonoMethodSignature*
  1612. mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
  1613. {
  1614. return mono_metadata_signature_dup_internal (image, NULL, sig);
  1615. }
  1616. /*The mempool is accessed without synchronization*/
  1617. MonoMethodSignature*
  1618. mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
  1619. {
  1620. return mono_metadata_signature_dup_internal (NULL, mp, sig);
  1621. }
  1622. /*
  1623. * mono_metadata_signature_dup:
  1624. * @sig: method signature
  1625. *
  1626. * Duplicate an existing MonoMethodSignature so it can be modified.
  1627. * This is a Mono runtime internal function.
  1628. *
  1629. * Returns: the new MonoMethodSignature structure.
  1630. */
  1631. MonoMethodSignature*
  1632. mono_metadata_signature_dup (MonoMethodSignature *sig)
  1633. {
  1634. return mono_metadata_signature_dup_full (NULL, sig);
  1635. }
  1636. /*
  1637. * mono_metadata_signature_size:
  1638. *
  1639. * Return the amount of memory allocated to SIG.
  1640. */
  1641. guint32
  1642. mono_metadata_signature_size (MonoMethodSignature *sig)
  1643. {
  1644. return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
  1645. }
  1646. /*
  1647. * mono_metadata_parse_method_signature:
  1648. * @m: metadata context
  1649. * @generic_container: generics container
  1650. * @def: the MethodDef index or 0 for Ref signatures.
  1651. * @ptr: pointer to the signature metadata representation
  1652. * @rptr: pointer updated to match the end of the decoded stream
  1653. *
  1654. * Decode a method signature stored at @ptr.
  1655. * This is a Mono runtime internal function.
  1656. *
  1657. * LOCKING: Assumes the loader lock is held.
  1658. *
  1659. * Returns: a MonoMethodSignature describing the signature.
  1660. */
  1661. MonoMethodSignature *
  1662. mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
  1663. int def, const char *ptr, const char **rptr)
  1664. {
  1665. MonoMethodSignature *method;
  1666. int i, *pattrs = NULL;
  1667. guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
  1668. guint32 gen_param_count = 0;
  1669. gboolean is_open = FALSE;
  1670. if (*ptr & 0x10)
  1671. gen_param_count = 1;
  1672. if (*ptr & 0x20)
  1673. hasthis = 1;
  1674. if (*ptr & 0x40)
  1675. explicit_this = 1;
  1676. call_convention = *ptr & 0x0F;
  1677. ptr++;
  1678. if (gen_param_count)
  1679. gen_param_count = mono_metadata_decode_value (ptr, &ptr);
  1680. param_count = mono_metadata_decode_value (ptr, &ptr);
  1681. if (def)
  1682. pattrs = mono_metadata_get_param_attrs (m, def, param_count + 1); /*Must be + 1 since signature's param count doesn't account for the return value */
  1683. method = mono_metadata_signature_alloc (m, param_count);
  1684. method->hasthis = hasthis;
  1685. method->explicit_this = explicit_this;
  1686. method->call_convention = call_convention;
  1687. method->generic_param_count = gen_param_count;
  1688. if (call_convention != 0xa) {
  1689. method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr);
  1690. if (!method->ret) {
  1691. mono_metadata_free_method_signature (method);
  1692. g_free (pattrs);
  1693. return NULL;
  1694. }
  1695. is_open = mono_class_is_open_constructed_type (method->ret);
  1696. }
  1697. for (i = 0; i < method->param_count; ++i) {
  1698. if (*ptr == MONO_TYPE_SENTINEL) {
  1699. if (method->call_convention != MONO_CALL_VARARG || def) {
  1700. g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def, m->name);
  1701. g_free (pattrs);
  1702. return NULL;
  1703. }
  1704. if (method->sentinelpos >= 0) {
  1705. g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def, m->name);
  1706. g_free (pattrs);
  1707. return NULL;
  1708. }
  1709. method->sentinelpos = i;
  1710. ptr++;
  1711. }
  1712. method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
  1713. if (!method->params [i]) {
  1714. mono_metadata_free_method_signature (method);
  1715. g_free (pattrs);
  1716. return NULL;
  1717. }
  1718. if (!is_open)
  1719. is_open = mono_class_is_open_constructed_type (method->params [i]);
  1720. }
  1721. /* The sentinel could be missing if the caller does not pass any additional arguments */
  1722. if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
  1723. method->sentinelpos = method->param_count;
  1724. method->has_type_parameters = is_open;
  1725. if (def && (method->call_convention == MONO_CALL_VARARG))
  1726. method->sentinelpos = method->param_count;
  1727. g_free (pattrs);
  1728. if (rptr)
  1729. *rptr = ptr;
  1730. /*
  1731. * Add signature to a cache and increase ref count...
  1732. */
  1733. return method;
  1734. }
  1735. /*
  1736. * mono_metadata_parse_method_signature:
  1737. * @m: metadata context
  1738. * @def: the MethodDef index or 0 for Ref signatures.
  1739. * @ptr: pointer to the signature metadata representation
  1740. * @rptr: pointer updated to match the end of the decoded stream
  1741. *
  1742. * Decode a method signature stored at @ptr.
  1743. * This is a Mono runtime internal function.
  1744. *
  1745. * LOCKING: Assumes the loader lock is held.
  1746. *
  1747. * Returns: a MonoMethodSignature describing the signature.
  1748. */
  1749. MonoMethodSignature *
  1750. mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
  1751. {
  1752. return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
  1753. }
  1754. /*
  1755. * mono_metadata_free_method_signature:
  1756. * @sig: signature to destroy
  1757. *
  1758. * Free the memory allocated in the signature @sig.
  1759. * This method needs to be robust and work also on partially-built
  1760. * signatures, so it does extra checks.
  1761. */
  1762. void
  1763. mono_metadata_free_method_signature (MonoMethodSignature *sig)
  1764. {
  1765. /* Everything is allocated from mempools */
  1766. /*
  1767. int i;
  1768. if (sig->ret)
  1769. mono_metadata_free_type (sig->ret);
  1770. for (i = 0; i < sig->param_count; ++i) {
  1771. if (sig->params [i])
  1772. mono_metadata_free_type (sig->params [i]);
  1773. }
  1774. */
  1775. }
  1776. void
  1777. mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
  1778. {
  1779. int i;
  1780. /* Allocated in inflate_generic_signature () */
  1781. if (sig->ret)
  1782. mono_metadata_free_type (sig->ret);
  1783. for (i = 0; i < sig->param_count; ++i) {
  1784. if (sig->params [i])
  1785. mono_metadata_free_type (sig->params [i]);
  1786. }
  1787. g_free (sig);
  1788. }
  1789. static gboolean
  1790. inflated_method_equal (gconstpointer a, gconstpointer b)
  1791. {
  1792. const MonoMethodInflated *ma = a;
  1793. const MonoMethodInflated *mb = b;
  1794. if (ma->declaring != mb->declaring)
  1795. return FALSE;
  1796. if (ma->method.method.is_mb_open != mb->method.method.is_mb_open)
  1797. return FALSE;
  1798. return mono_metadata_generic_context_equal (&ma->context, &mb->context);
  1799. }
  1800. static guint
  1801. inflated_method_hash (gconstpointer a)
  1802. {
  1803. const MonoMethodInflated *ma = a;
  1804. return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring)) + ma->method.method.is_mb_open;
  1805. }
  1806. static gboolean
  1807. inflated_signature_equal (gconstpointer a, gconstpointer b)
  1808. {
  1809. const MonoInflatedMethodSignature *sig1 = a;
  1810. const MonoInflatedMethodSignature *sig2 = b;
  1811. /* sig->sig is assumed to be canonized */
  1812. if (sig1->sig != sig2->sig)
  1813. return FALSE;
  1814. /* The generic instances are canonized */
  1815. return mono_metadata_generic_context_equal (&sig1->context, &sig2->context);
  1816. }
  1817. static guint
  1818. inflated_signature_hash (gconstpointer a)
  1819. {
  1820. const MonoInflatedMethodSignature *sig = a;
  1821. /* sig->sig is assumed to be canonized */
  1822. return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig);
  1823. }
  1824. /*static void
  1825. dump_ginst (MonoGenericInst *ginst)
  1826. {
  1827. int i;
  1828. char *name;
  1829. g_print ("Ginst: <");
  1830. for (i = 0; i < ginst->type_argc; ++i) {
  1831. if (i != 0)
  1832. g_print (", ");
  1833. name = mono_type_get_name (ginst->type_argv [i]);
  1834. g_print ("%s", name);
  1835. g_free (name);
  1836. }
  1837. g_print (">");
  1838. }*/
  1839. static gboolean type_in_image (MonoType *type, MonoImage *image);
  1840. static gboolean
  1841. signature_in_image (MonoMethodSignature *sig, MonoImage *image)
  1842. {
  1843. gpointer iter = NULL;
  1844. MonoType *p;
  1845. while ((p = mono_signature_get_params (sig, &iter)) != NULL)
  1846. if (type_in_image (p, image))
  1847. return TRUE;
  1848. return type_in_image (mono_signature_get_return_type (sig), image);
  1849. }
  1850. static gboolean
  1851. ginst_in_image (MonoGenericInst *ginst, MonoImage *image)
  1852. {
  1853. int i;
  1854. for (i = 0; i < ginst->type_argc; ++i) {
  1855. if (type_in_image (ginst->type_argv [i], image))
  1856. return TRUE;
  1857. }
  1858. return FALSE;
  1859. }
  1860. static gboolean
  1861. gclass_in_image (MonoGenericClass *gclass, MonoImage *image)
  1862. {
  1863. return gclass->container_class->image == image ||
  1864. ginst_in_image (gclass->context.class_inst, image);
  1865. }
  1866. static gboolean
  1867. type_in_image (MonoType *type, MonoImage *image)
  1868. {
  1869. retry:
  1870. switch (type->type) {
  1871. case MONO_TYPE_GENERICINST:
  1872. return gclass_in_image (type->data.generic_class, image);
  1873. case MONO_TYPE_PTR:
  1874. type = type->data.type;
  1875. goto retry;
  1876. case MONO_TYPE_SZARRAY:
  1877. type = &type->data.klass->byval_arg;
  1878. goto retry;
  1879. case MONO_TYPE_ARRAY:
  1880. type = &type->data.array->eklass->byval_arg;
  1881. goto retry;
  1882. case MONO_TYPE_FNPTR:
  1883. return signature_in_image (type->data.method, image);
  1884. case MONO_TYPE_VAR: {
  1885. MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
  1886. if (container) {
  1887. g_assert (!container->is_method);
  1888. /*
  1889. * FIXME: The following check is here solely
  1890. * for monodis, which uses the internal
  1891. * function
  1892. * mono_metadata_load_generic_params(). The
  1893. * caller of that function needs to fill in
  1894. * owner->klass or owner->method of the
  1895. * returned struct, but monodis doesn't do
  1896. * that. The image unloading depends on that,
  1897. * however, so a crash results without this
  1898. * check.
  1899. */
  1900. if (!container->owner.klass)
  1901. return container->image == image;
  1902. return container->owner.klass->image == image;
  1903. } else {
  1904. return type->data.generic_param->image == image;
  1905. }
  1906. }
  1907. case MONO_TYPE_MVAR: {
  1908. MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
  1909. if (type->data.generic_param->image == image)
  1910. return TRUE;
  1911. if (container) {
  1912. g_assert (container->is_method);
  1913. if (!container->owner.method)
  1914. /* RefEmit created generic param whose method is not finished */
  1915. return container->image == image;
  1916. return container->owner.method->klass->image == image;
  1917. } else {
  1918. return type->data.generic_param->image == image;
  1919. }
  1920. }
  1921. default:
  1922. /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
  1923. return image == mono_class_from_mono_type (type)->image;
  1924. }
  1925. }
  1926. /*
  1927. * get_image_set:
  1928. *
  1929. * Return a MonoImageSet representing the set of images in IMAGES.
  1930. *
  1931. * LOCKING: Assumes the loader lock is held.
  1932. */
  1933. static MonoImageSet*
  1934. get_image_set (MonoImage **images, int nimages)
  1935. {
  1936. int i, j, k;
  1937. MonoImageSet *set;
  1938. GSList *l;
  1939. if (!image_sets)
  1940. image_sets = g_ptr_array_new ();
  1941. /* Common case */
  1942. if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
  1943. return mscorlib_image_set;
  1944. /* Happens with empty generic instances */
  1945. if (nimages == 0)
  1946. return mscorlib_image_set;
  1947. if (images [0] == mono_defaults.corlib && nimages > 1)
  1948. l = images [1]->image_sets;
  1949. else
  1950. l = images [0]->image_sets;
  1951. set = NULL;
  1952. for (; l; l = l->next) {
  1953. set = l->data;
  1954. if (set->nimages == nimages) {
  1955. for (j = 0; j < nimages; ++j) {
  1956. for (k = 0; k < nimages; ++k)
  1957. if (set->images [k] == images [j])
  1958. break;
  1959. if (k == nimages)
  1960. /* Not found */
  1961. break;
  1962. }
  1963. if (j == nimages)
  1964. /* Found */
  1965. break;
  1966. }
  1967. }
  1968. if (!l) {
  1969. /* Not found */
  1970. set = g_new0 (MonoImageSet, 1);
  1971. set->nimages = nimages;
  1972. set->images = g_new0 (MonoImage*, nimages);
  1973. InitializeCriticalSection (&set->lock);
  1974. for (i = 0; i < nimages; ++i)
  1975. set->images [i] = images [i];
  1976. set->gclass_cache = g_hash_table_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
  1977. set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
  1978. set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
  1979. set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
  1980. for (i = 0; i < nimages; ++i)
  1981. set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
  1982. g_ptr_array_add (image_sets, set);
  1983. }
  1984. if (nimages == 1 && images [0] == mono_defaults.corlib)
  1985. mscorlib_image_set = set;
  1986. return set;
  1987. }
  1988. static void
  1989. delete_image_set (MonoImageSet *set)
  1990. {
  1991. int i;
  1992. g_hash_table_destroy (set->gclass_cache);
  1993. g_hash_table_destroy (set->ginst_cache);
  1994. g_hash_table_destroy (set->gmethod_cache);
  1995. g_hash_table_destroy (set->gsignature_cache);
  1996. for (i = 0; i < set->nimages; ++i)
  1997. set->images [i]->image_sets = g_slist_remove (set->images [i]->image_sets, set);
  1998. g_ptr_array_remove (image_sets, set);
  1999. if (set->mempool)
  2000. mono_mempool_destroy (set->mempool);
  2001. g_free (set->images);
  2002. DeleteCriticalSection (&set->lock);
  2003. g_free (set);
  2004. }
  2005. static void
  2006. mono_image_set_lock (MonoImageSet *set)
  2007. {
  2008. EnterCriticalSection (&set->lock);
  2009. }
  2010. static void
  2011. mono_image_set_unlock (MonoImageSet *set)
  2012. {
  2013. LeaveCriticalSection (&set->lock);
  2014. }
  2015. gpointer
  2016. mono_image_set_alloc (MonoImageSet *set, guint size)
  2017. {
  2018. gpointer res;
  2019. mono_image_set_lock (set);
  2020. if (!set->mempool)
  2021. set->mempool = mono_mempool_new_size (1024);
  2022. res = mono_mempool_alloc (set->mempool, size);
  2023. mono_image_set_unlock (set);
  2024. return res;
  2025. }
  2026. gpointer
  2027. mono_image_set_alloc0 (MonoImageSet *set, guint size)
  2028. {
  2029. gpointer res;
  2030. mono_image_set_lock (set);
  2031. if (!set->mempool)
  2032. set->mempool = mono_mempool_new_size (1024);
  2033. res = mono_mempool_alloc0 (set->mempool, size);
  2034. mono_image_set_unlock (set);
  2035. return res;
  2036. }
  2037. char*
  2038. mono_image_set_strdup (MonoImageSet *set, const char *s)
  2039. {
  2040. char *res;
  2041. mono_image_set_lock (set);
  2042. if (!set->mempool)
  2043. set->mempool = mono_mempool_new_size (1024);
  2044. res = mono_mempool_strdup (set->mempool, s);
  2045. mono_image_set_unlock (set);
  2046. return res;
  2047. }
  2048. /*
  2049. * Structure used by the collect_..._images functions to store the image list.
  2050. */
  2051. typedef struct {
  2052. MonoImage *image_buf [64];
  2053. MonoImage **images;
  2054. int nimages, images_len;
  2055. } CollectData;
  2056. static void
  2057. collect_data_init (CollectData *data)
  2058. {
  2059. data->images = data->image_buf;
  2060. data->images_len = 64;
  2061. data->nimages = 0;
  2062. }
  2063. static void
  2064. collect_data_free (CollectData *data)
  2065. {
  2066. if (data->images != data->image_buf)
  2067. g_free (data->images);
  2068. }
  2069. static void
  2070. enlarge_data (CollectData *data)
  2071. {
  2072. int new_len = data->images_len < 16 ? 16 : data->images_len * 2;
  2073. MonoImage **d = g_new (MonoImage *, new_len);
  2074. // FIXME: test this
  2075. g_assert_not_reached ();
  2076. memcpy (d, data->images, data->images_len);
  2077. if (data->images != data->image_buf)
  2078. g_free (data->images);
  2079. data->images = d;
  2080. data->images_len = new_len;
  2081. }
  2082. static inline void
  2083. add_image (MonoImage *image, CollectData *data)
  2084. {
  2085. int i;
  2086. /* The arrays are small, so use a linear search instead of a hash table */
  2087. for (i = 0; i < data->nimages; ++i)
  2088. if (data->images [i] == image)
  2089. return;
  2090. if (data->nimages == data->images_len)
  2091. enlarge_data (data);
  2092. data->images [data->nimages ++] = image;
  2093. }
  2094. static void
  2095. collect_type_images (MonoType *type, CollectData *data);
  2096. static void
  2097. collect_ginst_images (MonoGenericInst *ginst, CollectData *data)
  2098. {
  2099. int i;
  2100. for (i = 0; i < ginst->type_argc; ++i) {
  2101. collect_type_images (ginst->type_argv [i], data);
  2102. }
  2103. }
  2104. static void
  2105. collect_gclass_images (MonoGenericClass *gclass, CollectData *data)
  2106. {
  2107. add_image (gclass->container_class->image, data);
  2108. if (gclass->context.class_inst)
  2109. collect_ginst_images (gclass->context.class_inst, data);
  2110. }
  2111. static void
  2112. collect_signature_images (MonoMethodSignature *sig, CollectData *data)
  2113. {
  2114. gpointer iter = NULL;
  2115. MonoType *p;
  2116. collect_type_images (mono_signature_get_return_type (sig), data);
  2117. while ((p = mono_signature_get_params (sig, &iter)) != NULL)
  2118. collect_type_images (p, data);
  2119. }
  2120. static void
  2121. collect_inflated_signature_images (MonoInflatedMethodSignature *sig, CollectData *data)
  2122. {
  2123. collect_signature_images (sig->sig, data);
  2124. if (sig->context.class_inst)
  2125. collect_ginst_images (sig->context.class_inst, data);
  2126. if (sig->context.method_inst)
  2127. collect_ginst_images (sig->context.method_inst, data);
  2128. }
  2129. static void
  2130. collect_method_images (MonoMethodInflated *method, CollectData *data)
  2131. {
  2132. add_image (method->declaring->klass->image, data);
  2133. if (method->context.class_inst)
  2134. collect_ginst_images (method->context.class_inst, data);
  2135. if (method->context.method_inst)
  2136. collect_ginst_images (method->context.method_inst, data);
  2137. /*
  2138. if (((MonoMethod*)method)->signature)
  2139. collect_signature_images (mono_method_signature ((MonoMethod*)method), data);
  2140. */
  2141. }
  2142. static void
  2143. collect_type_images (MonoType *type, CollectData *data)
  2144. {
  2145. retry:
  2146. switch (type->type) {
  2147. case MONO_TYPE_GENERICINST:
  2148. collect_gclass_images (type->data.generic_class, data);
  2149. break;
  2150. case MONO_TYPE_PTR:
  2151. type = type->data.type;
  2152. goto retry;
  2153. case MONO_TYPE_SZARRAY:
  2154. type = &type->data.klass->byval_arg;
  2155. goto retry;
  2156. case MONO_TYPE_ARRAY:
  2157. type = &type->data.array->eklass->byval_arg;
  2158. goto retry;
  2159. case MONO_TYPE_FNPTR:
  2160. //return signature_in_image (type->data.method, image);
  2161. g_assert_not_reached ();
  2162. case MONO_TYPE_VAR: {
  2163. MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
  2164. if (container) {
  2165. g_assert (!container->is_method);
  2166. /*
  2167. * FIXME: The following check is here solely
  2168. * for monodis, which uses the internal
  2169. * function
  2170. * mono_metadata_load_generic_params(). The
  2171. * caller of that function needs to fill in
  2172. * owner->klass or owner->method of the
  2173. * returned struct, but monodis doesn't do
  2174. * that. The image unloading depends on that,
  2175. * however, so a crash results without this
  2176. * check.
  2177. */
  2178. if (!container->owner.klass)
  2179. add_image (container->image, data);
  2180. else
  2181. add_image (container->owner.klass->image, data);
  2182. } else {
  2183. add_image (type->data.generic_param->image, data);
  2184. }
  2185. }
  2186. break;
  2187. case MONO_TYPE_MVAR: {
  2188. MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
  2189. if (type->data.generic_param->image)
  2190. add_image (type->data.generic_param->image, data);
  2191. if (container) {
  2192. if (!container->owner.method) {
  2193. /* RefEmit created generic param whose method is not finished */
  2194. add_image (container->image, data);
  2195. } else {
  2196. g_assert (container->is_method);
  2197. add_image (container->owner.method->klass->image, data);
  2198. }
  2199. } else {
  2200. add_image (type->data.generic_param->image, data);
  2201. }
  2202. }
  2203. break;
  2204. case MONO_TYPE_CLASS:
  2205. case MONO_TYPE_VALUETYPE:
  2206. add_image (mono_class_from_mono_type (type)->image, data);
  2207. break;
  2208. default:
  2209. add_image (mono_defaults.corlib, data);
  2210. }
  2211. }
  2212. typedef struct {
  2213. MonoImage *image;
  2214. GSList *list;
  2215. } CleanForImageUserData;
  2216. static gboolean
  2217. steal_gclass_in_image (gpointer key, gpointer value, gpointer data)
  2218. {
  2219. MonoGenericClass *gclass = key;
  2220. CleanForImageUserData *user_data = data;
  2221. g_assert (gclass_in_image (gclass, user_data->image));
  2222. user_data->list = g_slist_prepend (user_data->list, gclass);
  2223. return TRUE;
  2224. }
  2225. static gboolean
  2226. steal_ginst_in_image (gpointer key, gpointer value, gpointer data)
  2227. {
  2228. MonoGenericInst *ginst = key;
  2229. CleanForImageUserData *user_data = data;
  2230. // This doesn't work during corlib compilation
  2231. //g_assert (ginst_in_image (ginst, user_data->image));
  2232. user_data->list = g_slist_prepend (user_data->list, ginst);
  2233. return TRUE;
  2234. }
  2235. static gboolean
  2236. inflated_method_in_image (gpointer key, gpointer value, gpointer data)
  2237. {
  2238. MonoImage *image = data;
  2239. MonoMethodInflated *method = key;
  2240. // FIXME:
  2241. // https://bugzilla.novell.com/show_bug.cgi?id=458168
  2242. g_assert (method->declaring->klass->image == image ||
  2243. (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
  2244. (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image)));
  2245. return TRUE;
  2246. }
  2247. static gboolean
  2248. inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
  2249. {
  2250. MonoImage *image = data;
  2251. MonoInflatedMethodSignature *sig = key;
  2252. return signature_in_image (sig->sig, image) ||
  2253. (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
  2254. (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
  2255. }
  2256. static void
  2257. check_gmethod (gpointer key, gpointer value, gpointer data)
  2258. {
  2259. MonoMethodInflated *method = key;
  2260. MonoImage *image = data;
  2261. if (method->context.class_inst)
  2262. g_assert (!ginst_in_image (method->context.class_inst, image));
  2263. if (method->context.method_inst)
  2264. g_assert (!ginst_in_image (method->context.method_inst, image));
  2265. if (((MonoMethod*)method)->signature)
  2266. g_assert (!signature_in_image (mono_method_signature ((MonoMethod*)method), image));
  2267. }
  2268. /*
  2269. * check_image_sets:
  2270. *
  2271. * Run a consistency check on the image set data structures.
  2272. */
  2273. static G_GNUC_UNUSED void
  2274. check_image_sets (MonoImage *image)
  2275. {
  2276. int i;
  2277. GSList *l = image->image_sets;
  2278. if (!image_sets)
  2279. return;
  2280. for (i = 0; i < image_sets->len; ++i) {
  2281. MonoImageSet *set = g_ptr_array_index (image_sets, i);
  2282. if (!g_slist_find (l, set)) {
  2283. g_hash_table_foreach (set->gmethod_cache, check_gmethod, image);
  2284. }
  2285. }
  2286. }
  2287. GSList*
  2288. mono_metadata_clean_for_image (MonoImage *image)
  2289. {
  2290. CleanForImageUserData ginst_data, gclass_data;
  2291. GSList *l, *set_list, *free_list = NULL;
  2292. //check_image_sets (image);
  2293. /*
  2294. * The data structures could reference each other so we delete them in two phases.
  2295. * This is required because of the hashing functions in gclass/ginst_cache.
  2296. */
  2297. ginst_data.image = gclass_data.image = image;
  2298. ginst_data.list = gclass_data.list = NULL;
  2299. mono_loader_lock ();
  2300. /* Collect the items to delete */
  2301. /* delete_image_set () modifies the lists so make a copy */
  2302. for (l = image->image_sets; l; l = l->next) {
  2303. MonoImageSet *set = l->data;
  2304. g_hash_table_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
  2305. g_hash_table_foreach_steal (set->ginst_cache, steal_ginst_in_image, &ginst_data);
  2306. g_hash_table_foreach_remove (set->gmethod_cache, inflated_method_in_image, image);
  2307. g_hash_table_foreach_remove (set->gsignature_cache, inflated_signature_in_image, image);
  2308. }
  2309. /* Delete the removed items */
  2310. for (l = ginst_data.list; l; l = l->next)
  2311. free_generic_inst (l->data);
  2312. for (l = gclass_data.list; l; l = l->next)
  2313. free_generic_class (l->data);
  2314. g_slist_free (ginst_data.list);
  2315. g_slist_free (gclass_data.list);
  2316. /* delete_image_set () modifies the lists so make a copy */
  2317. set_list = g_slist_copy (image->image_sets);
  2318. for (l = set_list; l; l = l->next) {
  2319. MonoImageSet *set = l->data;
  2320. delete_image_set (set);
  2321. }
  2322. g_slist_free (set_list);
  2323. mono_loader_unlock ();
  2324. return free_list;
  2325. }
  2326. static void
  2327. free_inflated_method (MonoMethodInflated *imethod)
  2328. {
  2329. int i;
  2330. MonoMethod *method = (MonoMethod*)imethod;
  2331. mono_marshal_free_inflated_wrappers (method);
  2332. if (method->signature)
  2333. mono_metadata_free_inflated_signature (method->signature);
  2334. if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))) {
  2335. MonoMethodHeader *header = imethod->header;
  2336. if (header) {
  2337. /* Allocated in inflate_generic_header () */
  2338. for (i = 0; i < header->num_locals; ++i)
  2339. mono_metadata_free_type (header->locals [i]);
  2340. g_free (header->clauses);
  2341. g_free (header);
  2342. }
  2343. }
  2344. g_free (method);
  2345. }
  2346. static void
  2347. free_generic_inst (MonoGenericInst *ginst)
  2348. {
  2349. int i;
  2350. /* The ginst itself is allocated from the image set mempool */
  2351. for (i = 0; i < ginst->type_argc; ++i)
  2352. mono_metadata_free_type (ginst->type_argv [i]);
  2353. }
  2354. static void
  2355. free_generic_class (MonoGenericClass *gclass)
  2356. {
  2357. /* The gclass itself is allocated from the image set mempool */
  2358. if (gclass->is_dynamic)
  2359. mono_reflection_free_dynamic_generic_class (gclass);
  2360. if (gclass->cached_class && gclass->cached_class->interface_id)
  2361. mono_unload_interface_id (gclass->cached_class);
  2362. }
  2363. static void
  2364. free_inflated_signature (MonoInflatedMethodSignature *sig)
  2365. {
  2366. mono_metadata_free_inflated_signature (sig->sig);
  2367. g_free (sig);
  2368. }
  2369. /*
  2370. * LOCKING: assumes the loader lock is held.
  2371. */
  2372. MonoMethodInflated*
  2373. mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
  2374. {
  2375. CollectData data;
  2376. MonoImageSet *set;
  2377. collect_data_init (&data);
  2378. collect_method_images (method, &data);
  2379. set = get_image_set (data.images, data.nimages);
  2380. collect_data_free (&data);
  2381. if (cache) {
  2382. g_hash_table_insert (set->gmethod_cache, method, method);
  2383. return method;
  2384. } else {
  2385. return g_hash_table_lookup (set->gmethod_cache, method);
  2386. }
  2387. }
  2388. /*
  2389. * mono_metadata_get_inflated_signature:
  2390. *
  2391. * Given an inflated signature and a generic context, return a canonical copy of the
  2392. * signature. The returned signature might be equal to SIG or it might be a cached copy.
  2393. */
  2394. MonoMethodSignature *
  2395. mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context)
  2396. {
  2397. MonoInflatedMethodSignature helper;
  2398. MonoInflatedMethodSignature *res;
  2399. CollectData data;
  2400. MonoImageSet *set;
  2401. mono_loader_lock ();
  2402. helper.sig = sig;
  2403. helper.context.class_inst = context->class_inst;
  2404. helper.context.method_inst = context->method_inst;
  2405. collect_data_init (&data);
  2406. collect_inflated_signature_images (&helper, &data);
  2407. set = get_image_set (data.images, data.nimages);
  2408. collect_data_free (&data);
  2409. res = g_hash_table_lookup (set->gsignature_cache, &helper);
  2410. if (!res) {
  2411. res = g_new0 (MonoInflatedMethodSignature, 1);
  2412. res->sig = sig;
  2413. res->context.class_inst = context->class_inst;
  2414. res->context.method_inst = context->method_inst;
  2415. g_hash_table_insert (set->gsignature_cache, res, res);
  2416. }
  2417. mono_loader_unlock ();
  2418. return res->sig;
  2419. }
  2420. /*
  2421. * mono_metadata_get_generic_inst:
  2422. *
  2423. * Given a list of types, return a MonoGenericInst that represents that list.
  2424. * The returned MonoGenericInst has its own copy of the list of types. The list
  2425. * passed in the argument can be freed, modified or disposed of.
  2426. *
  2427. */
  2428. MonoGenericInst *
  2429. mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
  2430. {
  2431. MonoGenericInst *ginst;
  2432. gboolean is_open;
  2433. int i;
  2434. int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
  2435. CollectData data;
  2436. MonoImageSet *set;
  2437. for (i = 0; i < type_argc; ++i)
  2438. if (mono_class_is_open_constructed_type (type_argv [i]))
  2439. break;
  2440. is_open = (i < type_argc);
  2441. ginst = g_alloca (size);
  2442. memset (ginst, 0, sizeof (MonoGenericInst));
  2443. ginst->is_open = is_open;
  2444. ginst->type_argc = type_argc;
  2445. memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
  2446. mono_loader_lock ();
  2447. collect_data_init (&data);
  2448. collect_ginst_images (ginst, &data);
  2449. set = get_image_set (data.images, data.nimages);
  2450. collect_data_free (&data);
  2451. ginst = g_hash_table_lookup (set->ginst_cache, ginst);
  2452. if (!ginst) {
  2453. ginst = mono_image_set_alloc0 (set, size);
  2454. #ifndef MONO_SMALL_CONFIG
  2455. ginst->id = ++next_generic_inst_id;
  2456. #endif
  2457. ginst->is_open = is_open;
  2458. ginst->type_argc = type_argc;
  2459. for (i = 0; i < type_argc; ++i)
  2460. ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
  2461. g_hash_table_insert (set->ginst_cache, ginst, ginst);
  2462. }
  2463. mono_loader_unlock ();
  2464. return ginst;
  2465. }
  2466. static gboolean
  2467. mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
  2468. {
  2469. MonoGenericContainer *container = container_class->generic_container;
  2470. if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
  2471. return FALSE;
  2472. return inst == container->context.class_inst;
  2473. }
  2474. /*
  2475. * mono_metadata_lookup_generic_class:
  2476. *
  2477. * Returns a MonoGenericClass with the given properties.
  2478. *
  2479. */
  2480. MonoGenericClass *
  2481. mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
  2482. {
  2483. MonoGenericClass *gclass;
  2484. MonoGenericClass helper;
  2485. gboolean is_tb_open = mono_metadata_is_type_builder_generic_type_definition (container_class, inst, is_dynamic);
  2486. MonoImageSet *set;
  2487. CollectData data;
  2488. helper.container_class = container_class;
  2489. helper.context.class_inst = inst;
  2490. helper.context.method_inst = NULL;
  2491. helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
  2492. helper.is_tb_open = is_tb_open;
  2493. helper.cached_class = NULL;
  2494. mono_loader_lock ();
  2495. collect_data_init (&data);
  2496. collect_gclass_images (&helper, &data);
  2497. set = get_image_set (data.images, data.nimages);
  2498. collect_data_free (&data);
  2499. gclass = g_hash_table_lookup (set->gclass_cache, &helper);
  2500. /* A tripwire just to keep us honest */
  2501. g_assert (!helper.cached_class);
  2502. if (gclass) {
  2503. mono_loader_unlock ();
  2504. return gclass;
  2505. }
  2506. if (is_dynamic) {
  2507. MonoDynamicGenericClass *dgclass = mono_image_set_new0 (set, MonoDynamicGenericClass, 1);
  2508. gclass = &dgclass->generic_class;
  2509. gclass->is_dynamic = 1;
  2510. } else {
  2511. gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
  2512. }
  2513. gclass->is_tb_open = is_tb_open;
  2514. gclass->container_class = container_class;
  2515. gclass->context.class_inst = inst;
  2516. gclass->context.method_inst = NULL;
  2517. gclass->owner = set;
  2518. if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
  2519. gclass->cached_class = container_class;
  2520. g_hash_table_insert (set->gclass_cache, gclass, gclass);
  2521. mono_loader_unlock ();
  2522. return gclass;
  2523. }
  2524. /*
  2525. * mono_metadata_inflate_generic_inst:
  2526. *
  2527. * Instantiate the generic instance @ginst with the context @context.
  2528. * Check @error for success.
  2529. *
  2530. */
  2531. MonoGenericInst *
  2532. mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context, MonoError *error)
  2533. {
  2534. MonoType **type_argv;
  2535. MonoGenericInst *nginst = NULL;
  2536. int i, count = 0;
  2537. mono_error_init (error);
  2538. if (!ginst->is_open)
  2539. return ginst;
  2540. type_argv = g_new0 (MonoType*, ginst->type_argc);
  2541. for (i = 0; i < ginst->type_argc; i++) {
  2542. type_argv [i] = mono_class_inflate_generic_type_checked (ginst->type_argv [i], context, error);
  2543. if (!mono_error_ok (error))
  2544. goto cleanup;
  2545. ++count;
  2546. }
  2547. nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
  2548. cleanup:
  2549. for (i = 0; i < count; i++)
  2550. mono_metadata_free_type (type_argv [i]);
  2551. g_free (type_argv);
  2552. return nginst;
  2553. }
  2554. MonoGenericInst *
  2555. mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
  2556. int count, const char *ptr, const char **rptr)
  2557. {
  2558. MonoType **type_argv;
  2559. MonoGenericInst *ginst;
  2560. int i;
  2561. type_argv = g_new0 (MonoType*, count);
  2562. for (i = 0; i < count; i++) {
  2563. MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
  2564. if (!t) {
  2565. g_free (type_argv);
  2566. return NULL;
  2567. }
  2568. type_argv [i] = t;
  2569. }
  2570. if (rptr)
  2571. *rptr = ptr;
  2572. ginst = mono_metadata_get_generic_inst (count, type_argv);
  2573. g_free (type_argv);
  2574. return ginst;
  2575. }
  2576. static gboolean
  2577. do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
  2578. const char *ptr, const char **rptr)
  2579. {
  2580. MonoGenericInst *inst;
  2581. MonoClass *gklass;
  2582. MonoType *gtype;
  2583. int count;
  2584. gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
  2585. if (gtype == NULL)
  2586. return FALSE;
  2587. gklass = mono_class_from_mono_type (gtype);
  2588. if (!gklass->generic_container)
  2589. return FALSE;
  2590. count = mono_metadata_decode_value (ptr, &ptr);
  2591. inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
  2592. if (inst == NULL)
  2593. return FALSE;
  2594. if (rptr)
  2595. *rptr = ptr;
  2596. type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
  2597. return TRUE;
  2598. }
  2599. /*
  2600. * select_container:
  2601. * @gc: The generic container to normalize
  2602. * @type: The kind of generic parameters the resulting generic-container should contain
  2603. */
  2604. static MonoGenericContainer *
  2605. select_container (MonoGenericContainer *gc, MonoTypeEnum type)
  2606. {
  2607. gboolean is_var = (type == MONO_TYPE_VAR);
  2608. if (!gc)
  2609. return NULL;
  2610. g_assert (is_var || type == MONO_TYPE_MVAR);
  2611. if (is_var) {
  2612. if (gc->is_method || gc->parent)
  2613. /*
  2614. * The current MonoGenericContainer is a generic method -> its `parent'
  2615. * points to the containing class'es container.
  2616. */
  2617. return gc->parent;
  2618. }
  2619. return gc;
  2620. }
  2621. /*
  2622. * mono_metadata_parse_generic_param:
  2623. * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
  2624. * see mono_metadata_parse_type_full() for details.
  2625. * Internal routine to parse a generic type parameter.
  2626. * LOCKING: Acquires the loader lock
  2627. */
  2628. static MonoGenericParam *
  2629. mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
  2630. MonoTypeEnum type, const char *ptr, const char **rptr)
  2631. {
  2632. int index = mono_metadata_decode_value (ptr, &ptr);
  2633. if (rptr)
  2634. *rptr = ptr;
  2635. generic_container = select_container (generic_container, type);
  2636. if (!generic_container) {
  2637. /* Create dummy MonoGenericParam */
  2638. MonoGenericParam *param;
  2639. param = mono_image_alloc0 (m, sizeof (MonoGenericParam));
  2640. param->num = index;
  2641. param->image = m;
  2642. return param;
  2643. }
  2644. if (index >= generic_container->type_argc)
  2645. return NULL;
  2646. return mono_generic_container_get_param (generic_container, index);
  2647. }
  2648. /*
  2649. * mono_metadata_get_shared_type:
  2650. *
  2651. * Return a shared instance of TYPE, if available, NULL otherwise.
  2652. * Shared MonoType instances help save memory. Their contents should not be modified
  2653. * by the caller. They do not need to be freed as their lifetime is bound by either
  2654. * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
  2655. * instance they are embedded in. If they are freed, they should be freed using
  2656. * mono_metadata_free_type () instead of g_free ().
  2657. */
  2658. MonoType*
  2659. mono_metadata_get_shared_type (MonoType *type)
  2660. {
  2661. MonoType *cached;
  2662. /* No need to use locking since nobody is modifying the hash table */
  2663. if ((cached = g_hash_table_lookup (type_cache, type)))
  2664. return cached;
  2665. switch (type->type){
  2666. case MONO_TYPE_CLASS:
  2667. case MONO_TYPE_VALUETYPE:
  2668. if (type == &type->data.klass->byval_arg)
  2669. return type;
  2670. if (type == &type->data.klass->this_arg)
  2671. return type;
  2672. break;
  2673. }
  2674. return NULL;
  2675. }
  2676. static gboolean
  2677. compare_type_literals (int class_type, int type_type)
  2678. {
  2679. /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
  2680. * See mcs/test/gtest-440. and #650936.
  2681. * FIXME This better be moved to the metadata verifier as it can catch more cases.
  2682. */
  2683. if (!class_type)
  2684. return TRUE;
  2685. /* NET 1.1 assemblies might encode string and object in a denormalized way.
  2686. * See #675464.
  2687. */
  2688. if (type_type == MONO_TYPE_CLASS && (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT))
  2689. return TRUE;
  2690. return class_type == type_type;
  2691. }
  2692. /*
  2693. * do_mono_metadata_parse_type:
  2694. * @type: MonoType to be filled in with the return value
  2695. * @m: image context
  2696. * @generic_context: generics_context
  2697. * @transient: whenever to allocate data from the heap
  2698. * @ptr: pointer to the encoded type
  2699. * @rptr: pointer where the end of the encoded type is saved
  2700. *
  2701. * Internal routine used to "fill" the contents of @type from an
  2702. * allocated pointer. This is done this way to avoid doing too
  2703. * many mini-allocations (particularly for the MonoFieldType which
  2704. * most of the time is just a MonoType, but sometimes might be augmented).
  2705. *
  2706. * This routine is used by mono_metadata_parse_type and
  2707. * mono_metadata_parse_field_type
  2708. *
  2709. * This extracts a Type as specified in Partition II (22.2.12)
  2710. *
  2711. * Returns: FALSE if the type could not be loaded
  2712. */
  2713. static gboolean
  2714. do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
  2715. gboolean transient, const char *ptr, const char **rptr)
  2716. {
  2717. gboolean ok = TRUE;
  2718. type->type = mono_metadata_decode_value (ptr, &ptr);
  2719. switch (type->type){
  2720. case MONO_TYPE_VOID:
  2721. case MONO_TYPE_BOOLEAN:
  2722. case MONO_TYPE_CHAR:
  2723. case MONO_TYPE_I1:
  2724. case MONO_TYPE_U1:
  2725. case MONO_TYPE_I2:
  2726. case MONO_TYPE_U2:
  2727. case MONO_TYPE_I4:
  2728. case MONO_TYPE_U4:
  2729. case MONO_TYPE_I8:
  2730. case MONO_TYPE_U8:
  2731. case MONO_TYPE_R4:
  2732. case MONO_TYPE_R8:
  2733. case MONO_TYPE_I:
  2734. case MONO_TYPE_U:
  2735. case MONO_TYPE_STRING:
  2736. case MONO_TYPE_OBJECT:
  2737. case MONO_TYPE_TYPEDBYREF:
  2738. break;
  2739. case MONO_TYPE_VALUETYPE:
  2740. case MONO_TYPE_CLASS: {
  2741. guint32 token;
  2742. MonoClass *class;
  2743. token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
  2744. class = mono_class_get (m, token);
  2745. type->data.klass = class;
  2746. if (!class)
  2747. return FALSE;
  2748. if (!compare_type_literals (class->byval_arg.type, type->type))
  2749. return FALSE;
  2750. break;
  2751. }
  2752. case MONO_TYPE_SZARRAY: {
  2753. MonoType *etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
  2754. if (!etype)
  2755. return FALSE;
  2756. type->data.klass = mono_class_from_mono_type (etype);
  2757. if (!type->data.klass)
  2758. return FALSE;
  2759. break;
  2760. }
  2761. case MONO_TYPE_PTR:
  2762. type->data.type = mono_metadata_parse_type_internal (m, container, MONO_PARSE_MOD_TYPE, 0, transient, ptr, &ptr);
  2763. if (!type->data.type)
  2764. return FALSE;
  2765. break;
  2766. case MONO_TYPE_FNPTR:
  2767. type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
  2768. if (!type->data.method)
  2769. return FALSE;
  2770. break;
  2771. case MONO_TYPE_ARRAY:
  2772. type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr);
  2773. if (!type->data.array)
  2774. return FALSE;
  2775. break;
  2776. case MONO_TYPE_MVAR:
  2777. if (container && !container->is_method)
  2778. return FALSE;
  2779. case MONO_TYPE_VAR:
  2780. type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
  2781. if (!type->data.generic_param)
  2782. return FALSE;
  2783. break;
  2784. case MONO_TYPE_GENERICINST:
  2785. ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
  2786. break;
  2787. default:
  2788. g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type->type, m->name);
  2789. return FALSE;
  2790. }
  2791. if (rptr)
  2792. *rptr = ptr;
  2793. return ok;
  2794. }
  2795. /*
  2796. * mono_metadata_free_type:
  2797. * @type: type to free
  2798. *
  2799. * Free the memory allocated for type @type which is allocated on the heap.
  2800. */
  2801. void
  2802. mono_metadata_free_type (MonoType *type)
  2803. {
  2804. if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
  2805. return;
  2806. switch (type->type){
  2807. case MONO_TYPE_OBJECT:
  2808. case MONO_TYPE_STRING:
  2809. if (!type->data.klass)
  2810. break;
  2811. /* fall through */
  2812. case MONO_TYPE_CLASS:
  2813. case MONO_TYPE_VALUETYPE:
  2814. if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
  2815. return;
  2816. break;
  2817. case MONO_TYPE_PTR:
  2818. mono_metadata_free_type (type->data.type);
  2819. break;
  2820. case MONO_TYPE_FNPTR:
  2821. mono_metadata_free_method_signature (type->data.method);
  2822. break;
  2823. case MONO_TYPE_ARRAY:
  2824. mono_metadata_free_array (type->data.array);
  2825. break;
  2826. }
  2827. g_free (type);
  2828. }
  2829. #if 0
  2830. static void
  2831. hex_dump (const char *buffer, int base, int count)
  2832. {
  2833. int show_header = 1;
  2834. int i;
  2835. if (count < 0){
  2836. count = -count;
  2837. show_header = 0;
  2838. }
  2839. for (i = 0; i < count; i++){
  2840. if (show_header)
  2841. if ((i % 16) == 0)
  2842. printf ("\n0x%08x: ", (unsigned char) base + i);
  2843. printf ("%02x ", (unsigned char) (buffer [i]));
  2844. }
  2845. fflush (stdout);
  2846. }
  2847. #endif
  2848. /**
  2849. * @ptr: Points to the beginning of the Section Data (25.3)
  2850. */
  2851. static MonoExceptionClause*
  2852. parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr)
  2853. {
  2854. unsigned char sect_data_flags;
  2855. const unsigned char *sptr;
  2856. int is_fat;
  2857. guint32 sect_data_len;
  2858. MonoExceptionClause* clauses = NULL;
  2859. while (1) {
  2860. /* align on 32-bit boundary */
  2861. sptr = ptr = dword_align (ptr);
  2862. sect_data_flags = *ptr;
  2863. ptr++;
  2864. is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
  2865. if (is_fat) {
  2866. sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
  2867. ptr += 3;
  2868. } else {
  2869. sect_data_len = ptr [0];
  2870. ++ptr;
  2871. }
  2872. /*
  2873. g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
  2874. hex_dump (sptr, 0, sect_data_len+8);
  2875. g_print ("\nheader: ");
  2876. hex_dump (sptr-4, 0, 4);
  2877. g_print ("\n");
  2878. */
  2879. if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
  2880. const unsigned char *p = dword_align (ptr);
  2881. int i;
  2882. *num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
  2883. /* we could just store a pointer if we don't need to byteswap */
  2884. clauses = g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses));
  2885. for (i = 0; i < *num_clauses; ++i) {
  2886. MonoExceptionClause *ec = &clauses [i];
  2887. guint32 tof_value;
  2888. if (is_fat) {
  2889. ec->flags = read32 (p);
  2890. ec->try_offset = read32 (p + 4);
  2891. ec->try_len = read32 (p + 8);
  2892. ec->handler_offset = read32 (p + 12);
  2893. ec->handler_len = read32 (p + 16);
  2894. tof_value = read32 (p + 20);
  2895. p += 24;
  2896. } else {
  2897. ec->flags = read16 (p);
  2898. ec->try_offset = read16 (p + 2);
  2899. ec->try_len = *(p + 4);
  2900. ec->handler_offset = read16 (p + 5);
  2901. ec->handler_len = *(p + 7);
  2902. tof_value = read32 (p + 8);
  2903. p += 12;
  2904. }
  2905. if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
  2906. ec->data.filter_offset = tof_value;
  2907. } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
  2908. ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
  2909. } else {
  2910. ec->data.catch_class = NULL;
  2911. }
  2912. /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
  2913. }
  2914. }
  2915. if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
  2916. ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
  2917. else
  2918. return clauses;
  2919. }
  2920. }
  2921. /*
  2922. * mono_method_get_header_summary:
  2923. * @method: The method to get the header.
  2924. * @summary: Where to store the header
  2925. *
  2926. *
  2927. * Returns: true if the header was properly decoded.
  2928. */
  2929. gboolean
  2930. mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *summary)
  2931. {
  2932. int idx;
  2933. guint32 rva;
  2934. MonoImage* img;
  2935. const char *ptr;
  2936. unsigned char flags, format;
  2937. guint16 fat_flags;
  2938. /*Only the GMD has a pointer to the metadata.*/
  2939. while (method->is_inflated)
  2940. method = ((MonoMethodInflated*)method)->declaring;
  2941. summary->code_size = 0;
  2942. summary->has_clauses = FALSE;
  2943. /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
  2944. if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
  2945. return FALSE;
  2946. if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
  2947. MonoMethodHeader *header = ((MonoMethodWrapper *)method)->header;
  2948. if (!header)
  2949. return FALSE;
  2950. summary->code_size = header->code_size;
  2951. summary->has_clauses = header->num_clauses > 0;
  2952. return TRUE;
  2953. }
  2954. idx = mono_metadata_token_index (method->token);
  2955. img = method->klass->image;
  2956. rva = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_RVA);
  2957. /*We must run the verifier since we'll be decoding it.*/
  2958. if (!mono_verifier_verify_method_header (img, rva, NULL))
  2959. return FALSE;
  2960. ptr = mono_image_rva_map (img, rva);
  2961. g_assert (ptr);
  2962. flags = *(const unsigned char *)ptr;
  2963. format = flags & METHOD_HEADER_FORMAT_MASK;
  2964. switch (format) {
  2965. case METHOD_HEADER_TINY_FORMAT:
  2966. ptr++;
  2967. summary->code_size = flags >> 2;
  2968. break;
  2969. case METHOD_HEADER_FAT_FORMAT:
  2970. fat_flags = read16 (ptr);
  2971. ptr += 4;
  2972. summary->code_size = read32 (ptr);
  2973. if (fat_flags & METHOD_HEADER_MORE_SECTS)
  2974. summary->has_clauses = TRUE;
  2975. break;
  2976. default:
  2977. return FALSE;
  2978. }
  2979. return TRUE;
  2980. }
  2981. /*
  2982. * mono_metadata_parse_mh_full:
  2983. * @m: metadata context
  2984. * @generic_context: generics context
  2985. * @ptr: pointer to the method header.
  2986. *
  2987. * Decode the method header at @ptr, including pointer to the IL code,
  2988. * info about local variables and optional exception tables.
  2989. * This is a Mono runtime internal function.
  2990. *
  2991. * LOCKING: Acquires the loader lock.
  2992. *
  2993. * Returns: a transient MonoMethodHeader allocated from the heap.
  2994. */
  2995. MonoMethodHeader *
  2996. mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
  2997. {
  2998. MonoMethodHeader *mh;
  2999. unsigned char flags = *(const unsigned char *) ptr;
  3000. unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
  3001. guint16 fat_flags;
  3002. guint32 local_var_sig_tok, max_stack, code_size, init_locals;
  3003. const unsigned char *code;
  3004. MonoExceptionClause* clauses = NULL;
  3005. int hsize, num_clauses = 0;
  3006. MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
  3007. guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
  3008. g_return_val_if_fail (ptr != NULL, NULL);
  3009. switch (format) {
  3010. case METHOD_HEADER_TINY_FORMAT:
  3011. mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER);
  3012. ptr++;
  3013. mh->max_stack = 8;
  3014. mh->is_transient = TRUE;
  3015. local_var_sig_tok = 0;
  3016. mh->code_size = flags >> 2;
  3017. mh->code = (unsigned char*)ptr;
  3018. return mh;
  3019. case METHOD_HEADER_FAT_FORMAT:
  3020. fat_flags = read16 (ptr);
  3021. ptr += 2;
  3022. hsize = (fat_flags >> 12) & 0xf;
  3023. max_stack = read16 (ptr);
  3024. ptr += 2;
  3025. code_size = read32 (ptr);
  3026. ptr += 4;
  3027. local_var_sig_tok = read32 (ptr);
  3028. ptr += 4;
  3029. if (fat_flags & METHOD_HEADER_INIT_LOCALS)
  3030. init_locals = 1;
  3031. else
  3032. init_locals = 0;
  3033. code = (unsigned char*)ptr;
  3034. if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
  3035. break;
  3036. /*
  3037. * There are more sections
  3038. */
  3039. ptr = (char*)code + code_size;
  3040. break;
  3041. default:
  3042. return NULL;
  3043. }
  3044. if (local_var_sig_tok) {
  3045. int idx = (local_var_sig_tok & 0xffffff)-1;
  3046. if (idx >= t->rows || idx < 0)
  3047. return NULL;
  3048. mono_metadata_decode_row (t, idx, cols, 1);
  3049. if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL))
  3050. return NULL;
  3051. }
  3052. if (fat_flags & METHOD_HEADER_MORE_SECTS)
  3053. clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr);
  3054. if (local_var_sig_tok) {
  3055. const char *locals_ptr;
  3056. int len=0, i, bsize;
  3057. locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
  3058. bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
  3059. if (*locals_ptr != 0x07)
  3060. g_warning ("wrong signature for locals blob");
  3061. locals_ptr++;
  3062. len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
  3063. mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause));
  3064. mh->num_locals = len;
  3065. for (i = 0; i < len; ++i) {
  3066. mh->locals [i] = mono_metadata_parse_type_internal (m, container,
  3067. MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr);
  3068. if (!mh->locals [i]) {
  3069. g_free (clauses);
  3070. g_free (mh);
  3071. return NULL;
  3072. }
  3073. }
  3074. } else {
  3075. mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
  3076. }
  3077. mh->code = code;
  3078. mh->code_size = code_size;
  3079. mh->max_stack = max_stack;
  3080. mh->is_transient = TRUE;
  3081. mh->init_locals = init_locals;
  3082. if (clauses) {
  3083. MonoExceptionClause* clausesp = (MonoExceptionClause*)&mh->locals [mh->num_locals];
  3084. memcpy (clausesp, clauses, num_clauses * sizeof (MonoExceptionClause));
  3085. g_free (clauses);
  3086. mh->clauses = clausesp;
  3087. mh->num_clauses = num_clauses;
  3088. }
  3089. return mh;
  3090. }
  3091. /*
  3092. * mono_metadata_parse_mh:
  3093. * @generic_context: generics context
  3094. * @ptr: pointer to the method header.
  3095. *
  3096. * Decode the method header at @ptr, including pointer to the IL code,
  3097. * info about local variables and optional exception tables.
  3098. * This is a Mono runtime internal function.
  3099. *
  3100. * Returns: a MonoMethodHeader.
  3101. */
  3102. MonoMethodHeader *
  3103. mono_metadata_parse_mh (MonoImage *m, const char *ptr)
  3104. {
  3105. MonoMethodHeader *res;
  3106. mono_loader_lock ();
  3107. res = mono_metadata_parse_mh_full (m, NULL, ptr);
  3108. mono_loader_unlock ();
  3109. return res;
  3110. }
  3111. /*
  3112. * mono_metadata_free_mh:
  3113. * @mh: a method header
  3114. *
  3115. * Free the memory allocated for the method header.
  3116. */
  3117. void
  3118. mono_metadata_free_mh (MonoMethodHeader *mh)
  3119. {
  3120. int i;
  3121. /* If it is not transient it means it's part of a wrapper method,
  3122. * or a SRE-generated method, so the lifetime in that case is
  3123. * dictated by the method's own lifetime
  3124. */
  3125. if (mh->is_transient) {
  3126. for (i = 0; i < mh->num_locals; ++i)
  3127. mono_metadata_free_type (mh->locals [i]);
  3128. g_free (mh);
  3129. }
  3130. }
  3131. /*
  3132. * mono_method_header_get_code:
  3133. * @header: a MonoMethodHeader pointer
  3134. * @code_size: memory location for returning the code size
  3135. * @max_stack: memory location for returning the max stack
  3136. *
  3137. * Method header accessor to retreive info about the IL code properties:
  3138. * a pointer to the IL code itself, the size of the code and the max number
  3139. * of stack slots used by the code.
  3140. *
  3141. * Returns: pointer to the IL code represented by the method header.
  3142. */
  3143. const unsigned char*
  3144. mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
  3145. {
  3146. if (code_size)
  3147. *code_size = header->code_size;
  3148. if (max_stack)
  3149. *max_stack = header->max_stack;
  3150. return header->code;
  3151. }
  3152. /*
  3153. * mono_method_header_get_locals:
  3154. * @header: a MonoMethodHeader pointer
  3155. * @num_locals: memory location for returning the number of local variables
  3156. * @init_locals: memory location for returning the init_locals flag
  3157. *
  3158. * Method header accessor to retreive info about the local variables:
  3159. * an array of local types, the number of locals and whether the locals
  3160. * are supposed to be initialized to 0 on method entry
  3161. *
  3162. * Returns: pointer to an array of types of the local variables
  3163. */
  3164. MonoType**
  3165. mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
  3166. {
  3167. if (num_locals)
  3168. *num_locals = header->num_locals;
  3169. if (init_locals)
  3170. *init_locals = header->init_locals;
  3171. return header->locals;
  3172. }
  3173. /*
  3174. * mono_method_header_get_num_clauses:
  3175. * @header: a MonoMethodHeader pointer
  3176. *
  3177. * Method header accessor to retreive the number of exception clauses.
  3178. *
  3179. * Returns: the number of exception clauses present
  3180. */
  3181. int
  3182. mono_method_header_get_num_clauses (MonoMethodHeader *header)
  3183. {
  3184. return header->num_clauses;
  3185. }
  3186. /*
  3187. * mono_method_header_get_clauses:
  3188. * @header: a MonoMethodHeader pointer
  3189. * @method: MonoMethod the header belongs to
  3190. * @iter: pointer to a iterator
  3191. * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
  3192. *
  3193. * Get the info about the exception clauses in the method. Set *iter to NULL to
  3194. * initiate the iteration, then call the method repeatedly until it returns FALSE.
  3195. * At each iteration, the structure pointed to by clause if filled with the
  3196. * exception clause information.
  3197. *
  3198. * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
  3199. * clauses.
  3200. */
  3201. int
  3202. mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
  3203. {
  3204. MonoExceptionClause *sc;
  3205. /* later we'll be able to use this interface to parse the clause info on demand,
  3206. * without allocating anything.
  3207. */
  3208. if (!iter || !header->num_clauses)
  3209. return FALSE;
  3210. if (!*iter) {
  3211. *iter = sc = header->clauses;
  3212. *clause = *sc;
  3213. return TRUE;
  3214. }
  3215. sc = *iter;
  3216. sc++;
  3217. if (sc < header->clauses + header->num_clauses) {
  3218. *iter = sc;
  3219. *clause = *sc;
  3220. return TRUE;
  3221. }
  3222. return FALSE;
  3223. }
  3224. /**
  3225. * mono_metadata_parse_field_type:
  3226. * @m: metadata context to extract information from
  3227. * @ptr: pointer to the field signature
  3228. * @rptr: pointer updated to match the end of the decoded stream
  3229. *
  3230. * Parses the field signature, and returns the type information for it.
  3231. *
  3232. * Returns: The MonoType that was extracted from @ptr.
  3233. */
  3234. MonoType *
  3235. mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
  3236. {
  3237. return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
  3238. }
  3239. /**
  3240. * mono_metadata_parse_param:
  3241. * @m: metadata context to extract information from
  3242. * @ptr: pointer to the param signature
  3243. * @rptr: pointer updated to match the end of the decoded stream
  3244. *
  3245. * Parses the param signature, and returns the type information for it.
  3246. *
  3247. * Returns: The MonoType that was extracted from @ptr.
  3248. */
  3249. MonoType *
  3250. mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
  3251. {
  3252. return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
  3253. }
  3254. /*
  3255. * mono_metadata_token_from_dor:
  3256. * @dor_token: A TypeDefOrRef coded index
  3257. *
  3258. * dor_token is a TypeDefOrRef coded index: it contains either
  3259. * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
  3260. * bits contain an index into the table.
  3261. *
  3262. * Returns: an expanded token
  3263. */
  3264. guint32
  3265. mono_metadata_token_from_dor (guint32 dor_index)
  3266. {
  3267. guint32 table, idx;
  3268. table = dor_index & 0x03;
  3269. idx = dor_index >> 2;
  3270. switch (table){
  3271. case 0: /* TypeDef */
  3272. return MONO_TOKEN_TYPE_DEF | idx;
  3273. case 1: /* TypeRef */
  3274. return MONO_TOKEN_TYPE_REF | idx;
  3275. case 2: /* TypeSpec */
  3276. return MONO_TOKEN_TYPE_SPEC | idx;
  3277. default:
  3278. g_assert_not_reached ();
  3279. }
  3280. return 0;
  3281. }
  3282. /*
  3283. * We use this to pass context information to the row locator
  3284. */
  3285. typedef struct {
  3286. int idx; /* The index that we are trying to locate */
  3287. int col_idx; /* The index in the row where idx may be stored */
  3288. MonoTableInfo *t; /* pointer to the table */
  3289. guint32 result;
  3290. } locator_t;
  3291. /*
  3292. * How the row locator works.
  3293. *
  3294. * Table A
  3295. * ___|___
  3296. * ___|___ Table B
  3297. * ___|___------> _______
  3298. * ___|___ _______
  3299. *
  3300. * A column in the rows of table A references an index in table B.
  3301. * For example A may be the TYPEDEF table and B the METHODDEF table.
  3302. *
  3303. * Given an index in table B we want to get the row in table A
  3304. * where the column n references our index in B.
  3305. *
  3306. * In the locator_t structure:
  3307. * t is table A
  3308. * col_idx is the column number
  3309. * index is the index in table B
  3310. * result will be the index in table A
  3311. *
  3312. * Examples:
  3313. * Table A Table B column (in table A)
  3314. * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
  3315. * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
  3316. * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
  3317. * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
  3318. * METHODSEM PROPERTY ASSOCIATION (encoded index)
  3319. *
  3320. * Note that we still don't support encoded indexes.
  3321. *
  3322. */
  3323. static int
  3324. typedef_locator (const void *a, const void *b)
  3325. {
  3326. locator_t *loc = (locator_t *) a;
  3327. const char *bb = (const char *) b;
  3328. int typedef_index = (bb - loc->t->base) / loc->t->row_size;
  3329. guint32 col, col_next;
  3330. col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
  3331. if (loc->idx < col)
  3332. return -1;
  3333. /*
  3334. * Need to check that the next row is valid.
  3335. */
  3336. if (typedef_index + 1 < loc->t->rows) {
  3337. col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
  3338. if (loc->idx >= col_next)
  3339. return 1;
  3340. if (col == col_next)
  3341. return 1;
  3342. }
  3343. loc->result = typedef_index;
  3344. return 0;
  3345. }
  3346. static int
  3347. table_locator (const void *a, const void *b)
  3348. {
  3349. locator_t *loc = (locator_t *) a;
  3350. const char *bb = (const char *) b;
  3351. guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
  3352. guint32 col;
  3353. col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
  3354. if (loc->idx == col) {
  3355. loc->result = table_index;
  3356. return 0;
  3357. }
  3358. if (loc->idx < col)
  3359. return -1;
  3360. else
  3361. return 1;
  3362. }
  3363. static int
  3364. declsec_locator (const void *a, const void *b)
  3365. {
  3366. locator_t *loc = (locator_t *) a;
  3367. const char *bb = (const char *) b;
  3368. guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
  3369. guint32 col;
  3370. col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
  3371. if (loc->idx == col) {
  3372. loc->result = table_index;
  3373. return 0;
  3374. }
  3375. if (loc->idx < col)
  3376. return -1;
  3377. else
  3378. return 1;
  3379. }
  3380. /**
  3381. * search_ptr_table:
  3382. *
  3383. * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
  3384. * which contains IDX.
  3385. */
  3386. static guint32
  3387. search_ptr_table (MonoImage *image, int table, int idx)
  3388. {
  3389. MonoTableInfo *ptrdef = &image->tables [table];
  3390. int i;
  3391. /* Use a linear search to find our index in the table */
  3392. for (i = 0; i < ptrdef->rows; i ++)
  3393. /* All the Ptr tables have the same structure */
  3394. if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
  3395. break;
  3396. if (i < ptrdef->rows)
  3397. return i + 1;
  3398. else
  3399. return idx;
  3400. }
  3401. /**
  3402. * mono_metadata_typedef_from_field:
  3403. * @meta: metadata context
  3404. * @index: FieldDef token
  3405. *
  3406. * Returns: the 1-based index into the TypeDef table of the type that
  3407. * declared the field described by @index, or 0 if not found.
  3408. */
  3409. guint32
  3410. mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
  3411. {
  3412. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
  3413. locator_t loc;
  3414. if (!tdef->base)
  3415. return 0;
  3416. loc.idx = mono_metadata_token_index (index);
  3417. loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
  3418. loc.t = tdef;
  3419. if (meta->uncompressed_metadata)
  3420. loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
  3421. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
  3422. return 0;
  3423. /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
  3424. return loc.result + 1;
  3425. }
  3426. /*
  3427. * mono_metadata_typedef_from_method:
  3428. * @meta: metadata context
  3429. * @index: MethodDef token
  3430. *
  3431. * Returns: the 1-based index into the TypeDef table of the type that
  3432. * declared the method described by @index. 0 if not found.
  3433. */
  3434. guint32
  3435. mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
  3436. {
  3437. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
  3438. locator_t loc;
  3439. if (!tdef->base)
  3440. return 0;
  3441. loc.idx = mono_metadata_token_index (index);
  3442. loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
  3443. loc.t = tdef;
  3444. if (meta->uncompressed_metadata)
  3445. loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
  3446. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
  3447. return 0;
  3448. /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
  3449. return loc.result + 1;
  3450. }
  3451. /*
  3452. * mono_metadata_interfaces_from_typedef_full:
  3453. * @meta: metadata context
  3454. * @index: typedef token
  3455. * @interfaces: Out parameter used to store the interface array
  3456. * @count: Out parameter used to store the number of interfaces
  3457. * @heap_alloc_result: if TRUE the result array will be g_malloc'd
  3458. * @context: The generic context
  3459. *
  3460. * The array of interfaces that the @index typedef token implements is returned in
  3461. * @interfaces. The number of elements in the array is returned in @count.
  3462. *
  3463. * LOCKING: Assumes the loader lock is held.
  3464. *
  3465. * Returns: TRUE on success, FALSE on failure.
  3466. */
  3467. gboolean
  3468. mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context)
  3469. {
  3470. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
  3471. locator_t loc;
  3472. guint32 start, pos;
  3473. guint32 cols [MONO_INTERFACEIMPL_SIZE];
  3474. MonoClass **result;
  3475. *interfaces = NULL;
  3476. *count = 0;
  3477. if (!tdef->base)
  3478. return TRUE;
  3479. loc.idx = mono_metadata_token_index (index);
  3480. loc.col_idx = MONO_INTERFACEIMPL_CLASS;
  3481. loc.t = tdef;
  3482. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  3483. return TRUE;
  3484. start = loc.result;
  3485. /*
  3486. * We may end up in the middle of the rows...
  3487. */
  3488. while (start > 0) {
  3489. if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
  3490. start--;
  3491. else
  3492. break;
  3493. }
  3494. pos = start;
  3495. while (pos < tdef->rows) {
  3496. mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
  3497. if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
  3498. break;
  3499. ++pos;
  3500. }
  3501. if (heap_alloc_result)
  3502. result = g_new0 (MonoClass*, pos - start);
  3503. else
  3504. result = mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
  3505. pos = start;
  3506. while (pos < tdef->rows) {
  3507. MonoClass *iface;
  3508. mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
  3509. if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
  3510. break;
  3511. iface = mono_class_get_full (
  3512. meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
  3513. if (iface == NULL)
  3514. return FALSE;
  3515. result [pos - start] = iface;
  3516. ++pos;
  3517. }
  3518. *count = pos - start;
  3519. *interfaces = result;
  3520. return TRUE;
  3521. }
  3522. /*
  3523. * @meta: metadata context
  3524. * @index: typedef token
  3525. * @count: Out parameter used to store the number of interfaces
  3526. *
  3527. * The array of interfaces that the @index typedef token implements is returned in
  3528. * @interfaces. The number of elements in the array is returned in @count. The returned
  3529. * array is g_malloc'd and the caller must free it.
  3530. *
  3531. * LOCKING: Acquires the loader lock .
  3532. *
  3533. * Returns: the interface array on success, NULL on failure.
  3534. */
  3535. MonoClass**
  3536. mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
  3537. {
  3538. MonoClass **interfaces;
  3539. gboolean rv;
  3540. mono_loader_lock ();
  3541. rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL);
  3542. mono_loader_unlock ();
  3543. if (rv)
  3544. return interfaces;
  3545. else
  3546. return NULL;
  3547. }
  3548. /*
  3549. * mono_metadata_nested_in_typedef:
  3550. * @meta: metadata context
  3551. * @index: typedef token
  3552. *
  3553. * Returns: the 1-based index into the TypeDef table of the type
  3554. * where the type described by @index is nested.
  3555. * Retruns 0 if @index describes a non-nested type.
  3556. */
  3557. guint32
  3558. mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
  3559. {
  3560. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
  3561. locator_t loc;
  3562. if (!tdef->base)
  3563. return 0;
  3564. loc.idx = mono_metadata_token_index (index);
  3565. loc.col_idx = MONO_NESTED_CLASS_NESTED;
  3566. loc.t = tdef;
  3567. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  3568. return 0;
  3569. /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
  3570. return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
  3571. }
  3572. /*
  3573. * mono_metadata_nesting_typedef:
  3574. * @meta: metadata context
  3575. * @index: typedef token
  3576. *
  3577. * Returns: the 1-based index into the TypeDef table of the first type
  3578. * that is nested inside the type described by @index. The search starts at
  3579. * @start_index. returns 0 if no such type is found.
  3580. */
  3581. guint32
  3582. mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
  3583. {
  3584. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
  3585. guint32 start;
  3586. guint32 class_index = mono_metadata_token_index (index);
  3587. if (!tdef->base)
  3588. return 0;
  3589. start = start_index;
  3590. while (start <= tdef->rows) {
  3591. if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
  3592. break;
  3593. else
  3594. start++;
  3595. }
  3596. if (start > tdef->rows)
  3597. return 0;
  3598. else
  3599. return start;
  3600. }
  3601. /*
  3602. * mono_metadata_packing_from_typedef:
  3603. * @meta: metadata context
  3604. * @index: token representing a type
  3605. *
  3606. * Returns: the info stored in the ClassLAyout table for the given typedef token
  3607. * into the @packing and @size pointers.
  3608. * Returns 0 if the info is not found.
  3609. */
  3610. guint32
  3611. mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
  3612. {
  3613. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
  3614. locator_t loc;
  3615. guint32 cols [MONO_CLASS_LAYOUT_SIZE];
  3616. if (!tdef->base)
  3617. return 0;
  3618. loc.idx = mono_metadata_token_index (index);
  3619. loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
  3620. loc.t = tdef;
  3621. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  3622. return 0;
  3623. mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
  3624. if (packing)
  3625. *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
  3626. if (size)
  3627. *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
  3628. /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
  3629. return loc.result + 1;
  3630. }
  3631. /*
  3632. * mono_metadata_custom_attrs_from_index:
  3633. * @meta: metadata context
  3634. * @index: token representing the parent
  3635. *
  3636. * Returns: the 1-based index into the CustomAttribute table of the first
  3637. * attribute which belongs to the metadata object described by @index.
  3638. * Returns 0 if no such attribute is found.
  3639. */
  3640. guint32
  3641. mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
  3642. {
  3643. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
  3644. locator_t loc;
  3645. if (!tdef->base)
  3646. return 0;
  3647. loc.idx = index;
  3648. loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
  3649. loc.t = tdef;
  3650. /* FIXME: Index translation */
  3651. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  3652. return 0;
  3653. /* Find the first entry by searching backwards */
  3654. while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
  3655. loc.result --;
  3656. /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
  3657. return loc.result + 1;
  3658. }
  3659. /*
  3660. * mono_metadata_declsec_from_index:
  3661. * @meta: metadata context
  3662. * @index: token representing the parent
  3663. *
  3664. * Returns: the 0-based index into the DeclarativeSecurity table of the first
  3665. * attribute which belongs to the metadata object described by @index.
  3666. * Returns -1 if no such attribute is found.
  3667. */
  3668. guint32
  3669. mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
  3670. {
  3671. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
  3672. locator_t loc;
  3673. if (!tdef->base)
  3674. return -1;
  3675. loc.idx = index;
  3676. loc.col_idx = MONO_DECL_SECURITY_PARENT;
  3677. loc.t = tdef;
  3678. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
  3679. return -1;
  3680. /* Find the first entry by searching backwards */
  3681. while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
  3682. loc.result --;
  3683. return loc.result;
  3684. }
  3685. #ifdef DEBUG
  3686. static void
  3687. mono_backtrace (int limit)
  3688. {
  3689. void *array[limit];
  3690. char **names;
  3691. int i;
  3692. backtrace (array, limit);
  3693. names = backtrace_symbols (array, limit);
  3694. for (i =0; i < limit; ++i) {
  3695. g_print ("\t%s\n", names [i]);
  3696. }
  3697. g_free (names);
  3698. }
  3699. #endif
  3700. #define abi__alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
  3701. /*
  3702. * mono_type_size:
  3703. * @t: the type to return the size of
  3704. *
  3705. * Returns: the number of bytes required to hold an instance of this
  3706. * type in memory
  3707. */
  3708. int
  3709. mono_type_size (MonoType *t, int *align)
  3710. {
  3711. if (!t) {
  3712. *align = 1;
  3713. return 0;
  3714. }
  3715. if (t->byref) {
  3716. *align = abi__alignof__(gpointer);
  3717. return sizeof (gpointer);
  3718. }
  3719. switch (t->type){
  3720. case MONO_TYPE_VOID:
  3721. *align = 1;
  3722. return 0;
  3723. case MONO_TYPE_BOOLEAN:
  3724. *align = abi__alignof__(gint8);
  3725. return 1;
  3726. case MONO_TYPE_I1:
  3727. case MONO_TYPE_U1:
  3728. *align = abi__alignof__(gint8);
  3729. return 1;
  3730. case MONO_TYPE_CHAR:
  3731. case MONO_TYPE_I2:
  3732. case MONO_TYPE_U2:
  3733. *align = abi__alignof__(gint16);
  3734. return 2;
  3735. case MONO_TYPE_I4:
  3736. case MONO_TYPE_U4:
  3737. *align = abi__alignof__(gint32);
  3738. return 4;
  3739. case MONO_TYPE_R4:
  3740. *align = abi__alignof__(float);
  3741. return 4;
  3742. case MONO_TYPE_I8:
  3743. case MONO_TYPE_U8:
  3744. *align = abi__alignof__(gint64);
  3745. return 8;
  3746. case MONO_TYPE_R8:
  3747. *align = abi__alignof__(double);
  3748. return 8;
  3749. case MONO_TYPE_I:
  3750. case MONO_TYPE_U:
  3751. *align = abi__alignof__(gpointer);
  3752. return sizeof (gpointer);
  3753. case MONO_TYPE_STRING:
  3754. *align = abi__alignof__(gpointer);
  3755. return sizeof (gpointer);
  3756. case MONO_TYPE_OBJECT:
  3757. *align = abi__alignof__(gpointer);
  3758. return sizeof (gpointer);
  3759. case MONO_TYPE_VALUETYPE: {
  3760. if (t->data.klass->enumtype)
  3761. return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
  3762. else
  3763. return mono_class_value_size (t->data.klass, (guint32*)align);
  3764. }
  3765. case MONO_TYPE_CLASS:
  3766. case MONO_TYPE_SZARRAY:
  3767. case MONO_TYPE_PTR:
  3768. case MONO_TYPE_FNPTR:
  3769. case MONO_TYPE_ARRAY:
  3770. *align = abi__alignof__(gpointer);
  3771. return sizeof (gpointer);
  3772. case MONO_TYPE_TYPEDBYREF:
  3773. return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
  3774. case MONO_TYPE_GENERICINST: {
  3775. MonoGenericClass *gclass = t->data.generic_class;
  3776. MonoClass *container_class = gclass->container_class;
  3777. // g_assert (!gclass->inst->is_open);
  3778. if (container_class->valuetype) {
  3779. if (container_class->enumtype)
  3780. return mono_type_size (mono_class_enum_basetype (container_class), align);
  3781. else
  3782. return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
  3783. } else {
  3784. *align = abi__alignof__(gpointer);
  3785. return sizeof (gpointer);
  3786. }
  3787. }
  3788. case MONO_TYPE_VAR:
  3789. case MONO_TYPE_MVAR:
  3790. /* FIXME: Martin, this is wrong. */
  3791. *align = abi__alignof__(gpointer);
  3792. return sizeof (gpointer);
  3793. default:
  3794. g_error ("mono_type_size: type 0x%02x unknown", t->type);
  3795. }
  3796. return 0;
  3797. }
  3798. /*
  3799. * mono_type_stack_size:
  3800. * @t: the type to return the size it uses on the stack
  3801. *
  3802. * Returns: the number of bytes required to hold an instance of this
  3803. * type on the runtime stack
  3804. */
  3805. int
  3806. mono_type_stack_size (MonoType *t, int *align)
  3807. {
  3808. return mono_type_stack_size_internal (t, align, FALSE);
  3809. }
  3810. int
  3811. mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
  3812. {
  3813. int tmp;
  3814. #if SIZEOF_VOID_P == SIZEOF_REGISTER
  3815. int stack_slot_size = sizeof (gpointer);
  3816. int stack_slot_align = abi__alignof__ (gpointer);
  3817. #elif SIZEOF_VOID_P < SIZEOF_REGISTER
  3818. int stack_slot_size = SIZEOF_REGISTER;
  3819. int stack_slot_align = SIZEOF_REGISTER;
  3820. #endif
  3821. g_assert (t != NULL);
  3822. if (!align)
  3823. align = &tmp;
  3824. if (t->byref) {
  3825. *align = stack_slot_align;
  3826. return stack_slot_size;
  3827. }
  3828. switch (t->type){
  3829. case MONO_TYPE_BOOLEAN:
  3830. case MONO_TYPE_CHAR:
  3831. case MONO_TYPE_I1:
  3832. case MONO_TYPE_U1:
  3833. case MONO_TYPE_I2:
  3834. case MONO_TYPE_U2:
  3835. case MONO_TYPE_I4:
  3836. case MONO_TYPE_U4:
  3837. case MONO_TYPE_I:
  3838. case MONO_TYPE_U:
  3839. case MONO_TYPE_STRING:
  3840. case MONO_TYPE_OBJECT:
  3841. case MONO_TYPE_CLASS:
  3842. case MONO_TYPE_SZARRAY:
  3843. case MONO_TYPE_PTR:
  3844. case MONO_TYPE_FNPTR:
  3845. case MONO_TYPE_ARRAY:
  3846. *align = stack_slot_align;
  3847. return stack_slot_size;
  3848. case MONO_TYPE_VAR:
  3849. case MONO_TYPE_MVAR:
  3850. g_assert (allow_open);
  3851. *align = stack_slot_align;
  3852. return stack_slot_size;
  3853. case MONO_TYPE_TYPEDBYREF:
  3854. *align = stack_slot_align;
  3855. return stack_slot_size * 3;
  3856. case MONO_TYPE_R4:
  3857. *align = abi__alignof__(float);
  3858. return sizeof (float);
  3859. case MONO_TYPE_I8:
  3860. case MONO_TYPE_U8:
  3861. *align = abi__alignof__(gint64);
  3862. return sizeof (gint64);
  3863. case MONO_TYPE_R8:
  3864. *align = abi__alignof__(double);
  3865. return sizeof (double);
  3866. case MONO_TYPE_VALUETYPE: {
  3867. guint32 size;
  3868. if (t->data.klass->enumtype)
  3869. return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
  3870. else {
  3871. size = mono_class_value_size (t->data.klass, (guint32*)align);
  3872. *align = *align + stack_slot_align - 1;
  3873. *align &= ~(stack_slot_align - 1);
  3874. size += stack_slot_size - 1;
  3875. size &= ~(stack_slot_size - 1);
  3876. return size;
  3877. }
  3878. }
  3879. case MONO_TYPE_GENERICINST: {
  3880. MonoGenericClass *gclass = t->data.generic_class;
  3881. MonoClass *container_class = gclass->container_class;
  3882. if (!allow_open)
  3883. g_assert (!gclass->context.class_inst->is_open);
  3884. if (container_class->valuetype) {
  3885. if (container_class->enumtype)
  3886. return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
  3887. else {
  3888. guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
  3889. *align = *align + stack_slot_align - 1;
  3890. *align &= ~(stack_slot_align - 1);
  3891. size += stack_slot_size - 1;
  3892. size &= ~(stack_slot_size - 1);
  3893. return size;
  3894. }
  3895. } else {
  3896. *align = stack_slot_align;
  3897. return stack_slot_size;
  3898. }
  3899. }
  3900. default:
  3901. g_error ("type 0x%02x unknown", t->type);
  3902. }
  3903. return 0;
  3904. }
  3905. gboolean
  3906. mono_type_generic_inst_is_valuetype (MonoType *type)
  3907. {
  3908. g_assert (type->type == MONO_TYPE_GENERICINST);
  3909. return type->data.generic_class->container_class->valuetype;
  3910. }
  3911. gboolean
  3912. mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
  3913. {
  3914. return gclass->container_class->valuetype;
  3915. }
  3916. static gboolean
  3917. _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
  3918. {
  3919. MonoGenericInst *i1 = g1->context.class_inst;
  3920. MonoGenericInst *i2 = g2->context.class_inst;
  3921. if (g1->is_dynamic != g2->is_dynamic)
  3922. return FALSE;
  3923. if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
  3924. return FALSE;
  3925. if (!mono_generic_inst_equal_full (i1, i2, signature_only))
  3926. return FALSE;
  3927. return g1->is_tb_open == g2->is_tb_open;
  3928. }
  3929. static gboolean
  3930. _mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
  3931. {
  3932. MonoGenericInst *i1 = g1->context.class_inst;
  3933. MonoGenericInst *i2 = c2->generic_container->context.class_inst;
  3934. if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
  3935. return FALSE;
  3936. if (!mono_generic_inst_equal_full (i1, i2, signature_only))
  3937. return FALSE;
  3938. return !g1->is_tb_open;
  3939. }
  3940. guint
  3941. mono_metadata_generic_context_hash (const MonoGenericContext *context)
  3942. {
  3943. /* FIXME: check if this seed is good enough */
  3944. guint hash = 0xc01dfee7;
  3945. if (context->class_inst)
  3946. hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->class_inst);
  3947. if (context->method_inst)
  3948. hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->method_inst);
  3949. return hash;
  3950. }
  3951. gboolean
  3952. mono_metadata_generic_context_equal (const MonoGenericContext *g1, const MonoGenericContext *g2)
  3953. {
  3954. return g1->class_inst == g2->class_inst && g1->method_inst == g2->method_inst;
  3955. }
  3956. /*
  3957. * mono_metadata_str_hash:
  3958. *
  3959. * This should be used instead of g_str_hash for computing hash codes visible
  3960. * outside this module, since g_str_hash () is not guaranteed to be stable
  3961. * (its not the same in eglib for example).
  3962. */
  3963. guint
  3964. mono_metadata_str_hash (gconstpointer v1)
  3965. {
  3966. /* Same as g_str_hash () in glib */
  3967. char *p = (char *) v1;
  3968. guint hash = *p;
  3969. while (*p++) {
  3970. if (*p)
  3971. hash = (hash << 5) - hash + *p;
  3972. }
  3973. return hash;
  3974. }
  3975. /*
  3976. * mono_metadata_type_hash:
  3977. * @t1: a type
  3978. *
  3979. * Computes an hash value for @t1 to be used in GHashTable.
  3980. * The returned hash is guaranteed to be the same across executions.
  3981. */
  3982. guint
  3983. mono_metadata_type_hash (MonoType *t1)
  3984. {
  3985. guint hash = t1->type;
  3986. hash |= t1->byref << 6; /* do not collide with t1->type values */
  3987. switch (t1->type) {
  3988. case MONO_TYPE_VALUETYPE:
  3989. case MONO_TYPE_CLASS:
  3990. case MONO_TYPE_SZARRAY: {
  3991. MonoClass *class = t1->data.klass;
  3992. /*
  3993. * Dynamic classes must not be hashed on their type since it can change
  3994. * during runtime. For example, if we hash a reference type that is
  3995. * later made into a valuetype.
  3996. *
  3997. * This is specially problematic with generic instances since they are
  3998. * inserted in a bunch of hash tables before been finished.
  3999. */
  4000. if (class->image->dynamic)
  4001. return (t1->byref << 6) | mono_metadata_str_hash (class->name);
  4002. return ((hash << 5) - hash) ^ mono_metadata_str_hash (class->name);
  4003. }
  4004. case MONO_TYPE_PTR:
  4005. return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
  4006. case MONO_TYPE_ARRAY:
  4007. return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
  4008. case MONO_TYPE_GENERICINST:
  4009. return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
  4010. }
  4011. return hash;
  4012. }
  4013. static gboolean
  4014. mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
  4015. {
  4016. if (p1 == p2)
  4017. return TRUE;
  4018. if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
  4019. return FALSE;
  4020. if (p1->serial != p2->serial)
  4021. return FALSE;
  4022. /*
  4023. * We have to compare the image as well because if we didn't,
  4024. * the generic_inst_cache lookup wouldn't care about the image
  4025. * of generic params, so what could happen is that a generic
  4026. * inst with params from image A is put into the cache, then
  4027. * image B gets that generic inst from the cache, image A is
  4028. * unloaded, so the inst is deleted, but image B still retains
  4029. * a pointer to it.
  4030. *
  4031. * The AOT runtime doesn't set the image when it's decoding
  4032. * types, so we only compare it when the owner is NULL.
  4033. */
  4034. if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2) &&
  4035. (mono_generic_param_owner (p1) || p1->image == p2->image))
  4036. return TRUE;
  4037. /*
  4038. * If `signature_only' is true, we're comparing two (method) signatures.
  4039. * In this case, the owner of two type parameters doesn't need to match.
  4040. */
  4041. return signature_only;
  4042. }
  4043. static gboolean
  4044. mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
  4045. {
  4046. if (c1 == c2)
  4047. return TRUE;
  4048. if (c1->generic_class && c2->generic_class)
  4049. return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
  4050. if (c1->generic_class && c2->generic_container)
  4051. return _mono_metadata_generic_class_container_equal (c1->generic_class, c2, signature_only);
  4052. if (c1->generic_container && c2->generic_class)
  4053. return _mono_metadata_generic_class_container_equal (c2->generic_class, c1, signature_only);
  4054. if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
  4055. return mono_metadata_generic_param_equal (
  4056. c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
  4057. if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
  4058. return mono_metadata_generic_param_equal (
  4059. c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
  4060. if (signature_only &&
  4061. (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
  4062. return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
  4063. if (signature_only &&
  4064. (c1->byval_arg.type == MONO_TYPE_ARRAY) && (c2->byval_arg.type == MONO_TYPE_ARRAY))
  4065. return do_mono_metadata_type_equal (&c1->byval_arg, &c2->byval_arg, signature_only);
  4066. return FALSE;
  4067. }
  4068. static gboolean
  4069. mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
  4070. {
  4071. gpointer iter1 = 0, iter2 = 0;
  4072. if (s1 == s2)
  4073. return TRUE;
  4074. if (s1->call_convention != s2->call_convention)
  4075. return FALSE;
  4076. if (s1->sentinelpos != s2->sentinelpos)
  4077. return FALSE;
  4078. if (s1->hasthis != s2->hasthis)
  4079. return FALSE;
  4080. if (s1->explicit_this != s2->explicit_this)
  4081. return FALSE;
  4082. if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
  4083. return FALSE;
  4084. if (s1->param_count != s2->param_count)
  4085. return FALSE;
  4086. while (TRUE) {
  4087. MonoType *t1 = mono_signature_get_params (s1, &iter1);
  4088. MonoType *t2 = mono_signature_get_params (s2, &iter2);
  4089. if (t1 == NULL || t2 == NULL)
  4090. return (t1 == t2);
  4091. if (! do_mono_metadata_type_equal (t1, t2, signature_only))
  4092. return FALSE;
  4093. }
  4094. }
  4095. /*
  4096. * mono_metadata_type_equal:
  4097. * @t1: a type
  4098. * @t2: another type
  4099. *
  4100. * Determine if @t1 and @t2 represent the same type.
  4101. * Returns: #TRUE if @t1 and @t2 are equal.
  4102. */
  4103. static gboolean
  4104. do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
  4105. {
  4106. if (t1->type != t2->type || t1->byref != t2->byref)
  4107. return FALSE;
  4108. switch (t1->type) {
  4109. case MONO_TYPE_VOID:
  4110. case MONO_TYPE_BOOLEAN:
  4111. case MONO_TYPE_CHAR:
  4112. case MONO_TYPE_I1:
  4113. case MONO_TYPE_U1:
  4114. case MONO_TYPE_I2:
  4115. case MONO_TYPE_U2:
  4116. case MONO_TYPE_I4:
  4117. case MONO_TYPE_U4:
  4118. case MONO_TYPE_I8:
  4119. case MONO_TYPE_U8:
  4120. case MONO_TYPE_R4:
  4121. case MONO_TYPE_R8:
  4122. case MONO_TYPE_STRING:
  4123. case MONO_TYPE_I:
  4124. case MONO_TYPE_U:
  4125. case MONO_TYPE_OBJECT:
  4126. case MONO_TYPE_TYPEDBYREF:
  4127. return TRUE;
  4128. case MONO_TYPE_VALUETYPE:
  4129. case MONO_TYPE_CLASS:
  4130. case MONO_TYPE_SZARRAY:
  4131. return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
  4132. case MONO_TYPE_PTR:
  4133. return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
  4134. case MONO_TYPE_ARRAY:
  4135. if (t1->data.array->rank != t2->data.array->rank)
  4136. return FALSE;
  4137. return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
  4138. case MONO_TYPE_GENERICINST:
  4139. return _mono_metadata_generic_class_equal (
  4140. t1->data.generic_class, t2->data.generic_class, signature_only);
  4141. case MONO_TYPE_VAR:
  4142. return mono_metadata_generic_param_equal (
  4143. t1->data.generic_param, t2->data.generic_param, signature_only);
  4144. case MONO_TYPE_MVAR:
  4145. return mono_metadata_generic_param_equal (
  4146. t1->data.generic_param, t2->data.generic_param, signature_only);
  4147. case MONO_TYPE_FNPTR:
  4148. return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
  4149. default:
  4150. g_error ("implement type compare for %0x!", t1->type);
  4151. return FALSE;
  4152. }
  4153. return FALSE;
  4154. }
  4155. gboolean
  4156. mono_metadata_type_equal (MonoType *t1, MonoType *t2)
  4157. {
  4158. return do_mono_metadata_type_equal (t1, t2, FALSE);
  4159. }
  4160. /**
  4161. * mono_metadata_type_equal_full:
  4162. * @t1: a type
  4163. * @t2: another type
  4164. * @signature_only: if signature only comparison should be made
  4165. *
  4166. * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
  4167. * behaves the same way as mono_metadata_type_equal.
  4168. * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
  4169. * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
  4170. */
  4171. gboolean
  4172. mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only)
  4173. {
  4174. return do_mono_metadata_type_equal (t1, t2, signature_only);
  4175. }
  4176. /**
  4177. * mono_metadata_signature_equal:
  4178. * @sig1: a signature
  4179. * @sig2: another signature
  4180. *
  4181. * Determine if @sig1 and @sig2 represent the same signature, with the
  4182. * same number of arguments and the same types.
  4183. * Returns: #TRUE if @sig1 and @sig2 are equal.
  4184. */
  4185. gboolean
  4186. mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
  4187. {
  4188. int i;
  4189. if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
  4190. return FALSE;
  4191. if (sig1->generic_param_count != sig2->generic_param_count)
  4192. return FALSE;
  4193. /*
  4194. * We're just comparing the signatures of two methods here:
  4195. *
  4196. * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
  4197. * U and V are equal here.
  4198. *
  4199. * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
  4200. */
  4201. for (i = 0; i < sig1->param_count; i++) {
  4202. MonoType *p1 = sig1->params[i];
  4203. MonoType *p2 = sig2->params[i];
  4204. /* if (p1->attrs != p2->attrs)
  4205. return FALSE;
  4206. */
  4207. if (!do_mono_metadata_type_equal (p1, p2, TRUE))
  4208. return FALSE;
  4209. }
  4210. if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
  4211. return FALSE;
  4212. return TRUE;
  4213. }
  4214. /**
  4215. * mono_metadata_type_dup:
  4216. * @image: image to alloc memory from
  4217. * @original: type to duplicate
  4218. *
  4219. * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
  4220. */
  4221. MonoType *
  4222. mono_metadata_type_dup (MonoImage *image, const MonoType *o)
  4223. {
  4224. MonoType *r = NULL;
  4225. int sizeof_o = MONO_SIZEOF_TYPE;
  4226. if (o->num_mods)
  4227. sizeof_o += o->num_mods * sizeof (MonoCustomMod);
  4228. r = image ? mono_image_alloc0 (image, sizeof_o) : g_malloc (sizeof_o);
  4229. memcpy (r, o, sizeof_o);
  4230. if (o->type == MONO_TYPE_PTR) {
  4231. r->data.type = mono_metadata_type_dup (image, o->data.type);
  4232. } else if (o->type == MONO_TYPE_ARRAY) {
  4233. r->data.array = mono_dup_array_type (image, o->data.array);
  4234. } else if (o->type == MONO_TYPE_FNPTR) {
  4235. /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
  4236. r->data.method = mono_metadata_signature_deep_dup (image, o->data.method);
  4237. }
  4238. return r;
  4239. }
  4240. guint
  4241. mono_signature_hash (MonoMethodSignature *sig)
  4242. {
  4243. guint i, res = sig->ret->type;
  4244. for (i = 0; i < sig->param_count; i++)
  4245. res = (res << 5) - res + mono_type_hash (sig->params[i]);
  4246. return res;
  4247. }
  4248. /*
  4249. * mono_metadata_encode_value:
  4250. * @value: value to encode
  4251. * @buf: buffer where to write the compressed representation
  4252. * @endbuf: pointer updated to point at the end of the encoded output
  4253. *
  4254. * Encodes the value @value in the compressed representation used
  4255. * in metadata and stores the result in @buf. @buf needs to be big
  4256. * enough to hold the data (4 bytes).
  4257. */
  4258. void
  4259. mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
  4260. {
  4261. char *p = buf;
  4262. if (value < 0x80)
  4263. *p++ = value;
  4264. else if (value < 0x4000) {
  4265. p [0] = 0x80 | (value >> 8);
  4266. p [1] = value & 0xff;
  4267. p += 2;
  4268. } else {
  4269. p [0] = (value >> 24) | 0xc0;
  4270. p [1] = (value >> 16) & 0xff;
  4271. p [2] = (value >> 8) & 0xff;
  4272. p [3] = value & 0xff;
  4273. p += 4;
  4274. }
  4275. if (endbuf)
  4276. *endbuf = p;
  4277. }
  4278. /*
  4279. * mono_metadata_field_info:
  4280. * @meta: the Image the field is defined in
  4281. * @index: the index in the field table representing the field
  4282. * @offset: a pointer to an integer where to store the offset that
  4283. * may have been specified for the field in a FieldLayout table
  4284. * @rva: a pointer to the RVA of the field data in the image that
  4285. * may have been defined in a FieldRVA table
  4286. * @marshal_spec: a pointer to the marshal spec that may have been
  4287. * defined for the field in a FieldMarshal table.
  4288. *
  4289. * Gather info for field @index that may have been defined in the FieldLayout,
  4290. * FieldRVA and FieldMarshal tables.
  4291. * Either of offset, rva and marshal_spec can be NULL if you're not interested
  4292. * in the data.
  4293. */
  4294. void
  4295. mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
  4296. MonoMarshalSpec **marshal_spec)
  4297. {
  4298. mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, FALSE);
  4299. }
  4300. void
  4301. mono_metadata_field_info_with_mempool (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
  4302. MonoMarshalSpec **marshal_spec)
  4303. {
  4304. mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, TRUE);
  4305. }
  4306. static void
  4307. mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
  4308. MonoMarshalSpec **marshal_spec, gboolean alloc_from_image)
  4309. {
  4310. MonoTableInfo *tdef;
  4311. locator_t loc;
  4312. loc.idx = index + 1;
  4313. if (meta->uncompressed_metadata)
  4314. loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
  4315. if (offset) {
  4316. tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
  4317. loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
  4318. loc.t = tdef;
  4319. if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
  4320. *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
  4321. } else {
  4322. *offset = (guint32)-1;
  4323. }
  4324. }
  4325. if (rva) {
  4326. tdef = &meta->tables [MONO_TABLE_FIELDRVA];
  4327. loc.col_idx = MONO_FIELD_RVA_FIELD;
  4328. loc.t = tdef;
  4329. if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
  4330. /*
  4331. * LAMESPEC: There is no signature, no nothing, just the raw data.
  4332. */
  4333. *rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
  4334. } else {
  4335. *rva = 0;
  4336. }
  4337. }
  4338. if (marshal_spec) {
  4339. const char *p;
  4340. if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
  4341. *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, p);
  4342. }
  4343. }
  4344. }
  4345. /*
  4346. * mono_metadata_get_constant_index:
  4347. * @meta: the Image the field is defined in
  4348. * @index: the token that may have a row defined in the constants table
  4349. * @hint: possible position for the row
  4350. *
  4351. * @token must be a FieldDef, ParamDef or PropertyDef token.
  4352. *
  4353. * Returns: the index into the Constants table or 0 if not found.
  4354. */
  4355. guint32
  4356. mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
  4357. {
  4358. MonoTableInfo *tdef;
  4359. locator_t loc;
  4360. guint32 index = mono_metadata_token_index (token);
  4361. tdef = &meta->tables [MONO_TABLE_CONSTANT];
  4362. index <<= MONO_HASCONSTANT_BITS;
  4363. switch (mono_metadata_token_table (token)) {
  4364. case MONO_TABLE_FIELD:
  4365. index |= MONO_HASCONSTANT_FIEDDEF;
  4366. break;
  4367. case MONO_TABLE_PARAM:
  4368. index |= MONO_HASCONSTANT_PARAM;
  4369. break;
  4370. case MONO_TABLE_PROPERTY:
  4371. index |= MONO_HASCONSTANT_PROPERTY;
  4372. break;
  4373. default:
  4374. g_warning ("Not a valid token for the constant table: 0x%08x", token);
  4375. return 0;
  4376. }
  4377. loc.idx = index;
  4378. loc.col_idx = MONO_CONSTANT_PARENT;
  4379. loc.t = tdef;
  4380. /* FIXME: Index translation */
  4381. if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
  4382. return hint;
  4383. if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
  4384. return loc.result + 1;
  4385. }
  4386. return 0;
  4387. }
  4388. /*
  4389. * mono_metadata_events_from_typedef:
  4390. * @meta: metadata context
  4391. * @index: 0-based index (in the TypeDef table) describing a type
  4392. *
  4393. * Returns: the 0-based index in the Event table for the events in the
  4394. * type. The last event that belongs to the type (plus 1) is stored
  4395. * in the @end_idx pointer.
  4396. */
  4397. guint32
  4398. mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
  4399. {
  4400. locator_t loc;
  4401. guint32 start, end;
  4402. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_EVENTMAP];
  4403. *end_idx = 0;
  4404. if (!tdef->base)
  4405. return 0;
  4406. loc.t = tdef;
  4407. loc.col_idx = MONO_EVENT_MAP_PARENT;
  4408. loc.idx = index + 1;
  4409. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  4410. return 0;
  4411. start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
  4412. if (loc.result + 1 < tdef->rows) {
  4413. end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
  4414. } else {
  4415. end = meta->tables [MONO_TABLE_EVENT].rows;
  4416. }
  4417. *end_idx = end;
  4418. return start - 1;
  4419. }
  4420. /*
  4421. * mono_metadata_methods_from_event:
  4422. * @meta: metadata context
  4423. * @index: 0-based index (in the Event table) describing a event
  4424. *
  4425. * Returns: the 0-based index in the MethodDef table for the methods in the
  4426. * event. The last method that belongs to the event (plus 1) is stored
  4427. * in the @end_idx pointer.
  4428. */
  4429. guint32
  4430. mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_idx)
  4431. {
  4432. locator_t loc;
  4433. guint start, end;
  4434. guint32 cols [MONO_METHOD_SEMA_SIZE];
  4435. MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
  4436. *end_idx = 0;
  4437. if (!msemt->base)
  4438. return 0;
  4439. if (meta->uncompressed_metadata)
  4440. index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
  4441. loc.t = msemt;
  4442. loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
  4443. loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
  4444. if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
  4445. return 0;
  4446. start = loc.result;
  4447. /*
  4448. * We may end up in the middle of the rows...
  4449. */
  4450. while (start > 0) {
  4451. if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
  4452. start--;
  4453. else
  4454. break;
  4455. }
  4456. end = start + 1;
  4457. while (end < msemt->rows) {
  4458. mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
  4459. if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
  4460. break;
  4461. ++end;
  4462. }
  4463. *end_idx = end;
  4464. return start;
  4465. }
  4466. /*
  4467. * mono_metadata_properties_from_typedef:
  4468. * @meta: metadata context
  4469. * @index: 0-based index (in the TypeDef table) describing a type
  4470. *
  4471. * Returns: the 0-based index in the Property table for the properties in the
  4472. * type. The last property that belongs to the type (plus 1) is stored
  4473. * in the @end_idx pointer.
  4474. */
  4475. guint32
  4476. mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
  4477. {
  4478. locator_t loc;
  4479. guint32 start, end;
  4480. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_PROPERTYMAP];
  4481. *end_idx = 0;
  4482. if (!tdef->base)
  4483. return 0;
  4484. loc.t = tdef;
  4485. loc.col_idx = MONO_PROPERTY_MAP_PARENT;
  4486. loc.idx = index + 1;
  4487. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  4488. return 0;
  4489. start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
  4490. if (loc.result + 1 < tdef->rows) {
  4491. end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
  4492. } else {
  4493. end = meta->tables [MONO_TABLE_PROPERTY].rows;
  4494. }
  4495. *end_idx = end;
  4496. return start - 1;
  4497. }
  4498. /*
  4499. * mono_metadata_methods_from_property:
  4500. * @meta: metadata context
  4501. * @index: 0-based index (in the PropertyDef table) describing a property
  4502. *
  4503. * Returns: the 0-based index in the MethodDef table for the methods in the
  4504. * property. The last method that belongs to the property (plus 1) is stored
  4505. * in the @end_idx pointer.
  4506. */
  4507. guint32
  4508. mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *end_idx)
  4509. {
  4510. locator_t loc;
  4511. guint start, end;
  4512. guint32 cols [MONO_METHOD_SEMA_SIZE];
  4513. MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
  4514. *end_idx = 0;
  4515. if (!msemt->base)
  4516. return 0;
  4517. if (meta->uncompressed_metadata)
  4518. index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
  4519. loc.t = msemt;
  4520. loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
  4521. loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
  4522. if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
  4523. return 0;
  4524. start = loc.result;
  4525. /*
  4526. * We may end up in the middle of the rows...
  4527. */
  4528. while (start > 0) {
  4529. if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
  4530. start--;
  4531. else
  4532. break;
  4533. }
  4534. end = start + 1;
  4535. while (end < msemt->rows) {
  4536. mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
  4537. if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
  4538. break;
  4539. ++end;
  4540. }
  4541. *end_idx = end;
  4542. return start;
  4543. }
  4544. guint32
  4545. mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
  4546. {
  4547. locator_t loc;
  4548. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_IMPLMAP];
  4549. if (!tdef->base)
  4550. return 0;
  4551. /* No index translation seems to be needed */
  4552. loc.t = tdef;
  4553. loc.col_idx = MONO_IMPLMAP_MEMBER;
  4554. loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
  4555. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  4556. return 0;
  4557. return loc.result + 1;
  4558. }
  4559. /**
  4560. * @image: context where the image is created
  4561. * @type_spec: typespec token
  4562. *
  4563. * Creates a MonoType representing the TypeSpec indexed by the @type_spec
  4564. * token.
  4565. */
  4566. MonoType *
  4567. mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
  4568. {
  4569. guint32 idx = mono_metadata_token_index (type_spec);
  4570. MonoTableInfo *t;
  4571. guint32 cols [MONO_TYPESPEC_SIZE];
  4572. const char *ptr;
  4573. guint32 len;
  4574. MonoType *type, *type2;
  4575. mono_loader_lock ();
  4576. type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
  4577. if (type) {
  4578. mono_loader_unlock ();
  4579. return type;
  4580. }
  4581. t = &image->tables [MONO_TABLE_TYPESPEC];
  4582. mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
  4583. ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
  4584. if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
  4585. mono_loader_unlock ();
  4586. return NULL;
  4587. }
  4588. len = mono_metadata_decode_value (ptr, &ptr);
  4589. type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr);
  4590. if (!type) {
  4591. mono_loader_unlock ();
  4592. return NULL;
  4593. }
  4594. type2 = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
  4595. if (type2) {
  4596. mono_loader_unlock ();
  4597. return type2;
  4598. }
  4599. type2 = mono_metadata_type_dup (image, type);
  4600. g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
  4601. mono_metadata_free_type (type);
  4602. mono_loader_unlock ();
  4603. return type2;
  4604. }
  4605. static char*
  4606. mono_image_strndup (MonoImage *image, const char *data, guint len)
  4607. {
  4608. char *res;
  4609. if (!image)
  4610. return g_strndup (data, len);
  4611. res = mono_image_alloc (image, len + 1);
  4612. memcpy (res, data, len);
  4613. res [len] = 0;
  4614. return res;
  4615. }
  4616. MonoMarshalSpec *
  4617. mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
  4618. {
  4619. return mono_metadata_parse_marshal_spec_full (NULL, ptr);
  4620. }
  4621. MonoMarshalSpec *
  4622. mono_metadata_parse_marshal_spec_full (MonoImage *image, const char *ptr)
  4623. {
  4624. MonoMarshalSpec *res;
  4625. int len;
  4626. const char *start = ptr;
  4627. /* fixme: this is incomplete, but I cant find more infos in the specs */
  4628. if (image)
  4629. res = mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
  4630. else
  4631. res = g_new0 (MonoMarshalSpec, 1);
  4632. len = mono_metadata_decode_value (ptr, &ptr);
  4633. res->native = *ptr++;
  4634. if (res->native == MONO_NATIVE_LPARRAY) {
  4635. res->data.array_data.param_num = -1;
  4636. res->data.array_data.num_elem = -1;
  4637. res->data.array_data.elem_mult = -1;
  4638. if (ptr - start <= len)
  4639. res->data.array_data.elem_type = *ptr++;
  4640. if (ptr - start <= len)
  4641. res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
  4642. if (ptr - start <= len)
  4643. res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
  4644. if (ptr - start <= len) {
  4645. /*
  4646. * LAMESPEC: Older spec versions say this parameter comes before
  4647. * num_elem. Never spec versions don't talk about elem_mult at
  4648. * all, but csc still emits it, and it is used to distinguish
  4649. * between param_num being 0, and param_num being omitted.
  4650. * So if (param_num == 0) && (num_elem > 0), then
  4651. * elem_mult == 0 -> the array size is num_elem
  4652. * elem_mult == 1 -> the array size is @param_num + num_elem
  4653. */
  4654. res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
  4655. }
  4656. }
  4657. if (res->native == MONO_NATIVE_BYVALTSTR) {
  4658. if (ptr - start <= len)
  4659. res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
  4660. }
  4661. if (res->native == MONO_NATIVE_BYVALARRAY) {
  4662. if (ptr - start <= len)
  4663. res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
  4664. }
  4665. if (res->native == MONO_NATIVE_CUSTOM) {
  4666. /* skip unused type guid */
  4667. len = mono_metadata_decode_value (ptr, &ptr);
  4668. ptr += len;
  4669. /* skip unused native type name */
  4670. len = mono_metadata_decode_value (ptr, &ptr);
  4671. ptr += len;
  4672. /* read custom marshaler type name */
  4673. len = mono_metadata_decode_value (ptr, &ptr);
  4674. res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);
  4675. ptr += len;
  4676. /* read cookie string */
  4677. len = mono_metadata_decode_value (ptr, &ptr);
  4678. res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
  4679. }
  4680. if (res->native == MONO_NATIVE_SAFEARRAY) {
  4681. res->data.safearray_data.elem_type = 0;
  4682. res->data.safearray_data.num_elem = 0;
  4683. if (ptr - start <= len)
  4684. res->data.safearray_data.elem_type = *ptr++;
  4685. if (ptr - start <= len)
  4686. res->data.safearray_data.num_elem = *ptr++;
  4687. }
  4688. return res;
  4689. }
  4690. void
  4691. mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
  4692. {
  4693. if (spec->native == MONO_NATIVE_CUSTOM) {
  4694. g_free (spec->data.custom_data.custom_name);
  4695. g_free (spec->data.custom_data.cookie);
  4696. }
  4697. g_free (spec);
  4698. }
  4699. /**
  4700. * mono_type_to_unmanaged:
  4701. *
  4702. * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
  4703. * describing the underlying native reprensetation of the type.
  4704. *
  4705. * In addition the value pointed by
  4706. * "conv" will contain the kind of marshalling required for this
  4707. * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
  4708. */
  4709. guint32
  4710. mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
  4711. gboolean unicode, MonoMarshalConv *conv)
  4712. {
  4713. MonoMarshalConv dummy_conv;
  4714. int t = type->type;
  4715. if (!conv)
  4716. conv = &dummy_conv;
  4717. *conv = MONO_MARSHAL_CONV_NONE;
  4718. if (type->byref)
  4719. return MONO_NATIVE_UINT;
  4720. handle_enum:
  4721. switch (t) {
  4722. case MONO_TYPE_BOOLEAN:
  4723. if (mspec) {
  4724. switch (mspec->native) {
  4725. case MONO_NATIVE_VARIANTBOOL:
  4726. *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
  4727. return MONO_NATIVE_VARIANTBOOL;
  4728. case MONO_NATIVE_BOOLEAN:
  4729. *conv = MONO_MARSHAL_CONV_BOOL_I4;
  4730. return MONO_NATIVE_BOOLEAN;
  4731. case MONO_NATIVE_I1:
  4732. case MONO_NATIVE_U1:
  4733. return mspec->native;
  4734. default:
  4735. g_error ("cant marshal bool to native type %02x", mspec->native);
  4736. }
  4737. }
  4738. *conv = MONO_MARSHAL_CONV_BOOL_I4;
  4739. return MONO_NATIVE_BOOLEAN;
  4740. case MONO_TYPE_CHAR:
  4741. if (mspec) {
  4742. switch (mspec->native) {
  4743. case MONO_NATIVE_U2:
  4744. case MONO_NATIVE_U1:
  4745. return mspec->native;
  4746. default:
  4747. g_error ("cant marshal char to native type %02x", mspec->native);
  4748. }
  4749. }
  4750. return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
  4751. case MONO_TYPE_I1: return MONO_NATIVE_I1;
  4752. case MONO_TYPE_U1: return MONO_NATIVE_U1;
  4753. case MONO_TYPE_I2: return MONO_NATIVE_I2;
  4754. case MONO_TYPE_U2: return MONO_NATIVE_U2;
  4755. case MONO_TYPE_I4: return MONO_NATIVE_I4;
  4756. case MONO_TYPE_U4: return MONO_NATIVE_U4;
  4757. case MONO_TYPE_I8: return MONO_NATIVE_I8;
  4758. case MONO_TYPE_U8: return MONO_NATIVE_U8;
  4759. case MONO_TYPE_R4: return MONO_NATIVE_R4;
  4760. case MONO_TYPE_R8: return MONO_NATIVE_R8;
  4761. case MONO_TYPE_STRING:
  4762. if (mspec) {
  4763. switch (mspec->native) {
  4764. case MONO_NATIVE_BSTR:
  4765. *conv = MONO_MARSHAL_CONV_STR_BSTR;
  4766. return MONO_NATIVE_BSTR;
  4767. case MONO_NATIVE_LPSTR:
  4768. *conv = MONO_MARSHAL_CONV_STR_LPSTR;
  4769. return MONO_NATIVE_LPSTR;
  4770. case MONO_NATIVE_LPWSTR:
  4771. *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
  4772. return MONO_NATIVE_LPWSTR;
  4773. case MONO_NATIVE_LPTSTR:
  4774. *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
  4775. return MONO_NATIVE_LPTSTR;
  4776. case MONO_NATIVE_ANSIBSTR:
  4777. *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
  4778. return MONO_NATIVE_ANSIBSTR;
  4779. case MONO_NATIVE_TBSTR:
  4780. *conv = MONO_MARSHAL_CONV_STR_TBSTR;
  4781. return MONO_NATIVE_TBSTR;
  4782. case MONO_NATIVE_BYVALTSTR:
  4783. if (unicode)
  4784. *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
  4785. else
  4786. *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
  4787. return MONO_NATIVE_BYVALTSTR;
  4788. default:
  4789. g_error ("Can not marshal string to native type '%02x': Invalid managed/unmanaged type combination (String fields must be paired with LPStr, LPWStr, BStr or ByValTStr).", mspec->native);
  4790. }
  4791. }
  4792. if (unicode) {
  4793. *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
  4794. return MONO_NATIVE_LPWSTR;
  4795. }
  4796. else {
  4797. *conv = MONO_MARSHAL_CONV_STR_LPSTR;
  4798. return MONO_NATIVE_LPSTR;
  4799. }
  4800. case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
  4801. case MONO_TYPE_VALUETYPE: /*FIXME*/
  4802. if (type->data.klass->enumtype) {
  4803. t = mono_class_enum_basetype (type->data.klass)->type;
  4804. goto handle_enum;
  4805. }
  4806. if (type->data.klass == mono_defaults.handleref_class){
  4807. *conv = MONO_MARSHAL_CONV_HANDLEREF;
  4808. return MONO_NATIVE_INT;
  4809. }
  4810. return MONO_NATIVE_STRUCT;
  4811. case MONO_TYPE_SZARRAY:
  4812. case MONO_TYPE_ARRAY:
  4813. if (mspec) {
  4814. switch (mspec->native) {
  4815. case MONO_NATIVE_BYVALARRAY:
  4816. if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
  4817. *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
  4818. else
  4819. *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
  4820. return MONO_NATIVE_BYVALARRAY;
  4821. case MONO_NATIVE_SAFEARRAY:
  4822. *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
  4823. return MONO_NATIVE_SAFEARRAY;
  4824. case MONO_NATIVE_LPARRAY:
  4825. *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
  4826. return MONO_NATIVE_LPARRAY;
  4827. default:
  4828. g_error ("cant marshal array as native type %02x", mspec->native);
  4829. }
  4830. }
  4831. *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
  4832. return MONO_NATIVE_LPARRAY;
  4833. case MONO_TYPE_I: return MONO_NATIVE_INT;
  4834. case MONO_TYPE_U: return MONO_NATIVE_UINT;
  4835. case MONO_TYPE_CLASS:
  4836. case MONO_TYPE_OBJECT: {
  4837. /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
  4838. if (mspec) {
  4839. switch (mspec->native) {
  4840. case MONO_NATIVE_STRUCT:
  4841. return MONO_NATIVE_STRUCT;
  4842. case MONO_NATIVE_CUSTOM:
  4843. return MONO_NATIVE_CUSTOM;
  4844. case MONO_NATIVE_INTERFACE:
  4845. *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
  4846. return MONO_NATIVE_INTERFACE;
  4847. case MONO_NATIVE_IDISPATCH:
  4848. *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
  4849. return MONO_NATIVE_IDISPATCH;
  4850. case MONO_NATIVE_IUNKNOWN:
  4851. *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
  4852. return MONO_NATIVE_IUNKNOWN;
  4853. case MONO_NATIVE_FUNC:
  4854. if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
  4855. type->data.klass == mono_defaults.delegate_class ||
  4856. type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
  4857. *conv = MONO_MARSHAL_CONV_DEL_FTN;
  4858. return MONO_NATIVE_FUNC;
  4859. }
  4860. /* Fall through */
  4861. default:
  4862. g_error ("cant marshal object as native type %02x", mspec->native);
  4863. }
  4864. }
  4865. if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
  4866. type->data.klass == mono_defaults.delegate_class ||
  4867. type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
  4868. *conv = MONO_MARSHAL_CONV_DEL_FTN;
  4869. return MONO_NATIVE_FUNC;
  4870. }
  4871. if (mono_defaults.safehandle_class && type->data.klass == mono_defaults.safehandle_class){
  4872. *conv = MONO_MARSHAL_CONV_SAFEHANDLE;
  4873. return MONO_NATIVE_INT;
  4874. }
  4875. *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
  4876. return MONO_NATIVE_STRUCT;
  4877. }
  4878. case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
  4879. case MONO_TYPE_GENERICINST:
  4880. type = &type->data.generic_class->container_class->byval_arg;
  4881. t = type->type;
  4882. goto handle_enum;
  4883. case MONO_TYPE_TYPEDBYREF:
  4884. default:
  4885. g_error ("type 0x%02x not handled in marshal", t);
  4886. }
  4887. return MONO_NATIVE_MAX;
  4888. }
  4889. const char*
  4890. mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
  4891. {
  4892. locator_t loc;
  4893. MonoTableInfo *tdef = &meta->tables [MONO_TABLE_FIELDMARSHAL];
  4894. if (!tdef->base)
  4895. return NULL;
  4896. loc.t = tdef;
  4897. loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
  4898. loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
  4899. /* FIXME: Index translation */
  4900. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  4901. return NULL;
  4902. return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
  4903. }
  4904. MonoMethod*
  4905. method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
  4906. {
  4907. guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
  4908. switch (tok & MONO_METHODDEFORREF_MASK) {
  4909. case MONO_METHODDEFORREF_METHODDEF:
  4910. return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
  4911. case MONO_METHODDEFORREF_METHODREF:
  4912. return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
  4913. }
  4914. g_assert_not_reached ();
  4915. return NULL;
  4916. }
  4917. /*
  4918. * mono_class_get_overrides_full:
  4919. *
  4920. * Return the method overrides belonging to class @type_token in @overrides, and
  4921. * the number of overrides in @num_overrides.
  4922. *
  4923. * Returns: TRUE on success, FALSE on failure.
  4924. */
  4925. gboolean
  4926. mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
  4927. MonoGenericContext *generic_context)
  4928. {
  4929. MonoError error;
  4930. locator_t loc;
  4931. MonoTableInfo *tdef = &image->tables [MONO_TABLE_METHODIMPL];
  4932. guint32 start, end;
  4933. gint32 i, num;
  4934. guint32 cols [MONO_METHODIMPL_SIZE];
  4935. MonoMethod **result;
  4936. gint32 ok = TRUE;
  4937. *overrides = NULL;
  4938. if (num_overrides)
  4939. *num_overrides = 0;
  4940. if (!tdef->base)
  4941. return TRUE;
  4942. loc.t = tdef;
  4943. loc.col_idx = MONO_METHODIMPL_CLASS;
  4944. loc.idx = mono_metadata_token_index (type_token);
  4945. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  4946. return TRUE;
  4947. start = loc.result;
  4948. end = start + 1;
  4949. /*
  4950. * We may end up in the middle of the rows...
  4951. */
  4952. while (start > 0) {
  4953. if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
  4954. start--;
  4955. else
  4956. break;
  4957. }
  4958. while (end < tdef->rows) {
  4959. if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
  4960. end++;
  4961. else
  4962. break;
  4963. }
  4964. num = end - start;
  4965. result = g_new (MonoMethod*, num * 2);
  4966. for (i = 0; i < num; ++i) {
  4967. MonoMethod *method;
  4968. if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
  4969. mono_error_cleanup (&error);
  4970. ok = FALSE;
  4971. break;
  4972. }
  4973. mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
  4974. method = method_from_method_def_or_ref (
  4975. image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
  4976. if (method == NULL)
  4977. ok = FALSE;
  4978. result [i * 2] = method;
  4979. method = method_from_method_def_or_ref (
  4980. image, cols [MONO_METHODIMPL_BODY], generic_context);
  4981. if (method == NULL)
  4982. ok = FALSE;
  4983. result [i * 2 + 1] = method;
  4984. }
  4985. *overrides = result;
  4986. if (num_overrides)
  4987. *num_overrides = num;
  4988. return ok;
  4989. }
  4990. /**
  4991. * mono_guid_to_string:
  4992. *
  4993. * Converts a 16 byte Microsoft GUID to the standard string representation.
  4994. */
  4995. char *
  4996. mono_guid_to_string (const guint8 *guid)
  4997. {
  4998. return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  4999. guid[3], guid[2], guid[1], guid[0],
  5000. guid[5], guid[4],
  5001. guid[7], guid[6],
  5002. guid[8], guid[9],
  5003. guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
  5004. }
  5005. static gboolean
  5006. get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
  5007. {
  5008. MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
  5009. guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
  5010. guint32 i, token, found;
  5011. MonoClass *klass, **res;
  5012. GSList *cons = NULL, *tmp;
  5013. MonoGenericContext *context = &container->context;
  5014. *constraints = NULL;
  5015. found = 0;
  5016. for (i = 0; i < tdef->rows; ++i) {
  5017. mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
  5018. if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
  5019. token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
  5020. klass = mono_class_get_full (image, token, context);
  5021. if (!klass) {
  5022. g_slist_free (cons);
  5023. return FALSE;
  5024. }
  5025. cons = g_slist_append (cons, klass);
  5026. ++found;
  5027. } else {
  5028. /* contiguous list finished */
  5029. if (found)
  5030. break;
  5031. }
  5032. }
  5033. if (!found)
  5034. return TRUE;
  5035. res = mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1));
  5036. for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
  5037. res [i] = tmp->data;
  5038. }
  5039. g_slist_free (cons);
  5040. *constraints = res;
  5041. return TRUE;
  5042. }
  5043. /*
  5044. * mono_metadata_get_generic_param_row:
  5045. *
  5046. * @image:
  5047. * @token: TypeOrMethodDef token, owner for GenericParam
  5048. * @owner: coded token, set on return
  5049. *
  5050. * Returns: 1-based row-id in the GenericParam table whose
  5051. * owner is @token. 0 if not found.
  5052. */
  5053. guint32
  5054. mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
  5055. {
  5056. MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
  5057. locator_t loc;
  5058. g_assert (owner);
  5059. if (!tdef->base)
  5060. return 0;
  5061. if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
  5062. *owner = MONO_TYPEORMETHOD_TYPE;
  5063. else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
  5064. *owner = MONO_TYPEORMETHOD_METHOD;
  5065. else {
  5066. g_error ("wrong token %x to get_generic_param_row", token);
  5067. return 0;
  5068. }
  5069. *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
  5070. loc.idx = *owner;
  5071. loc.col_idx = MONO_GENERICPARAM_OWNER;
  5072. loc.t = tdef;
  5073. if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
  5074. return 0;
  5075. /* Find the first entry by searching backwards */
  5076. while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_GENERICPARAM_OWNER) == loc.idx))
  5077. loc.result --;
  5078. return loc.result + 1;
  5079. }
  5080. gboolean
  5081. mono_metadata_has_generic_params (MonoImage *image, guint32 token)
  5082. {
  5083. guint32 owner;
  5084. return mono_metadata_get_generic_param_row (image, token, &owner);
  5085. }
  5086. /*
  5087. * Memory is allocated from IMAGE's mempool.
  5088. */
  5089. gboolean
  5090. mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
  5091. MonoGenericContainer *container)
  5092. {
  5093. guint32 start_row, i, owner;
  5094. if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
  5095. return TRUE;
  5096. for (i = 0; i < container->type_argc; i++) {
  5097. if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container))
  5098. return FALSE;
  5099. }
  5100. return TRUE;
  5101. }
  5102. /*
  5103. * mono_metadata_load_generic_param_constraints:
  5104. *
  5105. * @image: metadata context
  5106. * @token: metadata token to load the contraints, can be methodef or typedef.
  5107. * @container: generic container to load into.
  5108. *
  5109. * Load the generic parameter constraints for the newly created generic type or method
  5110. * represented by @token and @container. The @container is the new container which has
  5111. * been returned by a call to mono_metadata_load_generic_params() with this @token.
  5112. * Memory is allocated from IMAGE's mempool.
  5113. */
  5114. void
  5115. mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
  5116. MonoGenericContainer *container)
  5117. {
  5118. mono_metadata_load_generic_param_constraints_full (image, token, container);
  5119. /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
  5120. }
  5121. /*
  5122. * mono_metadata_load_generic_params:
  5123. *
  5124. * Load the type parameters from the type or method definition @token.
  5125. *
  5126. * Use this method after parsing a type or method definition to figure out whether it's a generic
  5127. * type / method. When parsing a method definition, @parent_container points to the generic container
  5128. * of the current class, if any.
  5129. *
  5130. * Note: This method does not load the constraints: for typedefs, this has to be done after fully
  5131. * creating the type.
  5132. *
  5133. * Returns: NULL if @token is not a generic type or method definition or the new generic container.
  5134. *
  5135. * LOCKING: Acquires the loader lock
  5136. *
  5137. */
  5138. MonoGenericContainer *
  5139. mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
  5140. {
  5141. MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
  5142. guint32 cols [MONO_GENERICPARAM_SIZE];
  5143. guint32 i, owner = 0, n;
  5144. MonoGenericContainer *container;
  5145. MonoGenericParamFull *params;
  5146. MonoGenericContext *context;
  5147. if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
  5148. return NULL;
  5149. mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
  5150. params = NULL;
  5151. n = 0;
  5152. container = mono_image_alloc0 (image, sizeof (MonoGenericContainer));
  5153. container->image = image;
  5154. do {
  5155. n++;
  5156. params = g_realloc (params, sizeof (MonoGenericParamFull) * n);
  5157. memset (&params [n - 1], 0, sizeof (MonoGenericParamFull));
  5158. params [n - 1].param.owner = container;
  5159. params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
  5160. params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
  5161. params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
  5162. params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
  5163. if (params [n - 1].param.num != n - 1)
  5164. g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
  5165. if (++i > tdef->rows)
  5166. break;
  5167. mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
  5168. } while (cols [MONO_GENERICPARAM_OWNER] == owner);
  5169. container->type_argc = n;
  5170. container->type_params = mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
  5171. memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
  5172. g_free (params);
  5173. container->parent = parent_container;
  5174. if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
  5175. container->is_method = 1;
  5176. g_assert (container->parent == NULL || container->is_method);
  5177. context = &container->context;
  5178. if (container->is_method) {
  5179. context->class_inst = container->parent ? container->parent->context.class_inst : NULL;
  5180. context->method_inst = mono_get_shared_generic_inst (container);
  5181. } else {
  5182. context->class_inst = mono_get_shared_generic_inst (container);
  5183. }
  5184. return container;
  5185. }
  5186. MonoGenericInst *
  5187. mono_get_shared_generic_inst (MonoGenericContainer *container)
  5188. {
  5189. MonoType **type_argv;
  5190. MonoType *helper;
  5191. MonoGenericInst *nginst;
  5192. int i;
  5193. type_argv = g_new0 (MonoType *, container->type_argc);
  5194. helper = g_new0 (MonoType, container->type_argc);
  5195. for (i = 0; i < container->type_argc; i++) {
  5196. MonoType *t = &helper [i];
  5197. t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
  5198. t->data.generic_param = mono_generic_container_get_param (container, i);
  5199. type_argv [i] = t;
  5200. }
  5201. nginst = mono_metadata_get_generic_inst (container->type_argc, type_argv);
  5202. g_free (type_argv);
  5203. g_free (helper);
  5204. return nginst;
  5205. }
  5206. /**
  5207. * mono_type_is_byref:
  5208. * @type: the MonoType operated on
  5209. *
  5210. * Returns: #TRUE if @type represents a type passed by reference,
  5211. * #FALSE otherwise.
  5212. */
  5213. gboolean
  5214. mono_type_is_byref (MonoType *type)
  5215. {
  5216. return type->byref;
  5217. }
  5218. /**
  5219. * mono_type_get_type:
  5220. * @type: the MonoType operated on
  5221. *
  5222. * Returns: the IL type value for @type. This is one of the MonoTypeEnum
  5223. * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
  5224. */
  5225. int
  5226. mono_type_get_type (MonoType *type)
  5227. {
  5228. return type->type;
  5229. }
  5230. /**
  5231. * mono_type_get_signature:
  5232. * @type: the MonoType operated on
  5233. *
  5234. * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
  5235. *
  5236. * Returns: the MonoMethodSignature pointer that describes the signature
  5237. * of the function pointer @type represents.
  5238. */
  5239. MonoMethodSignature*
  5240. mono_type_get_signature (MonoType *type)
  5241. {
  5242. g_assert (type->type == MONO_TYPE_FNPTR);
  5243. return type->data.method;
  5244. }
  5245. /**
  5246. * mono_type_get_class:
  5247. * @type: the MonoType operated on
  5248. *
  5249. * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
  5250. * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
  5251. * instead
  5252. *
  5253. * Returns: the MonoClass pointer that describes the class that @type represents.
  5254. */
  5255. MonoClass*
  5256. mono_type_get_class (MonoType *type)
  5257. {
  5258. /* FIXME: review the runtime users before adding the assert here */
  5259. return type->data.klass;
  5260. }
  5261. /**
  5262. * mono_type_get_array_type:
  5263. * @type: the MonoType operated on
  5264. *
  5265. * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
  5266. *
  5267. * Returns: a MonoArrayType struct describing the array type that @type
  5268. * represents. The info includes details such as rank, array element type
  5269. * and the sizes and bounds of multidimensional arrays.
  5270. */
  5271. MonoArrayType*
  5272. mono_type_get_array_type (MonoType *type)
  5273. {
  5274. return type->data.array;
  5275. }
  5276. /**
  5277. * mono_type_get_ptr_type:
  5278. * @type: the MonoType operated on
  5279. *
  5280. * It is only valid to call this function if @type is a MONO_TYPE_PTR.
  5281. * instead
  5282. *
  5283. * Returns: the MonoType pointer that describes the type that @type
  5284. * represents a pointer to.
  5285. */
  5286. MonoType*
  5287. mono_type_get_ptr_type (MonoType *type)
  5288. {
  5289. g_assert (type->type == MONO_TYPE_PTR);
  5290. return type->data.type;
  5291. }
  5292. MonoClass*
  5293. mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
  5294. {
  5295. /* FIXME: implement */
  5296. return NULL;
  5297. }
  5298. /**
  5299. * mono_type_is_struct:
  5300. * @type: the MonoType operated on
  5301. *
  5302. * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
  5303. * or a basic type like System.Int32. #FALSE otherwise.
  5304. */
  5305. mono_bool
  5306. mono_type_is_struct (MonoType *type)
  5307. {
  5308. return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE &&
  5309. !type->data.klass->enumtype) || (type->type == MONO_TYPE_TYPEDBYREF) ||
  5310. ((type->type == MONO_TYPE_GENERICINST) &&
  5311. mono_metadata_generic_class_is_valuetype (type->data.generic_class) &&
  5312. !type->data.generic_class->container_class->enumtype)));
  5313. }
  5314. /**
  5315. * mono_type_is_void:
  5316. * @type: the MonoType operated on
  5317. *
  5318. * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
  5319. */
  5320. mono_bool
  5321. mono_type_is_void (MonoType *type)
  5322. {
  5323. return (type && (type->type == MONO_TYPE_VOID) && !type->byref);
  5324. }
  5325. /**
  5326. * mono_type_is_pointer:
  5327. * @type: the MonoType operated on
  5328. *
  5329. * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
  5330. */
  5331. mono_bool
  5332. mono_type_is_pointer (MonoType *type)
  5333. {
  5334. return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING)
  5335. || (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
  5336. (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) ||
  5337. (type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) ||
  5338. (type->type == MONO_TYPE_FNPTR)));
  5339. }
  5340. /**
  5341. * mono_type_is_reference:
  5342. * @type: the MonoType operated on
  5343. *
  5344. * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
  5345. */
  5346. mono_bool
  5347. mono_type_is_reference (MonoType *type)
  5348. {
  5349. return (type && (((type->type == MONO_TYPE_STRING) ||
  5350. (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
  5351. (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) ||
  5352. ((type->type == MONO_TYPE_GENERICINST) &&
  5353. !mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
  5354. }
  5355. /**
  5356. * mono_signature_get_return_type:
  5357. * @sig: the method signature inspected
  5358. *
  5359. * Returns: the return type of the method signature @sig
  5360. */
  5361. MonoType*
  5362. mono_signature_get_return_type (MonoMethodSignature *sig)
  5363. {
  5364. return sig->ret;
  5365. }
  5366. /**
  5367. * mono_signature_get_params:
  5368. * @sig: the method signature inspected
  5369. * #iter: pointer to an iterator
  5370. *
  5371. * Iterates over the parameters for the method signature @sig.
  5372. * A void* pointer must be initualized to #NULL to start the iteration
  5373. * and it's address is passed to this function repeteadly until it returns
  5374. * #NULL.
  5375. *
  5376. * Returns: the next parameter type of the method signature @sig,
  5377. * #NULL when finished.
  5378. */
  5379. MonoType*
  5380. mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
  5381. {
  5382. MonoType** type;
  5383. if (!iter)
  5384. return NULL;
  5385. if (!*iter) {
  5386. /* start from the first */
  5387. if (sig->param_count) {
  5388. *iter = &sig->params [0];
  5389. return sig->params [0];
  5390. } else {
  5391. /* no method */
  5392. return NULL;
  5393. }
  5394. }
  5395. type = *iter;
  5396. type++;
  5397. if (type < &sig->params [sig->param_count]) {
  5398. *iter = type;
  5399. return *type;
  5400. }
  5401. return NULL;
  5402. }
  5403. /**
  5404. * mono_signature_get_param_count:
  5405. * @sig: the method signature inspected
  5406. *
  5407. * Returns: the number of parameters in the method signature @sig.
  5408. */
  5409. guint32
  5410. mono_signature_get_param_count (MonoMethodSignature *sig)
  5411. {
  5412. return sig->param_count;
  5413. }
  5414. /**
  5415. * mono_signature_get_call_conv:
  5416. * @sig: the method signature inspected
  5417. *
  5418. * Returns: the call convention of the method signature @sig.
  5419. */
  5420. guint32
  5421. mono_signature_get_call_conv (MonoMethodSignature *sig)
  5422. {
  5423. return sig->call_convention;
  5424. }
  5425. /**
  5426. * mono_signature_vararg_start:
  5427. * @sig: the method signature inspected
  5428. *
  5429. * Returns: the number of the first vararg parameter in the
  5430. * method signature @sig. -1 if this is not a vararg signature.
  5431. */
  5432. int
  5433. mono_signature_vararg_start (MonoMethodSignature *sig)
  5434. {
  5435. return sig->sentinelpos;
  5436. }
  5437. /**
  5438. * mono_signature_is_instance:
  5439. * @sig: the method signature inspected
  5440. *
  5441. * Returns: #TRUE if this the method signature @sig has an implicit
  5442. * first instance argument. #FALSE otherwise.
  5443. */
  5444. gboolean
  5445. mono_signature_is_instance (MonoMethodSignature *sig)
  5446. {
  5447. return sig->hasthis;
  5448. }
  5449. /**
  5450. * mono_signature_explicit_this:
  5451. * @sig: the method signature inspected
  5452. *
  5453. * Returns: #TRUE if this the method signature @sig has an explicit
  5454. * instance argument. #FALSE otherwise.
  5455. */
  5456. gboolean
  5457. mono_signature_explicit_this (MonoMethodSignature *sig)
  5458. {
  5459. return sig->explicit_this;
  5460. }
  5461. /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
  5462. guint
  5463. mono_aligned_addr_hash (gconstpointer ptr)
  5464. {
  5465. return GPOINTER_TO_UINT (ptr) >> 3;
  5466. }
  5467. /*
  5468. * If @field belongs to an inflated generic class, return the corresponding field of the
  5469. * generic type definition class.
  5470. */
  5471. MonoClassField*
  5472. mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField *field)
  5473. {
  5474. MonoClass *gtd;
  5475. int offset;
  5476. if (!field->parent->generic_class)
  5477. return field;
  5478. gtd = field->parent->generic_class->container_class;
  5479. offset = field - field->parent->fields;
  5480. return gtd->fields + offset;
  5481. }
  5482. /*
  5483. * If @event belongs to an inflated generic class, return the corresponding event of the
  5484. * generic type definition class.
  5485. */
  5486. MonoEvent*
  5487. mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *event)
  5488. {
  5489. MonoClass *gtd;
  5490. int offset;
  5491. if (!event->parent->generic_class)
  5492. return event;
  5493. gtd = event->parent->generic_class->container_class;
  5494. offset = event - event->parent->ext->events;
  5495. return gtd->ext->events + offset;
  5496. }
  5497. /*
  5498. * If @property belongs to an inflated generic class, return the corresponding property of the
  5499. * generic type definition class.
  5500. */
  5501. MonoProperty*
  5502. mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty *property)
  5503. {
  5504. MonoClass *gtd;
  5505. int offset;
  5506. if (!property->parent->generic_class)
  5507. return property;
  5508. gtd = property->parent->generic_class->container_class;
  5509. offset = property - property->parent->ext->properties;
  5510. return gtd->ext->properties + offset;
  5511. }