/mono/metadata/metadata.c
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
Large files files are truncated, but you can click here to view the full file
- /*
- * metadata.c: Routines for accessing the metadata
- *
- * Authors:
- * Miguel de Icaza (miguel@ximian.com)
- * Paolo Molaro (lupus@ximian.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- */
- #include <config.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <glib.h>
- #include "metadata.h"
- #include "tabledefs.h"
- #include "mono-endian.h"
- #include "cil-coff.h"
- #include "tokentype.h"
- #include "metadata-internals.h"
- #include "class-internals.h"
- #include "verify-internals.h"
- #include "class.h"
- #include "marshal.h"
- #include "debug-helpers.h"
- #include <mono/utils/mono-error-internals.h>
-
- /* Auxiliary structure used for caching inflated signatures */
- typedef struct {
- MonoMethodSignature *sig;
- MonoGenericContext context;
- } MonoInflatedMethodSignature;
- static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
- const char *ptr, const char **rptr);
- static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
- static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
- static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
- static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
- gboolean signature_only);
- static void free_generic_inst (MonoGenericInst *ginst);
- static void free_generic_class (MonoGenericClass *ginst);
- static void free_inflated_method (MonoMethodInflated *method);
- static void free_inflated_signature (MonoInflatedMethodSignature *sig);
- static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
- /*
- * This enumeration is used to describe the data types in the metadata
- * tables
- */
- enum {
- MONO_MT_END,
- /* Sized elements */
- MONO_MT_UINT32,
- MONO_MT_UINT16,
- MONO_MT_UINT8,
- /* Index into Blob heap */
- MONO_MT_BLOB_IDX,
- /* Index into String heap */
- MONO_MT_STRING_IDX,
- /* GUID index */
- MONO_MT_GUID_IDX,
- /* Pointer into a table */
- MONO_MT_TABLE_IDX,
- /* HasConstant:Parent pointer (Param, Field or Property) */
- MONO_MT_CONST_IDX,
- /* HasCustomAttribute index. Indexes any table except CustomAttribute */
- MONO_MT_HASCAT_IDX,
-
- /* CustomAttributeType encoded index */
- MONO_MT_CAT_IDX,
- /* HasDeclSecurity index: TypeDef Method or Assembly */
- MONO_MT_HASDEC_IDX,
- /* Implementation coded index: File, Export AssemblyRef */
- MONO_MT_IMPL_IDX,
- /* HasFieldMarshal coded index: Field or Param table */
- MONO_MT_HFM_IDX,
- /* MemberForwardedIndex: Field or Method */
- MONO_MT_MF_IDX,
- /* TypeDefOrRef coded index: typedef, typeref, typespec */
- MONO_MT_TDOR_IDX,
- /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
- MONO_MT_MRP_IDX,
- /* MethodDefOrRef coded index: Method or Member Ref table */
- MONO_MT_MDOR_IDX,
- /* HasSemantic coded index: Event or Property */
- MONO_MT_HS_IDX,
- /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
- MONO_MT_RS_IDX
- };
- const static unsigned char TableSchemas [] = {
- #define ASSEMBLY_SCHEMA_OFFSET 0
- MONO_MT_UINT32, /* "HashId" }, */
- MONO_MT_UINT16, /* "Major" }, */
- MONO_MT_UINT16, /* "Minor" }, */
- MONO_MT_UINT16, /* "BuildNumber" }, */
- MONO_MT_UINT16, /* "RevisionNumber" }, */
- MONO_MT_UINT32, /* "Flags" }, */
- MONO_MT_BLOB_IDX, /* "PublicKey" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_STRING_IDX, /* "Culture" }, */
- MONO_MT_END,
- #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
- MONO_MT_UINT32, /* "OSPlatformID" }, */
- MONO_MT_UINT32, /* "OSMajor" }, */
- MONO_MT_UINT32, /* "OSMinor" }, */
- MONO_MT_END,
- #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
- MONO_MT_UINT32, /* "Processor" }, */
- MONO_MT_END,
- #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
- MONO_MT_UINT16, /* "Major" }, */
- MONO_MT_UINT16, /* "Minor" }, */
- MONO_MT_UINT16, /* "Build" }, */
- MONO_MT_UINT16, /* "Revision" }, */
- MONO_MT_UINT32, /* "Flags" }, */
- MONO_MT_BLOB_IDX, /* "PublicKeyOrToken" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_STRING_IDX, /* "Culture" }, */
- MONO_MT_BLOB_IDX, /* "HashValue" }, */
- MONO_MT_END,
- #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
- MONO_MT_UINT32, /* "OSPlatformID" }, */
- MONO_MT_UINT32, /* "OSMajorVersion" }, */
- MONO_MT_UINT32, /* "OSMinorVersion" }, */
- MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
- MONO_MT_END,
- #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
- MONO_MT_UINT32, /* "Processor" }, */
- MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
- MONO_MT_END,
- #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
- MONO_MT_UINT16, /* "PackingSize" }, */
- MONO_MT_UINT32, /* "ClassSize" }, */
- MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
- MONO_MT_END,
- #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
- MONO_MT_UINT8, /* "Type" }, */
- MONO_MT_UINT8, /* "PaddingZero" }, */
- MONO_MT_CONST_IDX, /* "Parent" }, */
- MONO_MT_BLOB_IDX, /* "Value" }, */
- MONO_MT_END,
- #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
- MONO_MT_HASCAT_IDX, /* "Parent" }, */
- MONO_MT_CAT_IDX, /* "Type" }, */
- MONO_MT_BLOB_IDX, /* "Value" }, */
- MONO_MT_END,
- #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
- MONO_MT_UINT16, /* "Action" }, */
- MONO_MT_HASDEC_IDX, /* "Parent" }, */
- MONO_MT_BLOB_IDX, /* "PermissionSet" }, */
- MONO_MT_END,
- #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
- MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
- MONO_MT_TABLE_IDX, /* "EventList:Event" }, */
- MONO_MT_END,
- #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
- MONO_MT_UINT16, /* "EventFlags#EventAttribute" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_TDOR_IDX, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
- MONO_MT_END,
- #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
- MONO_MT_TABLE_IDX, /* "Event" }, */
- MONO_MT_END,
- #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
- MONO_MT_UINT32, /* "Flags" }, */
- MONO_MT_TABLE_IDX, /* "TypeDefId" }, */
- MONO_MT_STRING_IDX, /* "TypeName" }, */
- MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
- MONO_MT_IMPL_IDX, /* "Implementation" }, */
- MONO_MT_END,
- #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
- MONO_MT_UINT16, /* "Flags" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END,
- #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
- MONO_MT_UINT32, /* "Offset" }, */
- MONO_MT_TABLE_IDX, /* "Field:Field" }, */
- MONO_MT_END,
- #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
- MONO_MT_HFM_IDX, /* "Parent" }, */
- MONO_MT_BLOB_IDX, /* "NativeType" }, */
- MONO_MT_END,
- #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
- MONO_MT_UINT32, /* "RVA" }, */
- MONO_MT_TABLE_IDX, /* "Field:Field" }, */
- MONO_MT_END,
- #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
- MONO_MT_TABLE_IDX, /* "Field" }, */
- MONO_MT_END,
- #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
- MONO_MT_UINT32, /* "Flags" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_BLOB_IDX, /* "Value" }, */
- MONO_MT_END,
- #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
- MONO_MT_UINT16, /* "MappingFlag" }, */
- MONO_MT_MF_IDX, /* "MemberForwarded" }, */
- MONO_MT_STRING_IDX, /* "ImportName" }, */
- MONO_MT_TABLE_IDX, /* "ImportScope:ModuleRef" }, */
- MONO_MT_END,
- #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
- MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
- MONO_MT_TDOR_IDX, /* "Interface=TypeDefOrRef" }, */
- MONO_MT_END,
- #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
- MONO_MT_UINT32, /* "Offset" }, */
- MONO_MT_UINT32, /* "Flags" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_IMPL_IDX, /* "Implementation" }, */
- MONO_MT_END,
- #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
- MONO_MT_MRP_IDX, /* "Class" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END,
- #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
- MONO_MT_UINT32, /* "RVA" }, */
- MONO_MT_UINT16, /* "ImplFlags#MethodImplAttributes" }, */
- MONO_MT_UINT16, /* "Flags#MethodAttribute" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_TABLE_IDX, /* "ParamList:Param" }, */
- MONO_MT_END,
- #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
- MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
- MONO_MT_MDOR_IDX, /* "MethodBody" }, */
- MONO_MT_MDOR_IDX, /* "MethodDeclaration" }, */
- MONO_MT_END,
- #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
- MONO_MT_UINT16, /* "MethodSemantic" }, */
- MONO_MT_TABLE_IDX, /* "Method:Method" }, */
- MONO_MT_HS_IDX, /* "Association" }, */
- MONO_MT_END,
- #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
- MONO_MT_TABLE_IDX, /* "Method" }, */
- MONO_MT_END,
- #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
- MONO_MT_UINT16, /* "Generation" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_GUID_IDX, /* "MVID" }, */
- MONO_MT_GUID_IDX, /* "EncID" }, */
- MONO_MT_GUID_IDX, /* "EncBaseID" }, */
- MONO_MT_END,
- #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_END,
- #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
- MONO_MT_TABLE_IDX, /* "NestedClass:TypeDef" }, */
- MONO_MT_TABLE_IDX, /* "EnclosingClass:TypeDef" }, */
- MONO_MT_END,
- #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
- MONO_MT_UINT16, /* "Flags" }, */
- MONO_MT_UINT16, /* "Sequence" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_END,
- #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
- MONO_MT_TABLE_IDX, /* "Param" }, */
- MONO_MT_END,
- #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
- MONO_MT_UINT16, /* "Flags" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_BLOB_IDX, /* "Type" }, */
- MONO_MT_END,
- #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
- MONO_MT_TABLE_IDX, /* "Property" }, */
- MONO_MT_END,
- #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
- MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
- MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */
- MONO_MT_END,
- #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
- MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END,
- #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
- MONO_MT_UINT32, /* "Flags" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_STRING_IDX, /* "Namespace" }, */
- MONO_MT_TDOR_IDX, /* "Extends" }, */
- MONO_MT_TABLE_IDX, /* "FieldList:Field" }, */
- MONO_MT_TABLE_IDX, /* "MethodList:Method" }, */
- MONO_MT_END,
- #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
- MONO_MT_RS_IDX, /* "ResolutionScope=ResolutionScope" }, */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_STRING_IDX, /* "Namespace" }, */
- MONO_MT_END,
- #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
- MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END,
- #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
- MONO_MT_UINT16, /* "Number" }, */
- MONO_MT_UINT16, /* "Flags" }, */
- MONO_MT_TABLE_IDX, /* "Owner" }, TypeDef or MethodDef */
- MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_END,
- #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
- MONO_MT_MDOR_IDX, /* "Method" }, */
- MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END,
- #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
- MONO_MT_TABLE_IDX, /* "GenericParam" }, */
- MONO_MT_TDOR_IDX, /* "Constraint" }, */
- MONO_MT_END,
- #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
- MONO_MT_END
- };
- /* Must be the same order as MONO_TABLE_* */
- const static unsigned char
- table_description [] = {
- MODULE_SCHEMA_OFFSET,
- TYPEREF_SCHEMA_OFFSET,
- TYPEDEF_SCHEMA_OFFSET,
- FIELD_POINTER_SCHEMA_OFFSET,
- FIELD_SCHEMA_OFFSET,
- METHOD_POINTER_SCHEMA_OFFSET,
- METHOD_SCHEMA_OFFSET,
- PARAM_POINTER_SCHEMA_OFFSET,
- PARAM_SCHEMA_OFFSET,
- IFACEMAP_SCHEMA_OFFSET,
- MEMBERREF_SCHEMA_OFFSET, /* 0xa */
- CONSTANT_SCHEMA_OFFSET,
- CUSTOM_ATTR_SCHEMA_OFFSET,
- FIELD_MARSHAL_SCHEMA_OFFSET,
- DECL_SEC_SCHEMA_OFFSET,
- CLASS_LAYOUT_SCHEMA_OFFSET,
- FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
- STDALON_SIG_SCHEMA_OFFSET,
- EVENTMAP_SCHEMA_OFFSET,
- EVENT_POINTER_SCHEMA_OFFSET,
- EVENT_SCHEMA_OFFSET,
- PROPERTY_MAP_SCHEMA_OFFSET,
- PROPERTY_POINTER_SCHEMA_OFFSET,
- PROPERTY_SCHEMA_OFFSET,
- METHOD_SEMA_SCHEMA_OFFSET,
- METHOD_IMPL_SCHEMA_OFFSET,
- MODULEREF_SCHEMA_OFFSET, /* 0x1a */
- TYPESPEC_SCHEMA_OFFSET,
- IMPLMAP_SCHEMA_OFFSET,
- FIELD_RVA_SCHEMA_OFFSET,
- NULL_SCHEMA_OFFSET,
- NULL_SCHEMA_OFFSET,
- ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
- ASSEMBLYPROC_SCHEMA_OFFSET,
- ASSEMBLYOS_SCHEMA_OFFSET,
- ASSEMBLYREF_SCHEMA_OFFSET,
- ASSEMBLYREFPROC_SCHEMA_OFFSET,
- ASSEMBLYREFOS_SCHEMA_OFFSET,
- FILE_SCHEMA_OFFSET,
- EXPORTED_TYPE_SCHEMA_OFFSET,
- MANIFEST_SCHEMA_OFFSET,
- NESTED_CLASS_SCHEMA_OFFSET,
- GENPARAM_SCHEMA_OFFSET, /* 0x2a */
- METHOD_SPEC_SCHEMA_OFFSET,
- GEN_CONSTRAINT_SCHEMA_OFFSET
- };
- #ifdef HAVE_ARRAY_ELEM_INIT
- #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
- #define MSGSTRFIELD1(line) str##line
- static const struct msgstr_t {
- #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
- #include "mono/cil/tables.def"
- #undef TABLEDEF
- } tablestr = {
- #define TABLEDEF(a,b) b,
- #include "mono/cil/tables.def"
- #undef TABLEDEF
- };
- static const gint16 tableidx [] = {
- #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
- #include "mono/cil/tables.def"
- #undef TABLEDEF
- };
- #else
- #define TABLEDEF(a,b) b,
- static const char* const
- mono_tables_names [] = {
- #include "mono/cil/tables.def"
- NULL
- };
- #endif
- /**
- * mono_meta_table_name:
- * @table: table index
- *
- * Returns the name of the given ECMA metadata logical format table
- * as described in ECMA 335, Partition II, Section 22.
- *
- * Returns: the name for the @table index
- */
- const char *
- mono_meta_table_name (int table)
- {
- if ((table < 0) || (table > MONO_TABLE_LAST))
- return "";
- #ifdef HAVE_ARRAY_ELEM_INIT
- return (const char*)&tablestr + tableidx [table];
- #else
- return mono_tables_names [table];
- #endif
- }
- /* The guy who wrote the spec for this should not be allowed near a
- * computer again.
-
- If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
- then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
- rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
- finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
- inverse of this mapping.
- */
- #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
- #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
- /* Reference: Partition II - 23.2.6 */
- /*
- * mono_metadata_compute_size:
- * @meta: metadata context
- * @tableindex: metadata table number
- * @result_bitfield: pointer to guint32 where to store additional info
- *
- * mono_metadata_compute_size() computes the lenght in bytes of a single
- * row in a metadata table. The size of each column is encoded in the
- * @result_bitfield return value along with the number of columns in the table.
- * the resulting bitfield should be handed to the mono_metadata_table_size()
- * and mono_metadata_table_count() macros.
- * This is a Mono runtime internal only function.
- */
- int
- mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
- {
- guint32 bitfield = 0;
- int size = 0, field_size = 0;
- int i, n, code;
- int shift = 0;
- const unsigned char *description = TableSchemas + table_description [tableindex];
- for (i = 0; (code = description [i]) != MONO_MT_END; i++){
- switch (code){
- case MONO_MT_UINT32:
- field_size = 4; break;
-
- case MONO_MT_UINT16:
- field_size = 2; break;
-
- case MONO_MT_UINT8:
- field_size = 1; break;
-
- case MONO_MT_BLOB_IDX:
- field_size = meta->idx_blob_wide ? 4 : 2; break;
-
- case MONO_MT_STRING_IDX:
- field_size = meta->idx_string_wide ? 4 : 2; break;
-
- case MONO_MT_GUID_IDX:
- field_size = meta->idx_guid_wide ? 4 : 2; break;
- case MONO_MT_TABLE_IDX:
- /* Uhm, a table index can point to other tables besides the current one
- * so, it's not correct to use the rowcount of the current table to
- * get the size for this column - lupus
- */
- switch (tableindex) {
- case MONO_TABLE_ASSEMBLYREFOS:
- g_assert (i == 3);
- field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
- case MONO_TABLE_ASSEMBLYREFPROCESSOR:
- g_assert (i == 1);
- field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
- case MONO_TABLE_CLASSLAYOUT:
- g_assert (i == 2);
- field_size = idx_size (MONO_TABLE_TYPEDEF); break;
- case MONO_TABLE_EVENTMAP:
- g_assert (i == 0 || i == 1);
- field_size = i ? idx_size (MONO_TABLE_EVENT):
- idx_size(MONO_TABLE_TYPEDEF);
- break;
- case MONO_TABLE_EVENT_POINTER:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_EVENT); break;
- case MONO_TABLE_EXPORTEDTYPE:
- g_assert (i == 1);
- /* the index is in another metadata file, so it must be 4 */
- field_size = 4; break;
- case MONO_TABLE_FIELDLAYOUT:
- g_assert (i == 1);
- field_size = idx_size (MONO_TABLE_FIELD); break;
- case MONO_TABLE_FIELDRVA:
- g_assert (i == 1);
- field_size = idx_size (MONO_TABLE_FIELD); break;
- case MONO_TABLE_FIELD_POINTER:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_FIELD); break;
- case MONO_TABLE_IMPLMAP:
- g_assert (i == 3);
- field_size = idx_size (MONO_TABLE_MODULEREF); break;
- case MONO_TABLE_INTERFACEIMPL:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_TYPEDEF); break;
- case MONO_TABLE_METHOD:
- g_assert (i == 5);
- field_size = idx_size (MONO_TABLE_PARAM); break;
- case MONO_TABLE_METHODIMPL:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_TYPEDEF); break;
- case MONO_TABLE_METHODSEMANTICS:
- g_assert (i == 1);
- field_size = idx_size (MONO_TABLE_METHOD); break;
- case MONO_TABLE_METHOD_POINTER:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_METHOD); break;
- case MONO_TABLE_NESTEDCLASS:
- g_assert (i == 0 || i == 1);
- field_size = idx_size (MONO_TABLE_TYPEDEF); break;
- case MONO_TABLE_PARAM_POINTER:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_PARAM); break;
- case MONO_TABLE_PROPERTYMAP:
- g_assert (i == 0 || i == 1);
- field_size = i ? idx_size (MONO_TABLE_PROPERTY):
- idx_size(MONO_TABLE_TYPEDEF);
- break;
- case MONO_TABLE_PROPERTY_POINTER:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_PROPERTY); break;
- case MONO_TABLE_TYPEDEF:
- g_assert (i == 4 || i == 5);
- field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
- idx_size(MONO_TABLE_METHOD);
- break;
- case MONO_TABLE_GENERICPARAM:
- g_assert (i == 2);
- n = MAX (meta->tables [MONO_TABLE_METHOD].rows, meta->tables [MONO_TABLE_TYPEDEF].rows);
- /*This is a coded token for 2 tables, so takes 1 bit */
- field_size = rtsize (n, 16 - MONO_TYPEORMETHOD_BITS);
- break;
- case MONO_TABLE_GENERICPARAMCONSTRAINT:
- g_assert (i == 0);
- field_size = idx_size (MONO_TABLE_GENERICPARAM);
- break;
-
- default:
- g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
- }
- break;
- /*
- * HasConstant: ParamDef, FieldDef, Property
- */
- case MONO_MT_CONST_IDX:
- n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
- meta->tables [MONO_TABLE_FIELD].rows);
- n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
- /* 2 bits to encode tag */
- field_size = rtsize (n, 16-2);
- break;
- /*
- * HasCustomAttribute: points to any table but
- * itself.
- */
- case MONO_MT_HASCAT_IDX:
- /*
- * We believe that since the signature and
- * permission are indexing the Blob heap,
- * we should consider the blob size first
- */
- /* I'm not a believer - lupus
- if (meta->idx_blob_wide){
- field_size = 4;
- break;
- }*/
-
- n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
- meta->tables [MONO_TABLE_FIELD].rows);
- n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
- n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
- n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
- n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
- n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
- n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
- n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
- n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
- n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
- n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
- n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
- n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
- /* 5 bits to encode */
- field_size = rtsize (n, 16-5);
- break;
- /*
- * CustomAttributeType: TypeDef, TypeRef, MethodDef,
- * MemberRef and String.
- */
- case MONO_MT_CAT_IDX:
- /* String is a heap, if it is wide, we know the size */
- /* See above, nope.
- if (meta->idx_string_wide){
- field_size = 4;
- break;
- }*/
-
- n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
- meta->tables [MONO_TABLE_TYPEDEF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
- n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
- /* 3 bits to encode */
- field_size = rtsize (n, 16-3);
- break;
- /*
- * HasDeclSecurity: Typedef, MethodDef, Assembly
- */
- case MONO_MT_HASDEC_IDX:
- n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
- meta->tables [MONO_TABLE_METHOD].rows);
- n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
- /* 2 bits to encode */
- field_size = rtsize (n, 16-2);
- break;
- /*
- * Implementation: File, AssemblyRef, ExportedType
- */
- case MONO_MT_IMPL_IDX:
- n = MAX (meta->tables [MONO_TABLE_FILE].rows,
- meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
- /* 2 bits to encode tag */
- field_size = rtsize (n, 16-2);
- break;
- /*
- * HasFieldMarshall: FieldDef, ParamDef
- */
- case MONO_MT_HFM_IDX:
- n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
- meta->tables [MONO_TABLE_PARAM].rows);
- /* 1 bit used to encode tag */
- field_size = rtsize (n, 16-1);
- break;
- /*
- * MemberForwarded: FieldDef, MethodDef
- */
- case MONO_MT_MF_IDX:
- n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
- meta->tables [MONO_TABLE_METHOD].rows);
- /* 1 bit used to encode tag */
- field_size = rtsize (n, 16-1);
- break;
- /*
- * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
- * LAMESPEC
- * It is TypeDef, _TypeRef_, TypeSpec, instead.
- */
- case MONO_MT_TDOR_IDX:
- n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
- meta->tables [MONO_TABLE_TYPEREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
- /* 2 bits to encode */
- field_size = rtsize (n, 16-2);
- break;
- /*
- * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
- */
- case MONO_MT_MRP_IDX:
- n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
- meta->tables [MONO_TABLE_TYPEREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
- n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
- /* 3 bits to encode */
- field_size = rtsize (n, 16 - 3);
- break;
-
- /*
- * MethodDefOrRef: MethodDef, MemberRef
- */
- case MONO_MT_MDOR_IDX:
- n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
- meta->tables [MONO_TABLE_MEMBERREF].rows);
- /* 1 bit used to encode tag */
- field_size = rtsize (n, 16-1);
- break;
-
- /*
- * HasSemantics: Property, Event
- */
- case MONO_MT_HS_IDX:
- n = MAX (meta->tables [MONO_TABLE_PROPERTY].rows,
- meta->tables [MONO_TABLE_EVENT].rows);
- /* 1 bit used to encode tag */
- field_size = rtsize (n, 16-1);
- break;
- /*
- * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
- */
- case MONO_MT_RS_IDX:
- n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
- meta->tables [MONO_TABLE_MODULEREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
- n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
- /* 2 bits used to encode tag (ECMA spec claims 3) */
- field_size = rtsize (n, 16 - 2);
- break;
- }
- /*
- * encode field size as follows (we just need to
- * distinguish them).
- *
- * 4 -> 3
- * 2 -> 1
- * 1 -> 0
- */
- bitfield |= (field_size-1) << shift;
- shift += 2;
- size += field_size;
- /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
- }
- *result_bitfield = (i << 24) | bitfield;
- return size;
- }
- /**
- * mono_metadata_compute_table_bases:
- * @meta: metadata context to compute table values
- *
- * Computes the table bases for the metadata structure.
- * This is an internal function used by the image loader code.
- */
- void
- mono_metadata_compute_table_bases (MonoImage *meta)
- {
- int i;
- const char *base = meta->tables_base;
-
- for (i = 0; i < MONO_TABLE_NUM; i++) {
- MonoTableInfo *table = &meta->tables [i];
- if (table->rows == 0)
- continue;
- table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
- table->base = base;
- base += table->rows * table->row_size;
- }
- }
- /**
- * mono_metadata_locate:
- * @meta: metadata context
- * @table: table code.
- * @idx: index of element to retrieve from @table.
- *
- * Returns: a pointer to the @idx element in the metadata table
- * whose code is @table.
- */
- const char *
- mono_metadata_locate (MonoImage *meta, int table, int idx)
- {
- /* idx == 0 refers always to NULL */
- g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
-
- return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
- }
- /**
- * mono_metadata_locate_token:
- * @meta: metadata context
- * @token: metadata token
- *
- * Returns: a pointer to the data in the metadata represented by the
- * token #token.
- */
- const char *
- mono_metadata_locate_token (MonoImage *meta, guint32 token)
- {
- return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
- }
- /**
- * mono_metadata_string_heap:
- * @meta: metadata context
- * @index: index into the string heap.
- *
- * Returns: an in-memory pointer to the @index in the string heap.
- */
- const char *
- mono_metadata_string_heap (MonoImage *meta, guint32 index)
- {
- g_assert (index < meta->heap_strings.size);
- g_return_val_if_fail (index < meta->heap_strings.size, "");
- return meta->heap_strings.data + index;
- }
- /**
- * mono_metadata_user_string:
- * @meta: metadata context
- * @index: index into the user string heap.
- *
- * Returns: an in-memory pointer to the @index in the user string heap ("#US").
- */
- const char *
- mono_metadata_user_string (MonoImage *meta, guint32 index)
- {
- g_assert (index < meta->heap_us.size);
- g_return_val_if_fail (index < meta->heap_us.size, "");
- return meta->heap_us.data + index;
- }
- /**
- * mono_metadata_blob_heap:
- * @meta: metadata context
- * @index: index into the blob.
- *
- * Returns: an in-memory pointer to the @index in the Blob heap.
- */
- const char *
- mono_metadata_blob_heap (MonoImage *meta, guint32 index)
- {
- g_assert (index < meta->heap_blob.size);
- g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
- return meta->heap_blob.data + index;
- }
- /**
- * mono_metadata_guid_heap:
- * @meta: metadata context
- * @index: index into the guid heap.
- *
- * Returns: an in-memory pointer to the @index in the guid heap.
- */
- const char *
- mono_metadata_guid_heap (MonoImage *meta, guint32 index)
- {
- --index;
- index *= 16; /* adjust for guid size and 1-based index */
- g_return_val_if_fail (index < meta->heap_guid.size, "");
- return meta->heap_guid.data + index;
- }
- static const unsigned char *
- dword_align (const unsigned char *ptr)
- {
- #if SIZEOF_VOID_P == 8
- return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
- #else
- return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
- #endif
- }
- /**
- * mono_metadata_decode_row:
- * @t: table to extract information from.
- * @idx: index in table.
- * @res: array of @res_size cols to store the results in
- *
- * This decompresses the metadata element @idx in table @t
- * into the guint32 @res array that has res_size elements
- */
- void
- mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
- {
- guint32 bitfield = t->size_bitfield;
- int i, count = mono_metadata_table_count (bitfield);
- const char *data;
- g_assert (idx < t->rows);
- g_assert (idx >= 0);
- data = t->base + idx * t->row_size;
-
- g_assert (res_size == count);
- for (i = 0; i < count; i++) {
- int n = mono_metadata_table_size (bitfield, i);
- switch (n){
- case 1:
- res [i] = *data; break;
- case 2:
- res [i] = read16 (data); break;
- case 4:
- res [i] = read32 (data); break;
- default:
- g_assert_not_reached ();
- }
- data += n;
- }
- }
- /**
- * mono_metadata_decode_row_col:
- * @t: table to extract information from.
- * @idx: index for row in table.
- * @col: column in the row.
- *
- * This function returns the value of column @col from the @idx
- * row in the table @t.
- */
- guint32
- mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
- {
- guint32 bitfield = t->size_bitfield;
- int i;
- register const char *data;
- register int n;
-
- g_assert (idx < t->rows);
- g_assert (col < mono_metadata_table_count (bitfield));
- data = t->base + idx * t->row_size;
- n = mono_metadata_table_size (bitfield, 0);
- for (i = 0; i < col; ++i) {
- data += n;
- n = mono_metadata_table_size (bitfield, i + 1);
- }
- switch (n) {
- case 1:
- return *data;
- case 2:
- return read16 (data);
- case 4:
- return read32 (data);
- default:
- g_assert_not_reached ();
- }
- return 0;
- }
- /**
- * mono_metadata_decode_blob_size:
- * @ptr: pointer to a blob object
- * @rptr: the new position of the pointer
- *
- * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
- *
- * Returns: the size of the blob object
- */
- guint32
- mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
- {
- const unsigned char *ptr = (const unsigned char *)xptr;
- guint32 size;
-
- if ((*ptr & 0x80) == 0){
- size = ptr [0] & 0x7f;
- ptr++;
- } else if ((*ptr & 0x40) == 0){
- size = ((ptr [0] & 0x3f) << 8) + ptr [1];
- ptr += 2;
- } else {
- size = ((ptr [0] & 0x1f) << 24) +
- (ptr [1] << 16) +
- (ptr [2] << 8) +
- ptr [3];
- ptr += 4;
- }
- if (rptr)
- *rptr = (char*)ptr;
- return size;
- }
- /**
- * mono_metadata_decode_value:
- * @ptr: pointer to decode from
- * @rptr: the new position of the pointer
- *
- * This routine decompresses 32-bit values as specified in the "Blob and
- * Signature" section (22.2)
- *
- * Returns: the decoded value
- */
- guint32
- mono_metadata_decode_value (const char *_ptr, const char **rptr)
- {
- const unsigned char *ptr = (const unsigned char *) _ptr;
- unsigned char b = *ptr;
- guint32 len;
-
- if ((b & 0x80) == 0){
- len = b;
- ++ptr;
- } else if ((b & 0x40) == 0){
- len = ((b & 0x3f) << 8 | ptr [1]);
- ptr += 2;
- } else {
- len = ((b & 0x1f) << 24) |
- (ptr [1] << 16) |
- (ptr [2] << 8) |
- ptr [3];
- ptr += 4;
- }
- if (rptr)
- *rptr = (char*)ptr;
-
- return len;
- }
- /**
- * mono_metadata_decode_signed_value:
- * @ptr: pointer to decode from
- * @rptr: the new position of the pointer
- *
- * This routine decompresses 32-bit signed values
- * (not specified in the spec)
- *
- * Returns: the decoded value
- */
- gint32
- mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
- {
- guint32 uval = mono_metadata_decode_value (ptr, rptr);
- gint32 ival = uval >> 1;
- if (!(uval & 1))
- return ival;
- /* ival is a truncated 2's complement negative number. */
- if (ival < 0x40)
- /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
- return ival - 0x40;
- if (ival < 0x2000)
- /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
- return ival - 0x2000;
- if (ival < 0x10000000)
- /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
- return ival - 0x10000000;
- g_assert (ival < 0x20000000);
- g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
- return ival - 0x20000000;
- }
- /*
- * Translates the given 1-based index into the Method, Field, Event, or Param tables
- * using the *Ptr tables in uncompressed metadata, if they are available.
- *
- * FIXME: The caller is not forced to call this function, which is error-prone, since
- * forgetting to call it would only show up as a bug on uncompressed metadata.
- */
- guint32
- mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
- {
- if (!image->uncompressed_metadata)
- return idx;
- switch (table) {
- case MONO_TABLE_METHOD:
- if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
- return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
- else
- return idx;
- case MONO_TABLE_FIELD:
- if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
- return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
- else
- return idx;
- case MONO_TABLE_EVENT:
- if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
- return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
- else
- return idx;
- case MONO_TABLE_PROPERTY:
- if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
- return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
- else
- return idx;
- case MONO_TABLE_PARAM:
- if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
- return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
- else
- return idx;
- default:
- return idx;
- }
- }
- /**
- * mono_metadata_decode_table_row:
- *
- * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
- * uncompressed metadata into account, so it should be used to access the
- * Method, Field, Param and Event tables when the access is made from metadata, i.e.
- * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
- */
- void
- mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
- {
- if (image->uncompressed_metadata)
- idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
- mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
- }
- /**
- * mono_metadata_decode_table_row_col:
- *
- * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
- * uncompressed metadata into account, so it should be used to access the
- * Method, Field, Param and Event tables.
- */
- guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
- {
- if (image->uncompressed_metadata)
- idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
- return mono_metadata_decode_row_col (&image->tables [table], idx, col);
- }
- /*
- * mono_metadata_parse_typedef_or_ref:
- * @m: a metadata context.
- * @ptr: a pointer to an encoded TypedefOrRef in @m
- * @rptr: pointer updated to match the end of the decoded stream
- *
- * Returns: a token valid in the @m metadata decoded from
- * the compressed representation.
- */
- guint32
- mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
- {
- guint32 token;
- token = mono_metadata_decode_value (ptr, &ptr);
- if (rptr)
- *rptr = ptr;
- return mono_metadata_token_from_dor (token);
- }
- /*
- * mono_metadata_parse_custom_mod:
- * @m: a metadata context.
- * @dest: storage where the info about the custom modifier is stored (may be NULL)
- * @ptr: a pointer to (possibly) the start of a custom modifier list
- * @rptr: pointer updated to match the end of the decoded stream
- *
- * Checks if @ptr points to a type custom modifier compressed representation.
- *
- * Returns: #TRUE if a custom modifier was found, #FALSE if not.
- */
- int
- mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
- {
- MonoCustomMod local;
- if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
- if (!dest)
- dest = &local;
- dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
- dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
- return TRUE;
- }
- return FALSE;
- }
- /*
- * mono_metadata_parse_array_internal:
- * @m: a metadata context.
- * @transient: whenever to allocate data from the heap
- * @ptr: a pointer to an encoded array description.
- * @rptr: pointer updated to match the end of the decoded stream
- *
- * Decodes the compressed array description found in the metadata @m at @ptr.
- *
- * Returns: a #MonoArrayType structure describing the array type
- * and dimensions. Memory is allocated from the heap or from the image mempool, depending
- * on the value of @transient.
- *
- * LOCKING: Acquires the loader lock
- */
- static MonoArrayType *
- mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
- gboolean transient, const char *ptr, const char **rptr)
- {
- int i;
- MonoArrayType *array;
- MonoType *etype;
-
- array = transient ? g_malloc0 (sizeof (MonoArrayType)) : mono_image_alloc0 (m, sizeof (MonoArrayType));
- etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
- if (!etype)
- return NULL;
- array->eklass = mono_class_from_mono_type (etype);
- array->rank = mono_metadata_decode_value (ptr, &ptr);
- array->numsizes = mono_metadata_decode_value (ptr, &ptr);
- if (array->numsizes)
- array->sizes = transient ? g_malloc0 (sizeof (int) * array->numsizes) : mono_image_alloc0 (m, sizeof (int) * array->numsizes);
- for (i = 0; i < array->numsizes; ++i)
- array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
- array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
- if (array->numlobounds)
- array->lobounds = transient ? g_malloc0 (sizeof (int) * array->numlobounds) : mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
- for (i = 0; i < array->numlobounds; ++i)
- array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
- if (rptr)
- *rptr = ptr;
- return array;
- }
- MonoArrayType *
- mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
- const char *ptr, const char **rptr)
- {
- return mono_metadata_parse_array_internal (m, container, FALSE, ptr, rptr);
- }
- MonoArrayType *
- mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
- {
- return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
- }
- /*
- * mono_metadata_free_array:
- * @array: array description
- *
- * Frees the array description returned from mono_metadata_parse_array().
- */
- void
- mono_metadata_free_array (MonoArrayType *array)
- {
- g_free (array->sizes);
- g_free (array->lobounds);
- g_free (array);
- }
- /*
- * need to add common field and param attributes combinations:
- * [out] param
- * public static
- * public static literal
- * private
- * private static
- * private static literal
- */
- static const MonoType
- builtin_types[] = {
- /* data, attrs, type, nmods, byref, pinned */
- {{NULL}, 0, MONO_TYPE_VOID, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_CHAR, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_CHAR, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_I1, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_I1, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_U1, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_U1, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_I2, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_I2, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_U2, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_U2, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_I4, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_I4, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_U4, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_U4, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_I8, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_I8, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_U8, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_U8, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_R4, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_R4, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_R8, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_R8, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_STRING, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_STRING, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_OBJECT, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_OBJECT, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_TYPEDBYREF, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_I, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_I, 0, 1, 0},
- {{NULL}, 0, MONO_TYPE_U, 0, 0, 0},
- {{NULL}, 0, MONO_TYPE_U, 0, 1, 0},
- };
- #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
- static GHashTable *type_cache = NULL;
- static int next_generic_inst_id = 0;
- static MonoImageSet *mscorlib_image_set;
- static GPtrArray *image_sets;
- static guint mono_generic_class_hash (gconstpointer data);
- /*
- * MonoTypes with modifies are never cached, so we never check or use that field.
- */
- static guint
- mono_type_hash (gconstpointer data)
- {
- const MonoType *type = (const MonoType *) data;
- if (type->type == MONO_TYPE_GENERICINST)
- return mono_generic_class_hash (type->data.generic_class);
- else
- return type->type | (type->byref << 8) | (type->attrs << 9);
- }
- static gint
- mono_type_equal (gconstpointer ka, gconstpointer kb)
- {
- const MonoType *a = (const MonoType *) ka;
- const MonoType *b = (const MonoType *) kb;
-
- if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
- return 0;
- /* need other checks */
- return 1;
- }
- guint
- mono_metadata_generic_inst_hash (gconstpointer data)
- {
- const MonoGenericInst *ginst = (const MonoGenericInst *) data;
- guint hash = 0;
- int i;
-
- for (i = 0; i < ginst->type_argc; ++i) {
- hash *= 13;
- hash += mono_metadata_type_hash (ginst->type_argv [i]);
- }
- return hash ^ (ginst->is_open << 8);
- }
- static gboolean
- mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
- {
- int i;
- #ifndef MONO_SMALL_CONFIG
- if (a->id && b->id) {
- if (a->id == b->id)
- return TRUE;
- if (!signature_only)
- return FALSE;
- }
- #endif
- if (a->is_open != b->is_open || a->type_argc != b->type_argc)
- return FALSE;
- for (i = 0; i < a->type_argc; ++i) {
- if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
- return FALSE;
- }
- return TRUE;
- }
- gboolean
- mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
- {
- const MonoGenericInst *a = (const MonoGenericInst *) ka;
- const MonoGenericInst *b = (const MonoGenericInst *) kb;
- return mono_generic_inst_equal_full (a, b, FALSE);
- }
- static guint
- mono_generic_class_hash (gconstpointer data)
- {
- const MonoGenericClass *gclass = (const MonoGenericClass *) data;
- guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
- hash *= 13;
- hash += gclass->is_tb_open;
- hash += mono_metadata_generic_context_hash (&gclass->context);
- return hash;
- }
- static gboolean
- mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
- {
- const MonoGenericClass *a = (const MonoGenericClass *) ka;
- const MonoGenericClass *b = (const MonoGenericClass *) kb;
- return _mono_metadata_generic_class_equal (a, b, FALSE);
- }
- /**
- * mono_metadata_init:
- *
- * Initialize the global variables of this module.
- * This is a Mono runtime internal function.
- */
- void
- mono_metadata_init (void)
- {
- int i;
- type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
- for (i = 0; i < NBUILTIN_TYPES (); ++i)
- g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
- }
- /**
- * mono_metadata_cleanup:
- *
- * Free all resources used by this module.
- * This is a Mono runtime internal function.
- */
- void
- mono_metadata_cleanup (void)
- {
- g_hash_table_destroy (type_cache);
- type_cache = NULL;
- g_ptr_array_free (image_sets, TRUE);
- image_sets = NULL;
- }
- /**
- * mono_metadata_parse_type:
- * @m: metadata context
- * @mode: king of type that may be found at @ptr
- * @opt_attrs: optional attributes to store in the returned type
- * @ptr: pointer to the type representation
- * @rptr: pointer updated to match the end of the decoded stream
- * @transient: whenever to allocate the result from the heap or from a mempool
- *
- * Decode a compressed type description found at @ptr in @m.
- * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
- * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
- * This function can be used to decode type descriptions in method signatures,
- * field signatures, locals signatures etc.
- *
- * To parse a generic type, `generic_container' points to the current class'es
- * (the `generic_container' field in the MonoClass) or the current generic method's
- * (stored in image->property_hash) generic container.
- * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
- * this MonoGenericContainer.
- *
- * LOCKING: Acquires the loader lock.
- *
- * Returns: a #MonoType structure representing the decoded type.
- */
- static MonoType*
- mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
- short opt_attrs, gboolean transient, const char *ptr, const char **rptr)
- {
- MonoType *type, *cached;
- MonoType stype;
- gboolean byref = FALSE;
- gboolean pinned = FALSE;
- const char *tmp_ptr;
- int count = 0;
- gboolean found;
- /*
- * According to the spec, custom modifiers should come before the byref
- * flag, but the IL produced by ilasm from the following signature:
- * object modopt(...) &
- * starts with a byref flag, followed by the modifiers. (bug #49802)
- * Also, this type seems to be different from 'object & modopt(...)'. Maybe
- * it would be better to treat byref as real type constructor instead of
- * a modifier...
- * Also, pinned should come before anything else, but some MSV++ produced
- * assemblies violate this (#bug 61990).
- */
- /* Count the modifiers first */
- tmp_ptr = ptr;
- found = TRUE;
- while (found) {
- switch (*tmp_ptr) {
- case MONO_TYPE_PINNED:
- case MONO_TYPE_BYREF:
- ++tmp_ptr;
- break;
- case MONO_TYPE_CMOD_REQD:
- case MONO_TYPE_CMOD_OPT:
- count ++;
- mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
- break;
- default:
- found = FALSE;
- }
- }
- if (count) {
- int size;
- size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
- type = transient ? g_malloc0 (size) : mono_image_alloc0 (m, size);
- type->num_mods = count;
- if (count > 64)
- g_warning ("got more than 64 modifiers in type");
- } else {
- type = &stype;
- memset (type, 0, MONO_SIZEOF_TYPE);
- }
- /* Parse pinned, byref and custom modifiers */
- found = TRUE;
- count = 0;
- while (found) {
- switch (*ptr) {
- case MONO_TYPE_PINNED:
- pinned = TRUE;
- ++ptr;
- break;
- case MONO_TYPE_BYREF:
- byref = TRUE;
- ++ptr;
- break;
- case MONO_TYPE_CMOD_REQD:
- case MONO_TYPE_CMOD_OPT:
- mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
- count ++;
- break;
- default:
- found = FALSE;
- }
- }
-
- type->attrs = opt_attrs;
- type->byref = byref;
- type->pinned = pinned ? 1 : 0;
- if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr)) {
- return NULL;
- }
- if (rptr)
- *rptr = ptr;
- if (!type->num_mods && !transient) {
- /* no need to free type here, because it is on the stack */
- if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
- MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
- /* Consider the case:
- class Foo<T> { class Bar {} }
- class Test : Foo<Test>.Bar {}
- When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
- a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
- We ensure that the MonoClass is in a state that we can canonicalize to:
- klass->byval_arg.data.klass == klass
- klass->this_arg.data.klass == klass
- If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
- LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
- of a MonoClass which currently holds the loader lock. 'type' is local.
- */
- if (ret->data.klass == type->data.klass) {
- return ret;
- }
- }
- /* No need to use locking since nobody is modifying the hash table */
- if ((cached = g_hash_table_lookup (type_cache, type))) {
- return cached;
- }
- }
-
- /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
-
- if (type == &stype) {
- type = transient ? g_malloc (MONO_SIZEOF_TYPE) : mono_image_alloc (m, MONO_SIZEOF_TYPE);
- memcpy (type, &stype, MONO_SIZEOF_TYPE);
- }
- return type;
- }
- MonoType*
- mono_metadata_parse_type_full (Mo…
Large files files are truncated, but you can click here to view the full file