X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Freflection.c;h=d7c958f1bd2442d782558548316f59bfe94b7882;hb=0f128ab73f1d67e6847eed513038b338fe780099;hp=e02ea46253f278ff8167bf82f6fde417fd23bbe9;hpb=55406d467f7f4f92f7a80c54bb67e6a0856daff9;p=mono.git diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index e02ea46253f..d7c958f1bd2 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -1,4 +1,3 @@ - /* * reflection.c: Routines for creating an image at runtime. * @@ -50,7 +49,14 @@ typedef struct { MonoObject *type; MonoString *name; MonoBoolean init_locals; + MonoArray *return_modreq; + MonoArray *return_modopt; + MonoArray *param_modreq; + MonoArray *param_modopt; + MonoArray *permissions; MonoMethod *mhandle; + guint32 nrefs; + gpointer *refs; } ReflectionMethodBuilder; const unsigned char table_sizes [64] = { @@ -130,6 +136,10 @@ static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gp static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo); static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass); static void ensure_runtime_vtable (MonoClass *klass); +static gpointer resolve_object (MonoImage *image, MonoObject *obj); +static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf); +static guint32 type_get_signature_size (MonoType *type); + static void alloc_table (MonoDynamicTable *table, guint nrows) @@ -300,6 +310,75 @@ add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int return idx; } +/* + * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary. + * dest may be misaligned. + */ +static void +swap_with_size (char *dest, const char* val, int len, int nelem) { +#if G_BYTE_ORDER != G_LITTLE_ENDIAN + int elem; + + for (elem = 0; elem < nelem; ++elem) { + switch (len) { + case 1: + *dest = *val; + break; + case 2: + dest [0] = val [1]; + dest [1] = val [0]; + break; + case 4: + dest [0] = val [3]; + dest [1] = val [2]; + dest [2] = val [1]; + dest [3] = val [0]; + break; + case 8: + dest [0] = val [7]; + dest [1] = val [6]; + dest [2] = val [5]; + dest [3] = val [4]; + dest [4] = val [3]; + dest [5] = val [2]; + dest [6] = val [1]; + dest [7] = val [0]; + break; + default: + g_assert_not_reached (); + } + dest += len; + val += len; + } +#else + memcpy (dest, val, len * nelem); +#endif +} + +static guint32 +add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str) +{ + char blob_size [64]; + char *b = blob_size; + guint32 idx = 0, len; + + len = str->length * 2; + mono_metadata_encode_value (len, b, &b); +#if G_BYTE_ORDER != G_LITTLE_ENDIAN + { + char *swapped = g_malloc (2 * mono_string_length (str)); + const char *p = (const char*)mono_string_chars (str); + + swap_with_size (swapped, p, 2, mono_string_length (str)); + idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len); + g_free (swapped); + } +#else + idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len); +#endif + return idx; +} + /* modified version needed to handle building corlib */ static MonoClass* my_mono_class_from_mono_type (MonoType *type) { @@ -319,6 +398,25 @@ my_mono_class_from_mono_type (MonoType *type) { } } +static void +encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf) +{ + int i; + + if (!ginst) { + g_assert_not_reached (); + return; + } + + mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p); + encode_type (assembly, ginst->generic_type, p, &p); + mono_metadata_encode_value (ginst->type_argc, p, &p); + for (i = 0; i < ginst->type_argc; ++i) + encode_type (assembly, ginst->type_argv [i], p, &p); + + *endbuf = p; +} + static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf) { @@ -380,16 +478,9 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf) mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */ mono_metadata_encode_value (0, p, &p); break; - case MONO_TYPE_GENERICINST: { - int i; - mono_metadata_encode_value (type->type, p, &p); - encode_type (assembly, type->data.generic_inst->generic_type, p, &p); - mono_metadata_encode_value (type->data.generic_inst->type_argc, p, &p); - for (i = 0; i < type->data.generic_inst->type_argc; ++i) { - encode_type (assembly, type->data.generic_inst->type_argv [i], p, &p); - } + case MONO_TYPE_GENERICINST: + encode_generic_inst (assembly, type->data.generic_inst, p, &p); break; - } case MONO_TYPE_VAR: case MONO_TYPE_MVAR: mono_metadata_encode_value (type->type, p, &p); @@ -418,6 +509,119 @@ encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, ch } +static void +encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf) +{ + int i; + + if (modreq) { + for (i = 0; i < mono_array_length (modreq); ++i) { + MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i); + *p = MONO_TYPE_CMOD_REQD; + p++; + mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p); + } + } + if (modopt) { + for (i = 0; i < mono_array_length (modopt); ++i) { + MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i); + *p = MONO_TYPE_CMOD_OPT; + p++; + mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p); + } + } + *endbuf = p; +} + +static guint32 +generic_inst_get_signature_size (MonoGenericInst *ginst) +{ + guint32 size = 0; + int i; + + if (!ginst) { + g_assert_not_reached (); + } + + size += 1 + type_get_signature_size (ginst->generic_type); + size += 4; + for (i = 0; i < ginst->type_argc; ++i) + size += type_get_signature_size (ginst->type_argv [i]); + + return size; +} + +static guint32 +type_get_signature_size (MonoType *type) +{ + guint32 size = 0; + + if (!type) { + g_assert_not_reached (); + } + + if (type->byref) + size++; + + switch (type->type){ + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_STRING: + case MONO_TYPE_OBJECT: + case MONO_TYPE_TYPEDBYREF: + return size + 1; + case MONO_TYPE_PTR: + return size + 1 + type_get_signature_size (type->data.type); + case MONO_TYPE_SZARRAY: + return size + 1 + type_get_signature_size (&type->data.klass->byval_arg); + + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_CLASS: + return size + 5; + + case MONO_TYPE_ARRAY: + return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg); + case MONO_TYPE_GENERICINST: + return size + generic_inst_get_signature_size (type->data.generic_inst); + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + return size + 5; + + default: + g_error ("need to encode type %x", type->type); + return size; + } +} + +static guint32 +method_get_signature_size (MonoMethodSignature *sig) +{ + guint32 size; + int i; + + size = type_get_signature_size (sig->ret); + for (i = 0; i < sig->param_count; i++) + size += type_get_signature_size (sig->params [i]); + + if (sig->generic_param_count) + size += 4; + + return size; +} + static guint32 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig) { @@ -425,7 +629,7 @@ method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig) char *p; int i; guint32 nparams = sig->param_count; - guint32 size = 10 + nparams * 10; + guint32 size = 11 + method_get_signature_size (sig); guint32 idx; char blob_size [6]; char *b = blob_size; @@ -468,7 +672,7 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui int i; guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0; guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0; - guint32 size = 11 + nparams * 10; + guint32 size = 21 + nparams * 20; guint32 idx; char blob_size [6]; char *b = blob_size; @@ -486,9 +690,19 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui if (ngparams) mono_metadata_encode_value (ngparams, p, &p); mono_metadata_encode_value (nparams, p, &p); + encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p); encode_reflection_type (assembly, mb->rtype, p, &p); for (i = 0; i < nparams; ++i) { - MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i); + MonoArray *modreq = NULL; + MonoArray *modopt = NULL; + MonoReflectionType *pt; + + if (mb->param_modreq && (i < mono_array_length (mb->param_modreq))) + modreq = mono_array_get (mb->param_modreq, MonoArray*, i); + if (mb->param_modopt && (i < mono_array_length (mb->param_modopt))) + modopt = mono_array_get (mb->param_modopt, MonoArray*, i); + encode_custom_modifiers (assembly, modreq, modopt, p, &p); + pt = mono_array_get (mb->parameters, MonoReflectionType*, i); encode_reflection_type (assembly, pt, p, &p); } /* store length */ @@ -524,6 +738,10 @@ encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen) mono_metadata_encode_value (nl, p, &p); for (i = 0; i < nl; ++i) { MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i); + + if (lb->is_pinned) + mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p); + encode_reflection_type (assembly, lb->type, p, &p); } g_assert (p - buf < size); @@ -636,8 +854,14 @@ method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb) num_exception = method_count_clauses (mb->ilgen); } else { code = mb->code; - if (code == NULL) - mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated")); + if (code == NULL){ + char *name = mono_string_to_utf8 (mb->name); + char *str = g_strdup_printf ("Method %s does not have any IL associated", name); + MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated"); + g_free (str); + g_free (name); + mono_raise_exception (exception); + } code_size = mono_array_length (code); max_stack = 8; /* we probably need to run a verifier on the code... */ @@ -859,6 +1083,52 @@ mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, Mo } } +static void +mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, + MonoArray *permissions) +{ + MonoDynamicTable *table; + guint32 *values; + guint32 count, i, idx; + MonoReflectionPermissionSet *perm; + + if (!permissions) + return; + + count = mono_array_length (permissions); + table = &assembly->tables [MONO_TABLE_DECLSECURITY]; + table->rows += count; + alloc_table (table, table->rows); + + for (i = 0; i < mono_array_length (permissions); ++i) { + perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i); + + values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE; + + idx = mono_metadata_token_index (parent_token); + idx <<= HAS_DECL_SECURITY_BITS; + switch (mono_metadata_token_table (parent_token)) { + case MONO_TABLE_TYPEDEF: + idx |= HAS_DECL_SECURITY_TYPEDEF; + break; + case MONO_TABLE_METHOD: + idx |= HAS_DECL_SECURITY_METHODDEF; + break; + case MONO_TABLE_ASSEMBLY: + idx |= HAS_DECL_SECURITY_ASSEMBLY; + break; + default: + g_assert_not_reached (); + } + + values [MONO_DECL_SECURITY_ACTION] = perm->action; + values [MONO_DECL_SECURITY_PARENT] = idx; + values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset); + + ++table->next_idx; + } +} + /* * Fill in the MethodDef and ParamDef tables for a method. * This is used for both normal methods and constructors. @@ -887,6 +1157,10 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly table = &assembly->tables [MONO_TABLE_PARAM]; values [MONO_METHOD_PARAMLIST] = table->next_idx; + mono_image_add_decl_security (assembly, + mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), + mb->permissions); + if (mb->pinfo) { MonoDynamicTable *mtable; guint32 *mvalues; @@ -945,7 +1219,14 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, rmb->name = mb->name; rmb->table_idx = &mb->table_idx; rmb->init_locals = mb->init_locals; + rmb->return_modreq = mb->return_modreq; + rmb->return_modopt = mb->return_modopt; + rmb->param_modreq = mb->param_modreq; + rmb->param_modopt = mb->param_modopt; + rmb->permissions = mb->permissions; rmb->mhandle = mb->mhandle; + rmb->nrefs = 0; + rmb->refs = NULL; } static void @@ -967,9 +1248,43 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, rmb->name = mono_string_new (mono_domain_get (), name); rmb->table_idx = &mb->table_idx; rmb->init_locals = mb->init_locals; + rmb->return_modreq = NULL; + rmb->return_modopt = NULL; + rmb->param_modreq = mb->param_modreq; + rmb->param_modopt = mb->param_modopt; + rmb->permissions = mb->permissions; rmb->mhandle = mb->mhandle; + rmb->nrefs = 0; + rmb->refs = NULL; } +static void +reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, + MonoReflectionDynamicMethod *mb) +{ + rmb->ilgen = mb->ilgen; + rmb->rtype = mb->rtype; + rmb->parameters = mb->parameters; + rmb->generic_params = NULL; + rmb->pinfo = NULL; + rmb->attrs = mb->attrs; + rmb->iattrs = 0; + rmb->call_conv = mb->call_conv; + rmb->code = NULL; + rmb->type = NULL; + rmb->name = mb->name; + rmb->table_idx = NULL; + rmb->init_locals = mb->init_locals; + rmb->return_modreq = NULL; + rmb->return_modopt = NULL; + rmb->param_modreq = NULL; + rmb->param_modopt = NULL; + rmb->permissions = NULL; + rmb->mhandle = mb->mhandle; + rmb->nrefs = 0; + rmb->refs = NULL; +} + static void mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly) { @@ -1057,6 +1372,38 @@ mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, Mon mono_image_basic_method (&rmb, assembly); } +static char* +type_get_fully_qualified_name (MonoType *type) { + char *name, *result; + MonoClass *klass; + MonoAssembly *ta; + + name = mono_type_get_name (type); + klass = my_mono_class_from_mono_type (type); + ta = klass->image->assembly; + + result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s", + name, ta->aname.name, + ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision, + ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral", + ta->aname.public_tok_value ? ta->aname.public_tok_value : "null"); + g_free (name); + return result; +} + +static char* +type_get_qualified_name (MonoType *type, MonoAssembly *ass) { + MonoClass *klass; + MonoAssembly *ta; + + klass = my_mono_class_from_mono_type (type); + ta = klass->image->assembly; + if (ta == ass || klass->image == mono_defaults.corlib) + return mono_type_get_name (type); + + return type_get_fully_qualified_name (type); +} + static guint32 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type) { @@ -1093,6 +1440,7 @@ field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder * p = buf = g_malloc (64); mono_metadata_encode_value (0x06, p, &p); + encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p); /* encode custom attributes before the type */ encode_reflection_type (assembly, fb->type, p, &p); g_assert (p-buf < 64); @@ -1102,58 +1450,13 @@ field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder * return idx; } -/* - * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary. - * dest may be misaligned. - */ -static void -swap_with_size (char *dest, const char* val, int len, int nelem) { -#if G_BYTE_ORDER != G_LITTLE_ENDIAN - int elem; - - for (elem = 0; elem < nelem; ++elem) { - switch (len) { - case 1: - *dest = *val; - break; - case 2: - dest [0] = val [1]; - dest [1] = val [0]; - break; - case 4: - dest [0] = val [3]; - dest [1] = val [2]; - dest [2] = val [1]; - dest [3] = val [0]; - break; - case 8: - dest [0] = val [7]; - dest [1] = val [6]; - dest [2] = val [5]; - dest [3] = val [4]; - dest [4] = val [3]; - dest [5] = val [2]; - dest [6] = val [1]; - dest [7] = val [0]; - break; - default: - g_assert_not_reached (); - } - dest += len; - val += len; - } -#else - memcpy (dest, val, len * nelem); -#endif -} - static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) { char blob_size [64]; char *b = blob_size; char *p, *box_val; char* buf; - guint32 idx, len, dummy = 0; + guint32 idx = 0, len = 0, dummy = 0; p = buf = g_malloc (64); if (!val) { @@ -1248,7 +1551,16 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) { mono_metadata_encode_value (minfo->type, p, &p); mono_metadata_encode_value (minfo->count, p, &p); break; - /* FIXME: handle ARRAY and other unmanaged types that need extra info */ + case MONO_NATIVE_LPARRAY: + mono_metadata_encode_value (minfo->type, p, &p); + if (minfo->eltype || (minfo->count > 0)) { + mono_metadata_encode_value (minfo->eltype, p, &p); + if (minfo->count > 0) { + mono_metadata_encode_value (0, p, &p); + mono_metadata_encode_value (minfo->count, p, &p); + } + } + break; case MONO_NATIVE_CUSTOM: mono_metadata_encode_value (minfo->type, p, &p); if (minfo->guid) { @@ -1278,7 +1590,7 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) { mono_metadata_encode_value (0, p, &p); } if (minfo->marshaltyperef) { - str = type_get_qualified_name (minfo->marshaltyperef->type, assembly->image.assembly); + str = type_get_fully_qualified_name (minfo->marshaltyperef->type); len = strlen (str); mono_metadata_encode_value (len, p, &p); if (p + len >= buf + bufsize) { @@ -1360,7 +1672,7 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass values [MONO_CONSTANT_TYPE] = field_type; values [MONO_CONSTANT_PADDING] = 0; } - if (fb->rva_data) { + if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) { guint32 rva_idx; table = &assembly->tables [MONO_TABLE_FIELDRVA]; table->rows ++; @@ -1370,7 +1682,10 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass /* * We store it in the code section because it's simpler for now. */ - rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data)); + if (fb->rva_data) + rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data)); + else + rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL)); values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva; } if (fb->marshal_info) { @@ -1533,6 +1848,75 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *ass } } +static void +encode_new_constraint (MonoDynamicImage *assembly, guint32 owner) +{ + static MonoClass *NewConstraintAttr; + static MonoMethod *NewConstraintAttr_ctor; + MonoDynamicTable *table; + guint32 *values; + guint32 token, type; + char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 }; + char *buf, *p; + + if (!NewConstraintAttr) + NewConstraintAttr = mono_class_from_name ( + mono_defaults.corlib, "System.Runtime.CompilerServices", + "NewConstraintAttribute"); + g_assert (NewConstraintAttr); + + if (!NewConstraintAttr_ctor) { + int i; + + for (i = 0; i < NewConstraintAttr->method.count; i++) { + MonoMethod *m = NewConstraintAttr->methods [i]; + + if (strcmp (m->name, ".ctor")) + continue; + + NewConstraintAttr_ctor = m; + break; + } + + g_assert (NewConstraintAttr_ctor); + } + + table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE]; + table->rows += 1; + alloc_table (table, table->rows); + + values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE; + owner <<= CUSTOM_ATTR_BITS; + owner |= CUSTOM_ATTR_GENERICPAR; + values [MONO_CUSTOM_ATTR_PARENT] = owner; + + token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor); + + type = mono_metadata_token_index (token); + type <<= CUSTOM_ATTR_TYPE_BITS; + switch (mono_metadata_token_table (token)) { + case MONO_TABLE_METHOD: + type |= CUSTOM_ATTR_TYPE_METHODDEF; + break; + case MONO_TABLE_MEMBERREF: + type |= CUSTOM_ATTR_TYPE_MEMBERREF; + break; + default: + g_warning ("got wrong token in custom attr"); + return; + } + values [MONO_CUSTOM_ATTR_TYPE] = type; + + buf = p = g_malloc (1); + mono_metadata_encode_value (4, p, &p); + g_assert (p-buf == 1); + + values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4); + + values += MONO_CUSTOM_ATTR_SIZE; + ++table->next_idx; +} + static void encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly) { @@ -1542,25 +1926,43 @@ encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynam guint32 table_idx; table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT]; - num_constraints = gparam ? mono_array_length (gparam->constraints) : 0; + num_constraints = gparam->iface_constraints ? + mono_array_length (gparam->iface_constraints) : 0; table->rows += num_constraints; + if (gparam->base_type) + table->rows++; alloc_table (table, table->rows); + if (gparam->base_type) { + table_idx = table->next_idx ++; + values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE; + + values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner; + values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref ( + assembly, gparam->base_type->type); + } + for (i = 0; i < num_constraints; i++) { - MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i); + MonoReflectionType *constraint = mono_array_get ( + gparam->iface_constraints, gpointer, i); table_idx = table->next_idx ++; values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE; values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner; - values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type); + values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref ( + assembly, constraint->type); } + + if (gparam->has_ctor_constraint) + encode_new_constraint (assembly, owner); } static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly) { MonoDynamicTable *table; + MonoGenericParam *param; guint32 *values; guint32 table_idx; @@ -1568,15 +1970,20 @@ mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 o table_idx = table->next_idx ++; values = table->values + table_idx * MONO_GENERICPARAM_SIZE; + param = gparam->type.type->data.generic_param; + values [MONO_GENERICPARAM_OWNER] = owner; - values [MONO_GENERICPARAM_FLAGS] = gparam->param->flags; - values [MONO_GENERICPARAM_NUMBER] = gparam->param->num; - values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, gparam->param->name); + if (gparam->has_value_type) + values [MONO_GENERICPARAM_FLAGS] = 0x18; + else if (gparam->has_reference_type) + values [MONO_GENERICPARAM_FLAGS] = 0x04; + else + values [MONO_GENERICPARAM_FLAGS] = 0x00; + values [MONO_GENERICPARAM_NUMBER] = param->num; + values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name); values [MONO_GENERICPARAM_KIND] = 0; - values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0; - if (gparam->constraints) - encode_constraints (gparam, table_idx, assembly); + encode_constraints (gparam, table_idx, assembly); } static guint32 @@ -1621,10 +2028,7 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image) table->rows ++; alloc_table (table, table->rows); values = table->values + token * MONO_ASSEMBLYREF_SIZE; - if (strcmp ("corlib", image->assembly_name) == 0) - values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib"); - else - values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name); + values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name); values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION]; values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION]; values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER]; @@ -1633,6 +2037,11 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image) values [MONO_ASSEMBLYREF_CULTURE] = 0; values [MONO_ASSEMBLYREF_HASH_VALUE] = 0; + if (strcmp ("", image->assembly->aname.culture)) { + values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap, + image->assembly->aname.culture); + } + if ((pubkey = mono_image_get_public_key (image, &publen))) { guchar pubtoken [9]; pubtoken [0] = 8; @@ -1647,8 +2056,7 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image) * recognized by ms, yuck! * FIXME: need to add more assembly names, as needed. */ - if (strcmp (image->assembly_name, "corlib") == 0 || - strcmp (image->assembly_name, "mscorlib") == 0 || + if (strcmp (image->assembly_name, "mscorlib") == 0 || strcmp (image->assembly_name, "System") == 0 || strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 || strcmp (image->assembly_name, "System.Xml") == 0 || @@ -1720,7 +2128,7 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type) MonoClass *k = mono_class_from_mono_type (type); if (!k || !k->generic_inst) return 0; - encode_type (assembly, k->generic_inst, p, &p); + encode_generic_inst (assembly, k->generic_inst, p, &p); break; } default: @@ -1871,7 +2279,6 @@ mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMe return token; reflection_methodbuilder_from_method_builder (&rmb, mb); - token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type, mono_string_to_utf8 (rmb.name), @@ -1900,55 +2307,29 @@ mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtor } static guint32 -mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field, MonoClass *klass) +mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f) { + MonoType *type; guint32 token; - - token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field)); - if (token) - return token; - field->parent = klass; - token = mono_image_get_memberref_token (assembly, &klass->byval_arg, - field->name, fieldref_encode_signature (assembly, field->type)); - g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token)); - return token; -} - -static guint32 -field_encode_inflated_field (MonoDynamicImage *assembly, MonoReflectionInflatedField *field) -{ - guint32 sig, token; - MonoClass *klass; - const gchar *name; - - klass = field->rfield.klass; - name = field->rfield.field->name; - sig = fieldref_encode_signature (assembly, field->declaring->type); - token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig); - return token; -} - -static guint32 -mono_image_get_inflated_field_token (MonoDynamicImage *assembly, MonoReflectionInflatedField *field) -{ - guint32 token; - - token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field->rfield.field)); + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f)); if (token) return token; - token = field_encode_inflated_field (assembly, field); - g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token)); + g_assert (f->field->parent); + type = f->field->generic_type ? f->field->generic_type : f->field->type; + token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg, + f->field->name, fieldref_encode_signature (assembly, type)); + g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token)); return token; } static guint32 -encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst) +encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod) { char *buf; char *p; int i; - guint32 nparams = ginst->type_argc; + guint32 nparams = gmethod->mtype_argc; guint32 size = 10 + nparams * 10; guint32 idx; char blob_size [6]; @@ -1965,7 +2346,7 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst) mono_metadata_encode_value (nparams, p, &p); for (i = 0; i < nparams; i++) - encode_type (assembly, ginst->type_argv [i], p, &p); + encode_type (assembly, gmethod->mtype_argv [i], p, &p); /* store length */ g_assert (p - buf < size); @@ -1976,27 +2357,26 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst) } static guint32 -method_encode_methodspec (MonoDynamicImage *assembly, MonoGenericInst *ginst) +method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method) { MonoDynamicTable *table; guint32 *values; - guint32 token, mtoken, sig; + guint32 token, mtoken = 0, sig; + MonoMethodInflated *imethod; + MonoMethod *declaring; table = &assembly->tables [MONO_TABLE_METHODSPEC]; - g_assert (ginst); - if (ginst->generic_method) { - MonoMethod *gm = ginst->generic_method; - MonoClass *k = ginst->klass ? ginst->klass : gm->klass; + g_assert (method->signature->is_inflated); + imethod = (MonoMethodInflated *) method; + declaring = imethod->declaring; - sig = method_encode_signature (assembly, gm->signature); - mtoken = mono_image_get_memberref_token (assembly, &k->byval_arg, gm->name, sig); + sig = method_encode_signature (assembly, declaring->signature); + mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, + declaring->name, sig); - if (!ginst->generic_method->signature->generic_param_count) - return mtoken; - } - else - g_assert_not_reached (); + if (!declaring->signature->generic_param_count) + return mtoken; switch (mono_metadata_token_table (mtoken)) { case MONO_TABLE_MEMBERREF: @@ -2009,7 +2389,7 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoGenericInst *ginst) g_assert_not_reached (); } - sig = encode_generic_method_sig (assembly, ginst); + sig = encode_generic_method_sig (assembly, imethod->context->gmethod); if (assembly->save) { alloc_table (table, table->rows + 1); @@ -2025,15 +2405,28 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoGenericInst *ginst) } static guint32 -mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method, MonoGenericInst *ginst) +mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m) { + MonoMethodInflated *imethod; guint32 token; - token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method)); + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m)); if (token) return token; - token = method_encode_methodspec (assembly, ginst); - g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token)); + + g_assert (m->signature->is_inflated); + imethod = (MonoMethodInflated *) m; + + if (imethod->declaring->signature->generic_param_count) + token = method_encode_methodspec (assembly, m); + else { + guint32 sig = method_encode_signature ( + assembly, imethod->declaring->signature); + token = mono_image_get_memberref_token ( + assembly, &m->klass->byval_arg, m->name, sig); + } + + g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token)); return token; } @@ -2050,6 +2443,16 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder * char *b = blob_size; int count, i; + /* + * We're creating a TypeSpec for the TypeBuilder of a generic type declaration, + * ie. what we'd normally use as the generic type in a TypeSpec signature. + * Because of this, we must not insert it into the `typeref' hash table. + */ + + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type)); + if (token) + return token; + g_assert (tb->generic_params); klass = mono_class_from_mono_type (tb->type.type); @@ -2060,14 +2463,10 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder * mono_metadata_encode_value (count, p, &p); for (i = 0; i < count; i++) { MonoReflectionGenericParam *gparam; - MonoType t; gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i); - t.type = MONO_TYPE_VAR; - t.data.generic_param = gparam->param; - - encode_type (assembly, &t, p, &p); + encode_type (assembly, gparam->type.type, p, &p); } table = &assembly->tables [MONO_TABLE_TYPESPEC]; @@ -2081,7 +2480,7 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder * } token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS); - g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token)); + g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token)); table->next_idx ++; return token; } @@ -2095,6 +2494,10 @@ mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFi guint32 token, pclass, parent, sig; gchar *name; + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb)); + if (token) + return token; + klass = mono_class_from_mono_type (fb->typeb->type); name = mono_string_to_utf8 (fb->name); @@ -2118,7 +2521,7 @@ mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFi token = MONO_TOKEN_MEMBER_REF | table->next_idx; table->next_idx ++; - + g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token)); return token; } @@ -2340,9 +2743,9 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon /* handle fields */ if (tb->fields) { table = &assembly->tables [MONO_TABLE_FIELD]; - table->rows += mono_array_length (tb->fields); + table->rows += tb->num_fields; alloc_table (table, table->rows); - for (i = 0; i < mono_array_length (tb->fields); ++i) + for (i = 0; i < tb->num_fields; ++i) mono_image_get_field_info ( mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly); } @@ -2360,9 +2763,9 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon /* handle methods */ if (tb->methods) { table = &assembly->tables [MONO_TABLE_METHOD]; - table->rows += mono_array_length (tb->methods); + table->rows += tb->num_methods; alloc_table (table, table->rows); - for (i = 0; i < mono_array_length (tb->methods); ++i) + for (i = 0; i < tb->num_methods; ++i) mono_image_get_method_info ( mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly); } @@ -2396,6 +2799,11 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon mono_image_get_property_info ( mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly); } + + mono_image_add_decl_security (assembly, + mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), + tb->permissions); + if (tb->subtypes) { MonoDynamicTable *ntable; @@ -2469,7 +2877,7 @@ type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) { mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs); if (tb->fields) { - for (i = 0; i < mono_array_length (tb->fields); ++i) { + for (i = 0; i < tb->num_fields; ++i) { MonoReflectionFieldBuilder* fb; fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i); mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs); @@ -2499,7 +2907,7 @@ type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) { } if (tb->methods) { - for (i = 0; i < mono_array_length (tb->methods); ++i) { + for (i = 0; i < tb->num_methods; ++i) { MonoReflectionMethodBuilder* mb; mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i); mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs); @@ -2523,12 +2931,12 @@ module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) if (!mb->types) return; - for (i = 0; i < mono_array_length (mb->types); ++i) + for (i = 0; i < mb->num_types; ++i) type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i)); } static void -mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, +mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly) { MonoDynamicTable *table; @@ -2543,10 +2951,16 @@ mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, alloc_table (table, table->rows); values = table->values + table->next_idx * MONO_FILE_SIZE; values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA; - values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, mb->dynamic_image->image.module_name); - /* This depends on the fact that the main module is emitted last */ - dir = mono_string_to_utf8 (mb->assemblyb->dir); - path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, mb->dynamic_image->image.module_name); + values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name); + if (module->image->dynamic) { + /* This depends on the fact that the main module is emitted last */ + dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir); + path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name); + } + else { + dir = NULL; + path = g_strdup (module->image->name); + } mono_sha1_get_digest_from_file (path, hash); g_free (dir); g_free (path); @@ -2576,51 +2990,89 @@ mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *m table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0; } -static void -mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb, - guint32 module_index, guint32 parent_index, - MonoDynamicImage *assembly) +static guint32 +mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass, + guint32 module_index, guint32 parent_index, + MonoDynamicImage *assembly) { MonoDynamicTable *table; guint32 *values; - guint32 visib; - char *name; - char *name_space; - int i; + guint32 visib, res; - visib = tb->attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK; + visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK; if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC))) - return; - - name = mono_string_to_utf8 (tb->name); - name_space = mono_string_to_utf8 (tb->nspace); + return 0; table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE]; table->rows++; alloc_table (table, table->rows); values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE; - values [MONO_EXP_TYPE_FLAGS] = tb->attrs; - values [MONO_EXP_TYPE_TYPEDEF] = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx); - if (tb->nesting_type) { + values [MONO_EXP_TYPE_FLAGS] = klass->flags; + values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token; + if (klass->nested_in) values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE; - } - else { - values [MONO_EXP_TYPE_TYPEDEF] = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx); + else values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE; - } - values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, name); - values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, name_space); + values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name); + values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space); - g_free (name); - g_free (name_space); + res = table->next_idx; table->next_idx ++; /* Emit nested types */ + if (klass->nested_classes) { + GList *tmp; + + for (tmp = klass->nested_classes; tmp; tmp = tmp->next) + mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly); + } + + return res; +} + +static void +mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb, + guint32 module_index, guint32 parent_index, + MonoDynamicImage *assembly) +{ + MonoClass *klass; + guint32 idx, i; + + klass = mono_class_from_mono_type (tb->type.type); + + klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx); + + idx = mono_image_fill_export_table_from_class (domain, klass, module_index, + parent_index, assembly); + + /* + * Emit nested types + * We need to do this ourselves since klass->nested_classes is not set up. + */ if (tb->subtypes) { for (i = 0; i < mono_array_length (tb->subtypes); ++i) - mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, table->next_idx - 1, assembly); + mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly); + } +} + +static void +mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module, + guint32 module_index, + MonoDynamicImage *assembly) +{ + MonoImage *image = module->image; + MonoTableInfo *t; + guint32 i; + + t = &image->tables [MONO_TABLE_TYPEDEF]; + + for (i = 0; i < t->rows; ++i) { + MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1)); + + if (klass->flags & TYPE_ATTRIBUTE_PUBLIC) + mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly); } } @@ -2788,8 +3240,17 @@ build_compressed_metadata (MonoDynamicImage *assembly) int32val = (guint32*)p; *int32val = GUINT32_TO_LE (0); /* reserved */ p += 4; - *p++ = 1; /* version */ - *p++ = 0; + + if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) || + (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) || + (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) { + *p++ = 1; /* version */ + *p++ = 1; + } else { + *p++ = 1; /* version */ + *p++ = 0; + } + if (meta->idx_string_wide) *p |= 0x01; if (meta->idx_guid_wide) @@ -2886,7 +3347,7 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse MonoReflectionMethodBuilder *method; MonoReflectionTypeBuilder *tb; MonoReflectionArrayMethod *am; - guint32 i, idx; + guint32 i, idx = 0; unsigned char *target; for (i = 0; i < ilgen->num_token_fixups; ++i) { @@ -2911,7 +3372,8 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) { ctor = (MonoReflectionCtorBuilder *)iltoken->member; idx = ctor->table_idx; - } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) { + } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || + !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) { MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method; idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m)); } else { @@ -2933,12 +3395,12 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method; g_assert (m->klass->generic_inst); continue; - } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") || - !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor") || - !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedField")) { - continue; } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) { continue; + } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) { + MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field; + g_assert (f->generic_type); + continue; } else { g_assert_not_reached (); } @@ -2948,9 +3410,6 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method; g_assert (m->signature->generic_param_count); continue; - } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") || - !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor")) { - continue; } else { g_assert_not_reached (); } @@ -2964,8 +3423,63 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse } } +/* + * fixup_cattrs: + * + * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final + * value is not known when the table is emitted. + */ +static void +fixup_cattrs (MonoDynamicImage *assembly) +{ + MonoDynamicTable *table; + guint32 *values; + guint32 type, i, idx, token; + MonoObject *ctor; + + table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE]; + + for (i = 0; i < table->rows; ++i) { + values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE); + + type = values [MONO_CUSTOM_ATTR_TYPE]; + if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) { + idx = type >> CUSTOM_ATTR_TYPE_BITS; + token = mono_metadata_make_token (MONO_TABLE_METHOD, idx); + ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token)); + g_assert (ctor); + + if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) { + MonoMethod *m = ((MonoReflectionMethod*)ctor)->method; + idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m)); + values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF; + } + } + } +} + +static void +assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation) +{ + MonoDynamicTable *table; + guint32 *values; + char *name; + + table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE]; + table->rows++; + alloc_table (table, table->rows); + values = table->values + table->next_idx * MONO_MANIFEST_SIZE; + values [MONO_MANIFEST_OFFSET] = rsrc->offset; + values [MONO_MANIFEST_FLAGS] = rsrc->attrs; + name = mono_string_to_utf8 (rsrc->name); + values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name); + g_free (name); + values [MONO_MANIFEST_IMPLEMENTATION] = implementation; + table->next_idx++; +} + static void -assembly_add_resource (MonoDynamicImage *assembly, MonoReflectionResource *rsrc) +assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc) { MonoDynamicTable *table; guint32 *values; @@ -2993,29 +3507,28 @@ assembly_add_resource (MonoDynamicImage *assembly, MonoReflectionResource *rsrc) mono_image_add_stream_data (&assembly->blob, hash, 20); g_free (name); idx = table->next_idx++; + rsrc->offset = 0; idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS); - offset = 0; } else { char sizebuf [4]; offset = mono_array_length (rsrc->data); sizebuf [0] = offset; sizebuf [1] = offset >> 8; sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24; - offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4); + rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4); mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data)); - idx = 0; + + if (!mb->is_main) + /* + * The entry should be emitted into the MANIFESTRESOURCE table of + * the main module, but that needs to reference the FILE table + * which isn't emitted yet. + */ + return; + else + idx = 0; } - table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE]; - table->rows++; - alloc_table (table, table->rows); - values = table->values + table->next_idx * MONO_MANIFEST_SIZE; - values [MONO_MANIFEST_OFFSET] = offset; - values [MONO_MANIFEST_FLAGS] = rsrc->attrs; - name = mono_string_to_utf8 (rsrc->name); - values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name); - g_free (name); - values [MONO_MANIFEST_IMPLEMENTATION] = idx; - table->next_idx++; + assembly_add_resource_manifest (mb, assembly, rsrc, idx); } static void @@ -3069,6 +3582,89 @@ load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) { return token; } +static void +mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb) +{ + MonoDynamicTable *table; + MonoDynamicImage *assembly; + MonoReflectionAssemblyBuilder *assemblyb; + MonoDomain *domain; + guint32 *values; + char *name; + int i; + guint32 module_index; + + assemblyb = moduleb->assemblyb; + assembly = moduleb->dynamic_image; + domain = mono_object_domain (assemblyb); + + /* Emit ASSEMBLY table */ + table = &assembly->tables [MONO_TABLE_ASSEMBLY]; + alloc_table (table, 1); + values = table->values + MONO_ASSEMBLY_SIZE; + values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1; + name = mono_string_to_utf8 (assemblyb->name); + values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name); + g_free (name); + if (assemblyb->culture) { + name = mono_string_to_utf8 (assemblyb->culture); + values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name); + g_free (name); + } else { + values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, ""); + } + values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly); + values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags; + set_version_from_string (assemblyb->version, values); + + /* Emit FILE + EXPORTED_TYPE table */ + module_index = 0; + for (i = 0; i < mono_array_length (assemblyb->modules); ++i) { + int j; + MonoReflectionModuleBuilder *file_module = + mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i); + if (file_module != moduleb) { + mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly); + module_index ++; + if (file_module->types) { + for (j = 0; j < file_module->num_types; ++j) { + MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j); + mono_image_fill_export_table (domain, tb, module_index, 0, + assembly); + } + } + } + } + if (assemblyb->loaded_modules) { + for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) { + MonoReflectionModule *file_module = + mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i); + mono_image_fill_file_table (domain, file_module, assembly); + module_index ++; + mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly); + } + } + + /* Emit MANIFESTRESOURCE table */ + module_index = 0; + for (i = 0; i < mono_array_length (assemblyb->modules); ++i) { + int j; + MonoReflectionModuleBuilder *file_module = + mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i); + /* The table for the main module is emitted later */ + if (file_module != moduleb) { + module_index ++; + if (file_module->resources) { + int len = mono_array_length (file_module->resources); + for (j = 0; j < len; ++j) { + MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j); + assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS)); + } + } + } + } +} + /* * mono_image_build_metadata() will fill the info in all the needed metadata tables * for the modulebuilder @moduleb. @@ -3083,9 +3679,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb) MonoReflectionAssemblyBuilder *assemblyb; MonoDomain *domain; guint32 *values; - char *name; int i; - guint32 module_index; assemblyb = moduleb->assemblyb; assembly = moduleb->dynamic_image; @@ -3097,41 +3691,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb) assembly->text_rva = START_TEXT_RVA; if (moduleb->is_main) { - /* Emit the manifest */ - table = &assembly->tables [MONO_TABLE_ASSEMBLY]; - alloc_table (table, 1); - values = table->values + MONO_ASSEMBLY_SIZE; - values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1; - name = mono_string_to_utf8 (assemblyb->name); - values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name); - g_free (name); - if (assemblyb->culture) { - name = mono_string_to_utf8 (assemblyb->culture); - values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name); - g_free (name); - } else { - values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, ""); - } - values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly); - values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags; - set_version_from_string (assemblyb->version, values); - - /* Emit FILE + EXPORTED_TYPE table */ - module_index = 0; - for (i = 0; i < mono_array_length (assemblyb->modules); ++i) { - int j; - MonoReflectionModuleBuilder *file_module = - mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i); - if (file_module != moduleb) { - mono_image_fill_file_table (domain, file_module, assembly); - module_index ++; - for (j = 0; j < mono_array_length (file_module->types); ++j) { - MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j); - mono_image_fill_export_table (domain, tb, module_index, 0, - assembly); - } - } - } + mono_image_emit_manifest (moduleb); } table = &assembly->tables [MONO_TABLE_TYPEDEF]; @@ -3180,7 +3740,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb) GPtrArray *types = g_ptr_array_new (); if (moduleb->types) - for (i = 0; i < mono_array_length (moduleb->types); ++i) { + for (i = 0; i < moduleb->num_types; ++i) { MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i); collect_types (types, type); } @@ -3207,6 +3767,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb) /* fixup tokens */ mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly); + fixup_cattrs (assembly); } /* @@ -3277,7 +3838,7 @@ guint32 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj) { MonoClass *klass; - guint32 token; + guint32 token = 0; klass = obj->vtable->klass; if (strcmp (klass->name, "MethodBuilder") == 0) { @@ -3311,7 +3872,13 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj) MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj; token = tb->table_idx | MONO_TOKEN_TYPE_DEF; } - else if (strcmp (klass->name, "MonoType") == 0) { + else if (strcmp (klass->name, "MonoType") == 0 || + strcmp (klass->name, "GenericTypeParameterBuilder") == 0) { + MonoReflectionType *tb = (MonoReflectionType *)obj; + token = mono_metadata_token_from_dor ( + mono_image_typedef_or_ref (assembly, tb->type)); + } + else if (strcmp (klass->name, "MonoGenericInst") == 0) { MonoReflectionType *tb = (MonoReflectionType *)obj; token = mono_metadata_token_from_dor ( mono_image_typedef_or_ref (assembly, tb->type)); @@ -3319,9 +3886,10 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj) else if (strcmp (klass->name, "MonoCMethod") == 0 || strcmp (klass->name, "MonoMethod") == 0) { MonoReflectionMethod *m = (MonoReflectionMethod *)obj; - if (m->method->signature->generic_param_count) { + if (m->method->signature->is_inflated) { + token = mono_image_get_methodspec_token (assembly, m->method); + } else if (m->method->signature->generic_param_count) { g_assert_not_reached (); - token = mono_image_get_methodspec_token (assembly, m->method, NULL); } else if ((m->method->klass->image == &assembly->image) && !m->method->klass->generic_inst) { static guint32 method_table_idx = 0xffffff; @@ -3336,23 +3904,14 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj) token = mono_image_get_methodref_token (assembly, m->method); /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/ } - else if (strcmp (klass->name, "MonoInflatedMethod") == 0 || - strcmp (klass->name, "MonoInflatedCtor") == 0) { - MonoReflectionInflatedMethod *m = (MonoReflectionInflatedMethod *)obj; - token = mono_image_get_methodspec_token (assembly, m->rmethod.method, m->ginst); - } - else if (strcmp (klass->name, "MonoInflatedField") == 0) { - MonoReflectionInflatedField *f = (MonoReflectionInflatedField *)obj; - token = mono_image_get_inflated_field_token (assembly, f); - } else if (strcmp (klass->name, "MonoField") == 0) { MonoReflectionField *f = (MonoReflectionField *)obj; - if (f->klass->image == &assembly->image) { + if ((f->klass->image == &assembly->image) && !f->field->generic_type) { static guint32 field_table_idx = 0xffffff; field_table_idx --; token = MONO_TOKEN_FIELD_DEF | field_table_idx; } else - token = mono_image_get_fieldref_token (assembly, f->field, f->klass); + token = mono_image_get_fieldref_token (assembly, f); /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/ } else if (strcmp (klass->name, "MonoArrayMethod") == 0) { @@ -3413,6 +3972,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, image->image.assembly_name = image->image.name; /* they may be different */ image->image.module_name = module_name; image->image.version = g_strdup (version); + image->image.dynamic = TRUE; image->image.references = g_new0 (MonoAssembly*, 1); image->image.references [0] = NULL; @@ -3425,6 +3985,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, image->method_aux_hash = mono_g_hash_table_new (NULL, NULL); image->handleref = g_hash_table_new (NULL, NULL); image->tokens = mono_g_hash_table_new (NULL, NULL); + image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal); image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal); image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal); @@ -3474,7 +4035,7 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb) return; #if HAVE_BOEHM_GC - assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicImage)); + assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly)); #else assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1); #endif @@ -3515,6 +4076,14 @@ calc_section_size (MonoDynamicImage *assembly) assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ; nsections++; + if (assembly->win32_res) { + guint32 res_size = (assembly->win32_res_size + 3) & ~3; + + assembly->sections [MONO_SECTION_RSRC].size = res_size; + assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ; + nsections++; + } + assembly->sections [MONO_SECTION_RELOC].size = 12; assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA; nsections++; @@ -3522,6 +4091,227 @@ calc_section_size (MonoDynamicImage *assembly) return nsections; } +typedef struct { + guint32 id; + guint32 offset; + GSList *children; + MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */ +} ResTreeNode; + +static int +resource_tree_compare_by_id (gconstpointer a, gconstpointer b) +{ + ResTreeNode *t1 = (ResTreeNode*)a; + ResTreeNode *t2 = (ResTreeNode*)b; + + return t1->id - t2->id; +} + +/* + * resource_tree_create: + * + * Organize the resources into a resource tree. + */ +static ResTreeNode * +resource_tree_create (MonoArray *win32_resources) +{ + ResTreeNode *tree, *res_node, *type_node, *lang_node; + GSList *l; + int i; + + tree = g_new0 (ResTreeNode, 1); + + for (i = 0; i < mono_array_length (win32_resources); ++i) { + MonoReflectionWin32Resource *win32_res = + (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i); + + /* Create node */ + + lang_node = g_new0 (ResTreeNode, 1); + lang_node->id = win32_res->lang_id; + lang_node->win32_res = win32_res; + + /* Create type node if neccesary */ + type_node = NULL; + for (l = tree->children; l; l = l->next) + if (((ResTreeNode*)(l->data))->id == win32_res->res_type) { + type_node = (ResTreeNode*)l->data; + break; + } + + if (!type_node) { + type_node = g_new0 (ResTreeNode, 1); + type_node->id = win32_res->res_type; + + /* + * The resource types have to be sorted otherwise + * Windows Explorer can't display the version information. + */ + tree->children = g_slist_insert_sorted (tree->children, type_node, + resource_tree_compare_by_id); + } + + /* Create res node if neccesary */ + res_node = NULL; + for (l = type_node->children; l; l = l->next) + if (((ResTreeNode*)(l->data))->id == win32_res->res_id) { + res_node = (ResTreeNode*)l->data; + break; + } + + if (!res_node) { + res_node = g_new0 (ResTreeNode, 1); + res_node->id = win32_res->res_id; + type_node->children = g_slist_append (type_node->children, res_node); + } + + res_node->children = g_slist_append (res_node->children, lang_node); + } + + return tree; +} + +/* + * resource_tree_encode: + * + * Encode the resource tree into the format used in the PE file. + */ +static void +resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf) +{ + char *entries; + MonoPEResourceDir dir; + MonoPEResourceDirEntry dir_entry; + MonoPEResourceDataEntry data_entry; + GSList *l; + + /* + * For the format of the resource directory, see the article + * "An In-Depth Look into the Win32 Portable Executable File Format" by + * Matt Pietrek + */ + + memset (&dir, 0, sizeof (dir)); + memset (&dir_entry, 0, sizeof (dir_entry)); + memset (&data_entry, 0, sizeof (data_entry)); + + g_assert (sizeof (dir) == 16); + g_assert (sizeof (dir_entry) == 8); + g_assert (sizeof (data_entry) == 16); + + node->offset = p - begin; + + /* IMAGE_RESOURCE_DIRECTORY */ + dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children)); + + memcpy (p, &dir, sizeof (dir)); + p += sizeof (dir); + + /* Reserve space for entries */ + entries = p; + p += sizeof (dir_entry) * dir.res_id_entries; + + /* Write children */ + for (l = node->children; l; l = l->next) { + ResTreeNode *child = (ResTreeNode*)l->data; + + if (child->win32_res) { + + child->offset = p - begin; + + /* IMAGE_RESOURCE_DATA_ENTRY */ + data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry)); + data_entry.rde_size = mono_array_length (child->win32_res->res_data); + + memcpy (p, &data_entry, sizeof (data_entry)); + p += sizeof (data_entry); + + memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size); + p += data_entry.rde_size; + } + else + resource_tree_encode (child, begin, p, &p); + } + + /* IMAGE_RESOURCE_ENTRY */ + for (l = node->children; l; l = l->next) { + ResTreeNode *child = (ResTreeNode*)l->data; + dir_entry.name_offset = GUINT32_TO_LE (child->id); + + dir_entry.is_dir = child->win32_res ? 0 : 1; + dir_entry.dir_offset = GUINT32_TO_LE (child->offset); + + memcpy (entries, &dir_entry, sizeof (dir_entry)); + entries += sizeof (dir_entry); + } + + *endbuf = p; +} + +static void +assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb) +{ + char *buf; + char *p; + guint32 size, i; + MonoReflectionWin32Resource *win32_res; + ResTreeNode *tree; + + if (!assemblyb->win32_resources) + return; + + /* + * Resources are stored in a three level tree inside the PE file. + * - level one contains a node for each type of resource + * - level two contains a node for each resource + * - level three contains a node for each instance of a resource for a + * specific language. + */ + + tree = resource_tree_create (assemblyb->win32_resources); + + /* Estimate the size of the encoded tree */ + size = 0; + for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) { + win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i); + size += mono_array_length (win32_res->res_data); + } + /* Directory structure */ + size += mono_array_length (assemblyb->win32_resources) * 256; + p = buf = g_malloc (size); + + resource_tree_encode (tree, p, p, &p); + + g_assert (p - buf < size); + + assembly->win32_res = g_malloc (p - buf); + assembly->win32_res_size = p - buf; + memcpy (assembly->win32_res, buf, p - buf); + + g_free (buf); +} + +static void +fixup_resource_directory (char *res_section, char *p, guint32 rva) +{ + MonoPEResourceDir *dir = (MonoPEResourceDir*)p; + int i; + + p += sizeof (MonoPEResourceDir); + for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) { + MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p; + char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset)); + if (dir_entry->is_dir) + fixup_resource_directory (res_section, child, rva); + else { + MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child; + data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva); + } + + p += sizeof (MonoPEResourceDirEntry); + } +} + /* * mono_image_create_pefile: * @mb: a module builder object @@ -3566,15 +4356,23 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) { mono_image_build_metadata (mb); - if (assemblyb->resources) { + if (mb->is_main && assemblyb->resources) { int len = mono_array_length (assemblyb->resources); for (i = 0; i < len; ++i) - assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i)); + assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i)); + } + + if (mb->resources) { + int len = mono_array_length (mb->resources); + for (i = 0; i < len; ++i) + assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i)); } - build_compressed_metadata (assembly); + if (mb->is_main) + assembly_add_win32_resources (assembly, assemblyb); + nsections = calc_section_size (assembly); pefile = &assembly->pefile; @@ -3738,8 +4536,16 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) { cli_header->ch_size = GUINT32_FROM_LE (72); cli_header->ch_runtime_major = GUINT16_FROM_LE (2); cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY); - if (assemblyb->entry_point) - cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF); + if (assemblyb->entry_point) { + guint32 table_idx = 0; + if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) { + MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point; + table_idx = methodb->table_idx; + } + else + table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method)); + cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF); + } else cli_header->ch_entry_point = GUINT32_FROM_LE (0); /* The embedded managed resources */ @@ -3810,6 +4616,15 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) { *data16 = 0; /* terminate */ break; case MONO_SECTION_RSRC: + if (assembly->win32_res) { + text_offset = assembly->sections [i].offset; + + /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */ + fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva); + + memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size); + } + break; default: g_assert_not_reached (); } @@ -3826,6 +4641,41 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) { #endif } +MonoReflectionModule * +mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName) +{ + char *name; + MonoImage *image; + MonoImageOpenStatus status; + MonoDynamicAssembly *assembly; + + name = mono_string_to_utf8 (fileName); + + image = mono_image_open (name, &status); + if (status) { + MonoException *exc; + if (status == MONO_IMAGE_ERROR_ERRNO) + exc = mono_get_exception_file_not_found (fileName); + else + exc = mono_get_exception_bad_image_format (name); + g_free (name); + mono_raise_exception (exc); + } + + g_free (name); + + assembly = ab->dynamic_assembly; + image->assembly = (MonoAssembly*)assembly; + + mono_assembly_load_references (image, &status); + if (status) { + mono_image_close (image); + mono_raise_exception (mono_get_exception_file_not_found (fileName)); + } + + return mono_module_get_object (mono_domain_get (), image); +} + /* * We need to return always the same object for MethodInfo, FieldInfo etc.. * but we need to consider the reflected type. @@ -3958,9 +4808,11 @@ mono_module_get_object (MonoDomain *domain, MonoImage *image) res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly); res->fqname = mono_string_new (domain, image->name); - res->name = mono_string_new (domain, image->name); + res->name = mono_string_new (domain, g_path_get_basename (image->name)); res->scopename = mono_string_new (domain, image->module_name); + mono_image_addref (image); + CACHE_OBJECT (image, res, NULL); return res; } @@ -4086,6 +4938,36 @@ mymono_metadata_type_hash (MonoType *t1) return hash; } +static MonoReflectionGenericInst* +mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst) +{ + static MonoClass *System_Reflection_MonoGenericInst; + MonoReflectionGenericInst *res; + MonoGenericInst *ginst; + MonoClass *gklass; + + if (!System_Reflection_MonoGenericInst) { + System_Reflection_MonoGenericInst = mono_class_from_name ( + mono_defaults.corlib, "System.Reflection", "MonoGenericInst"); + g_assert (System_Reflection_MonoGenericInst); + } + + ginst = geninst->data.generic_inst; + gklass = mono_class_from_mono_type (ginst->generic_type); + + mono_class_init (ginst->klass); + + res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst); + + res->type.type = geninst; + if (gklass->wastypebuilder && gklass->reflection_info) + res->generic_type = gklass->reflection_info; + else + res->generic_type = mono_type_get_object (domain, ginst->generic_type); + + return res; +} + /* * mono_type_get_object: * @domain: an app domain @@ -4107,6 +4989,12 @@ mono_type_get_object (MonoDomain *domain, MonoType *type) mono_domain_unlock (domain); return res; } + if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) { + res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type); + mono_g_hash_table_insert (domain->type_hash, type, res); + mono_domain_unlock (domain); + return res; + } if (klass->reflection_info && !klass->wastypebuilder) { //g_assert_not_reached (); /* should this be considered an error condition? */ @@ -4294,8 +5182,9 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) { memset (assembly, 0, sizeof (MonoAssemblyName)); assembly->name = p; assembly->culture = ""; - - while (*p && (isalnum (*p) || *p == '.' || *p == '-')) + assembly->public_tok_value = NULL; + + while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@')) p++; found_sep = 0; while (*p == ' ' || *p == ',') { @@ -4307,7 +5196,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) { if (!found_sep) return 1; while (*p) { - if (*p == 'V' && strncmp (p, "Version=", 8) == 0) { + if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) { p += 8; assembly->major = strtoul (p, &s, 10); if (s == p || *s != '.') @@ -4324,10 +5213,11 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) { assembly->revision = strtoul (p, &s, 10); if (s == p) return 1; - } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) { + p = s; + } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) { p += 8; - if (strncmp (p, "neutral", 7) == 0) { - assembly->culture = ""; + if (g_ascii_strncasecmp (p, "neutral", 7) == 0) { + assembly->culture = g_strdup (""); p += 7; } else { assembly->culture = p; @@ -4335,26 +5225,16 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) { p++; } } - } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) { + } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) { p += 15; - s = p; - while (*s && isxdigit (*s)) { - *s = tolower (*s); - s++; - } - assembly->hash_len = s - p; - if (!(s-p) || ((s-p) & 1)) - return 1; - assembly->hash_value = s = p; - while (*s && isxdigit (*s)) { - int val; - val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10; - s++; - *p = val << 4; - *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10; - p++; + if (strncmp (p, "null", 4) == 0) { + p += 4; + } else { + assembly->public_tok_value = p; + while (*p && *p != ',') { + p++; + } } - p = s; } else { while (*p && *p != ',') p++; @@ -4597,9 +5477,36 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL); - if (assembly && (!image || (assembly->assembly->image == image))) - type = mono_reflection_get_type_internal (assembly->assembly->image, - info, ignorecase); + if (assembly && (!image || (assembly->assembly->image == image))) { + + if (assembly->assembly->dynamic) { + /* Enumerate all modules */ + MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly; + int i; + + type = NULL; + if (abuilder->modules) { + for (i = 0; i < mono_array_length (abuilder->modules); ++i) { + MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i); + type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase); + if (type) + break; + } + } + + if (!type && abuilder->loaded_modules) { + for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) { + MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i); + type = mono_reflection_get_type_internal (mod->image, info, ignorecase); + if (type) + break; + } + } + } + else + type = mono_reflection_get_type_internal (assembly->assembly->image, + info, ignorecase); + } g_string_free (fullName, TRUE); return type; } @@ -4619,6 +5526,7 @@ mono_reflection_type_from_name (char *name, MonoImage *image) { MonoType *type; MonoTypeNameParse info; + MonoAssembly *assembly; /*g_print ("requested type %s\n", str);*/ if (!mono_reflection_parse_type (name, &info)) { @@ -4628,13 +5536,15 @@ mono_reflection_type_from_name (char *name, MonoImage *image) } if (info.assembly.name) { - image = mono_image_loaded (info.assembly.name); + assembly = mono_assembly_loaded (&info.assembly); /* do we need to load if it's not already loaded? */ - if (!image) { + if (!assembly) { g_list_free (info.modifiers); g_list_free (info.nested); return NULL; } + else + image = assembly->image; } else if (image == NULL) { image = mono_defaults.corlib; } @@ -4728,12 +5638,15 @@ handle_type: g_warning ("Cannot load type '%s'", n); g_free (n); *end = p + slen; - return mono_type_get_object (mono_domain_get (), t); + if (t) + return mono_type_get_object (mono_domain_get (), t); + else + return NULL; } case MONO_TYPE_OBJECT: { char subt = *p++; MonoObject *obj; - MonoClass *subc; + MonoClass *subc = NULL; void *val; if (subt == 0x50) { @@ -4940,10 +5853,17 @@ create_custom_attr (MonoImage *image, MonoMethod *method, MonoObject *attr; void **params; + mono_class_init (method->klass); + + if (len == 0) { + attr = mono_object_new (mono_domain_get (), method->klass); + mono_runtime_invoke (method, attr, NULL, NULL); + return attr; + } + if (len < 2 || read16 (p) != 0x0001) /* Prolog */ return NULL; - mono_class_init (method->klass); /*g_print ("got attr %s\n", method->klass->name);*/ params = g_new (void*, method->signature->param_count); @@ -4976,6 +5896,10 @@ create_custom_attr (MonoImage *image, MonoMethod *method, named += type_len; /* FIXME: lookup the type and check type consistency */ } + else + if (data_type == MONO_TYPE_SZARRAY) + /* The spec does not mention this */ + named ++; name_len = mono_metadata_decode_blob_size (named, &named); name = g_malloc (name_len + 1); memcpy (name, named, name_len); @@ -5119,6 +6043,20 @@ mono_custom_attrs_from_assembly (MonoAssembly *assembly) return mono_custom_attrs_from_index (assembly->image, idx); } +static MonoCustomAttrInfo* +mono_custom_attrs_from_module (MonoImage *image) +{ + MonoCustomAttrInfo *cinfo; + guint32 idx; + + if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image))) + return cinfo; + idx = 1; /* there is only one module */ + idx <<= CUSTOM_ATTR_BITS; + idx |= CUSTOM_ATTR_MODULE; + return mono_custom_attrs_from_index (image, idx); +} + MonoCustomAttrInfo* mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property) { @@ -5168,10 +6106,15 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param) guint32 i, idx, method_index; guint32 param_list, param_last, param_pos, found; MonoImage *image; - - /* FIXME: handle dynamic custom attrs for parameters */ - /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field))) - return cinfo;*/ + MonoReflectionMethodAux *aux; + + if (method->klass->image->dynamic) { + aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method); + if (!aux || !aux->param_cattr) + return NULL; + return aux->param_cattr [param]; + } + image = method->klass->image; method_index = find_method_index (method); ca = &image->tables [MONO_TABLE_METHOD]; @@ -5218,7 +6161,7 @@ mono_reflection_get_custom_attrs (MonoObject *obj) { MonoClass *klass; MonoArray *result; - MonoCustomAttrInfo *cinfo; + MonoCustomAttrInfo *cinfo = NULL; MONO_ARCH_SAVE_REGS; @@ -5231,15 +6174,18 @@ mono_reflection_get_custom_attrs (MonoObject *obj) } else if (strcmp ("Assembly", klass->name) == 0) { MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj; cinfo = mono_custom_attrs_from_assembly (rassembly->assembly); + } else if (strcmp ("Module", klass->name) == 0) { + MonoReflectionModule *module = (MonoReflectionModule*)obj; + cinfo = mono_custom_attrs_from_module (module->image); } else if (strcmp ("MonoProperty", klass->name) == 0) { MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj; - cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property); + cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property); } else if (strcmp ("MonoEvent", klass->name) == 0) { MonoReflectionEvent *revent = (MonoReflectionEvent*)obj; - cinfo = mono_custom_attrs_from_event (revent->klass, revent->event); + cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event); } else if (strcmp ("MonoField", klass->name) == 0) { MonoReflectionField *rfield = (MonoReflectionField*)obj; - cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field); + cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field); } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) { MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj; cinfo = mono_custom_attrs_from_method (rmethod->method); @@ -5250,6 +6196,9 @@ mono_reflection_get_custom_attrs (MonoObject *obj) } else if (strcmp ("AssemblyBuilder", klass->name) == 0) { MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj; cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs); + } else if (strcmp ("TypeBuilder", klass->name) == 0) { + MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj; + cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs); } else { /* handle other types here... */ g_error ("get custom attrs not yet supported for %s", klass->name); } @@ -5302,6 +6251,17 @@ method_builder_to_signature (MonoReflectionMethodBuilder *method) { return sig; } +static MonoMethodSignature* +dynamic_method_to_signature (MonoReflectionDynamicMethod *method) { + MonoMethodSignature *sig; + + sig = parameters_to_signature (method->parameters); + sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1; + sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg; + sig->generic_param_count = 0; + return sig; +} + static void get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type) { @@ -5335,27 +6295,6 @@ get_field_name_and_type (MonoObject *field, char **name, MonoType **type) } } -static char* -type_get_qualified_name (MonoType *type, MonoAssembly *ass) { - char *name, *result; - MonoClass *klass; - MonoAssembly *ta; - - name = mono_type_get_name (type); - klass = my_mono_class_from_mono_type (type); - ta = klass->image->assembly; - if (ta == ass || klass->image == mono_defaults.corlib) - return name; - - /* missing public key */ - result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s", - name, ta->aname.name, - ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision, - ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral"); - g_free (name); - return result; -} - static void encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg) { @@ -5613,6 +6552,8 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo g_free (str); } else { mono_metadata_encode_value (ptype->type, p, &p); + if (ptype->type == MONO_TYPE_SZARRAY) + mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p); } len = strlen (pname); mono_metadata_encode_value (len, p, &p); @@ -5775,10 +6716,8 @@ mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb) for (i = 0; i < count; i++) { MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i); - klass->gen_params [i] = *gparam->param; + klass->gen_params [i] = *gparam->type.type->data.generic_param; } - - ensure_runtime_vtable (klass); } /* @@ -5843,8 +6782,7 @@ mono_marshal_spec_from_builder (MonoAssembly *assembly, case MONO_NATIVE_CUSTOM: if (minfo->marshaltyperef) res->data.custom_data.custom_name = - type_get_qualified_name (minfo->marshaltyperef->type, - assembly); + type_get_fully_qualified_name (minfo->marshaltyperef->type); if (minfo->mcookie) res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie); break; @@ -5858,8 +6796,8 @@ mono_marshal_spec_from_builder (MonoAssembly *assembly, static MonoMethod* reflection_methodbuilder_to_mono_method (MonoClass *klass, - ReflectionMethodBuilder *rmb, - MonoMethodSignature *sig) + ReflectionMethodBuilder *rmb, + MonoMethodSignature *sig) { MonoMethod *m; MonoMethodNormal *pm; @@ -5871,6 +6809,9 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1); else + if (rmb->refs) + m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1); + else m = (MonoMethod *)g_new0 (MonoMethodNormal, 1); pm = (MonoMethodNormal*)m; @@ -5881,7 +6822,8 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, m->name = mono_string_to_utf8 (rmb->name); m->klass = klass; m->signature = sig; - m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx); + if (rmb->table_idx) + m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx); if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) { if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor")) @@ -5944,23 +6886,52 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, header->num_clauses = num_clauses; if (num_clauses) { header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image, - rmb->ilgen, - num_clauses); + rmb->ilgen, + num_clauses); + } + + if (rmb->generic_params) { + int count = mono_array_length (rmb->generic_params); + header->gen_params = g_new0 (MonoGenericParam, count); + for (i = 0; i < count; i++) { + MonoReflectionGenericParam *gp = + mono_array_get (rmb->generic_params, + MonoReflectionGenericParam*, i); + + header->gen_params [i] = *gp->type.type->data.generic_param; + } } pm->header = header; } - method_aux = g_new0 (MonoReflectionMethodAux, 1); + if (rmb->refs) { + MonoMethodWrapper *mw = (MonoMethodWrapper*)m; + int i; + + m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD; + + for (i = 0; i < rmb->nrefs; ++i) + mw->data = g_list_append (mw->data, rmb->refs [i]); + } + + method_aux = NULL; /* Parameter names */ - if (rmb->parameters) { - method_aux->param_names = g_new0 (char *, m->signature->param_count); - for (i = 0; i < m->signature->param_count; ++i) { + if (rmb->pinfo) { + if (!method_aux) + method_aux = g_new0 (MonoReflectionMethodAux, 1); + method_aux->param_names = g_new0 (char *, m->signature->param_count + 1); + for (i = 0; i <= m->signature->param_count; ++i) { MonoReflectionParamBuilder *pb; - if ((pb = mono_array_get (rmb->parameters, MonoReflectionParamBuilder*, i))) { + if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) { if (pb->name) method_aux->param_names [i] = mono_string_to_utf8 (pb->name); + if (pb->cattrs) { + if (!method_aux->param_cattr) + method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1); + method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs); + } } } } @@ -5979,10 +6950,14 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, } } } - if (specs != NULL) + if (specs != NULL) { + if (!method_aux) + method_aux = g_new0 (MonoReflectionMethodAux, 1); method_aux->param_marshall = specs; + } - mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux); + if (klass->image->dynamic && method_aux) + mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux); return m; } @@ -6072,106 +7047,159 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* return field; } -static MonoReflectionInflatedMethod* -inflated_method_get_object (MonoDomain *domain, MonoMethod *method, MonoReflectionMethod *declaring, - MonoGenericInst *ginst) -{ - const char *cname; - MonoClass *klass, *refclass; - MonoReflectionInflatedMethod *ret; - - refclass = method->klass; - - CHECK_OBJECT (MonoReflectionInflatedMethod *, method, refclass); - if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) - cname = "MonoInflatedCtor"; - else - cname = "MonoInflatedMethod"; - klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname); - g_assert (klass); - - ret = (MonoReflectionInflatedMethod*)mono_object_new (domain, klass); - ret->rmethod.method = method; - ret->rmethod.name = mono_string_new (domain, method->name); - ret->rmethod.reftype = mono_type_get_object (domain, &refclass->byval_arg); - ret->declaring = declaring; - ret->ginst = ginst; - CACHE_OBJECT (method, ret, refclass); - return ret; -} - -MonoReflectionGenericInst* -mono_reflection_bind_generic_parameters (MonoReflectionType *type, MonoArray *types) +static MonoType* +do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, + MonoType **types) { - static MonoClass *System_Reflection_MonoGenericInst; + MonoClass *klass; + MonoReflectionTypeBuilder *tb = NULL; + MonoGenericInst *ginst; MonoDomain *domain; MonoType *geninst; - MonoGenericInst *ginst; - MonoReflectionType *ptype; - MonoClass *klass, *iklass, *pklass; - MonoReflectionGenericInst *res, *parent = NULL; - int i; - - domain = mono_object_domain (type); + int icount, i; klass = mono_class_from_mono_type (type->type); - if (!klass->gen_params && !klass->generic_inst) + if (!klass->gen_params && !klass->generic_inst && + !(klass->nested_in && klass->nested_in->gen_params)) return NULL; - if (!System_Reflection_MonoGenericInst) { - System_Reflection_MonoGenericInst = mono_class_from_name ( - mono_defaults.corlib, "System.Reflection", "MonoGenericInst"); - g_assert (System_Reflection_MonoGenericInst); - } + mono_loader_lock (); - if (klass->wastypebuilder && klass->reflection_info) { - MonoReflectionTypeBuilder *tb = klass->reflection_info; + domain = mono_object_domain (type); + + ginst = g_new0 (MonoGenericInst, 1); + + if (!klass->generic_inst) { + ginst->type_argc = type_argc; + ginst->type_argv = types; - ptype = tb->parent; - pklass = mono_class_from_mono_type (ptype->type); + for (i = 0; i < ginst->type_argc; ++i) { + if (!ginst->is_open) + ginst->is_open = mono_class_is_open_constructed_type (types [i]); + } + + ginst->generic_type = &klass->byval_arg; } else { - pklass = klass->parent; - ptype = mono_type_get_object (domain, &pklass->byval_arg); + MonoGenericInst *kginst = klass->generic_inst; + + ginst->type_argc = kginst->type_argc; + ginst->type_argv = g_new0 (MonoType *, ginst->type_argc); + + for (i = 0; i < ginst->type_argc; i++) { + MonoType *t = kginst->type_argv [i]; + + if (t->type == MONO_TYPE_VAR) + t = types [t->data.generic_param->num]; + + if (!ginst->is_open) + ginst->is_open = mono_class_is_open_constructed_type (t); + + ginst->type_argv [i] = t; + } + + ginst->generic_type = kginst->generic_type; } - if (pklass && pklass->generic_inst) - parent = mono_reflection_bind_generic_parameters (ptype, types); - else if (!pklass) - pklass = mono_defaults.object_class; + geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst); + if (geninst) { + g_free (ginst); + mono_loader_unlock (); + return geninst; + } + + ginst->context = g_new0 (MonoGenericContext, 1); + ginst->context->ginst = ginst; geninst = g_new0 (MonoType, 1); geninst->type = MONO_TYPE_GENERICINST; - geninst->data.generic_inst = ginst = g_new0 (MonoGenericInst, 1); - ginst->generic_type = &klass->byval_arg; + geninst->data.generic_inst = ginst; - ginst->type_argc = mono_array_length (types); - ginst->type_argv = g_new0 (MonoType *, ginst->type_argc); - for (i = 0; i < ginst->type_argc; ++i) { - MonoReflectionType *garg = mono_array_get (types, gpointer, i); - ginst->type_argv [i] = garg->type; + if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) { + tb = (MonoReflectionTypeBuilder *) type; + + icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0; + ginst->is_dynamic = TRUE; + } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) { + MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type; + MonoReflectionType *rgt = rgi->generic_type; + + g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder")); + tb = (MonoReflectionTypeBuilder *) rgt; + + icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0; + ginst->is_dynamic = TRUE; + } else + icount = klass->interface_count; + + ginst->ifaces = g_new0 (MonoType *, icount); + ginst->count_ifaces = icount; + + for (i = 0; i < icount; i++) { + MonoReflectionType *itype; + + if (tb) + itype = mono_array_get (tb->interfaces, MonoReflectionType *, i); + else + itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg); + ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types); + if (!ginst->ifaces [i]) + ginst->ifaces [i] = itype->type; } - iklass = mono_class_from_generic (geninst, FALSE); + mono_class_create_generic (ginst); - mono_class_setup_parent (iklass, parent ? parent->klass : pklass); - mono_class_setup_mono_type (iklass); + g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst); - res = (MonoReflectionGenericInst *)mono_object_new (domain, System_Reflection_MonoGenericInst); + mono_loader_unlock (); - res->type.type = iklass->generic_inst; - res->klass = iklass; - res->parent = parent; - res->generic_type = type; + return geninst; +} - return res; +MonoType* +mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types) +{ + MonoClass *klass, *pklass = NULL; + MonoReflectionType *parent = NULL; + MonoType *geninst; + MonoReflectionTypeBuilder *tb = NULL; + MonoGenericInst *ginst; + MonoDomain *domain; + + domain = mono_object_domain (type); + klass = mono_class_from_mono_type (type->type); + + if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) { + tb = (MonoReflectionTypeBuilder *) type; + + if (tb->parent) { + parent = tb->parent; + pklass = mono_class_from_mono_type (parent->type); + } + } else { + pklass = klass->parent; + if (pklass) + parent = mono_type_get_object (domain, &pklass->byval_arg); + } + + geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types); + if (!geninst) + return NULL; + + ginst = geninst->data.generic_inst; + + if (pklass && pklass->generic_inst) + ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types); + + return geninst; } -MonoReflectionInflatedMethod* +MonoReflectionMethod* mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types) { MonoMethod *method, *inflated; MonoReflectionMethodBuilder *mb = NULL; - MonoGenericInst *ginst; + MonoGenericMethod *gmethod; + MonoGenericContext *context; int count, i; MONO_ARCH_SAVE_REGS; @@ -6191,34 +7219,62 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M if (count != mono_array_length (types)) return NULL; - ginst = g_new0 (MonoGenericInst, 1); - ginst->generic_method = method; - ginst->type_argc = count; - ginst->type_argv = g_new0 (MonoType *, count); + gmethod = g_new0 (MonoGenericMethod, 1); + gmethod->mtype_argc = count; + gmethod->mtype_argv = g_new0 (MonoType *, count); for (i = 0; i < count; i++) { MonoReflectionType *garg = mono_array_get (types, gpointer, i); - ginst->type_argv [i] = garg->type; + gmethod->mtype_argv [i] = garg->type; + } + + context = g_new0 (MonoGenericContext, 1); + context->ginst = method->klass->generic_inst; + context->gmethod = gmethod; + + inflated = mono_class_inflate_generic_method (method, context, NULL); + + return mono_method_get_object ( + mono_object_domain (rmethod), inflated, NULL); +} + +static MonoMethod * +inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj) +{ + MonoGenericMethod *gmethod; + MonoGenericInst *ginst; + MonoGenericContext *context; + int i; + + ginst = type->type.type->data.generic_inst; + + gmethod = g_new0 (MonoGenericMethod, 1); + gmethod->reflection_info = obj; + + gmethod->mtype_argc = method->signature->generic_param_count; + gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc); + + for (i = 0; i < gmethod->mtype_argc; i++) { + MonoMethodNormal *mn = (MonoMethodNormal *) method; + MonoGenericParam *gparam = &mn->header->gen_params [i]; + + g_assert (gparam->pklass); + gmethod->mtype_argv [i] = &gparam->pklass->byval_arg; } - inflated = mono_class_inflate_generic_method (method, ginst); + context = g_new0 (MonoGenericContext, 1); + context->ginst = ginst; + context->gmethod = gmethod; - return inflated_method_get_object (mono_object_domain (rmethod), inflated, rmethod, ginst); + return mono_class_inflate_generic_method (method, context, ginst->klass); } -MonoReflectionInflatedMethod* -mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_type, - MonoReflectionGenericInst *reflected_type, - MonoObject *obj) +static MonoMethod * +inflate_method (MonoReflectionGenericInst *type, MonoObject *obj) { - MonoGenericInst *ginst, *type_ginst; - MonoMethod *method, *inflated; - MonoReflectionInflatedMethod *res; + MonoMethod *method; MonoClass *klass; - MONO_ARCH_SAVE_REGS; - - klass = mono_class_from_mono_type (reflected_type->type.type); - type_ginst = reflected_type->type.type->data.generic_inst; + klass = mono_class_from_mono_type (type->type.type); if (!strcmp (obj->vtable->klass->name, "MethodBuilder")) method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj); @@ -6227,83 +7283,138 @@ mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_typ else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod")) method = ((MonoReflectionMethod *) obj)->method; - else if (!strcmp (obj->vtable->klass->name, "MonoInflatedMethod") || - !strcmp (obj->vtable->klass->name, "MonoInflatedCtor")) - method = ((MonoReflectionInflatedMethod *) obj)->rmethod.method; - else + else { + method = NULL; /* prevent compiler warning */ g_assert_not_reached (); + } - ginst = g_new0 (MonoGenericInst, 1); - ginst->generic_method = method; - ginst->generic_type = reflected_type->type.type; - ginst->type_argc = type_ginst->type_argc; - ginst->type_argv = type_ginst->type_argv; + return inflate_mono_method (type, method, obj); +} - ginst->klass = mono_class_from_generic (ginst->generic_type, FALSE); +void +mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, + MonoArray *methods, MonoArray *ctors, + MonoArray *fields, MonoArray *properties, + MonoArray *events) +{ + MonoGenericInst *ginst; + MonoDynamicGenericInst *dginst; + MonoClass *klass, *gklass, *pklass; + int i; - inflated = mono_class_inflate_generic_method (method, ginst); + MONO_ARCH_SAVE_REGS; - res = inflated_method_get_object ( - mono_object_domain (reflected_type), inflated, (MonoReflectionMethod *) obj, ginst); + klass = mono_class_from_mono_type (type->type.type); + ginst = type->type.type->data.generic_inst; - res->declaring_type = declaring_type; - res->reflected_type = reflected_type; + if (ginst->initialized) + return; - return res; -} + dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1); -MonoReflectionInflatedField* -mono_reflection_inflate_field (MonoReflectionGenericInst *declaring_type, - MonoReflectionGenericInst *reflected_type, - MonoObject *obj) -{ - static MonoClass *System_Reflection_MonoInflatedField; - MonoGenericInst *ginst, *type_ginst; - MonoClassField *field, *inflated; - MonoReflectionInflatedField *res; - MonoDomain *domain; - MonoClass *klass; + gklass = mono_class_from_mono_type (ginst->generic_type); + mono_class_init (gklass); - MONO_ARCH_SAVE_REGS; + if (ginst->parent) + pklass = mono_class_from_mono_type (ginst->parent); + else + pklass = gklass->parent; + + mono_class_setup_parent (klass, pklass); + + dginst->count_methods = methods ? mono_array_length (methods) : 0; + dginst->count_ctors = ctors ? mono_array_length (ctors) : 0; + dginst->count_fields = fields ? mono_array_length (fields) : 0; + dginst->count_properties = properties ? mono_array_length (properties) : 0; + dginst->count_events = events ? mono_array_length (events) : 0; - if (!System_Reflection_MonoInflatedField) { - System_Reflection_MonoInflatedField = mono_class_from_name ( - mono_defaults.corlib, "System.Reflection", "MonoInflatedField"); - g_assert (System_Reflection_MonoInflatedField); + dginst->methods = g_new0 (MonoMethod *, dginst->count_methods); + dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors); + dginst->fields = g_new0 (MonoClassField, dginst->count_fields); + dginst->properties = g_new0 (MonoProperty, dginst->count_properties); + dginst->events = g_new0 (MonoEvent, dginst->count_events); + + for (i = 0; i < dginst->count_methods; i++) { + MonoObject *obj = mono_array_get (methods, gpointer, i); + + dginst->methods [i] = inflate_method (type, obj); } - klass = mono_class_from_mono_type (reflected_type->type.type); - type_ginst = reflected_type->type.type->data.generic_inst; + for (i = 0; i < dginst->count_ctors; i++) { + MonoObject *obj = mono_array_get (ctors, gpointer, i); - if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) { - field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj); - } else if (!strcmp (obj->vtable->klass->name, "MonoField")) - field = ((MonoReflectionField *) obj)->field; - else - g_assert_not_reached (); + dginst->ctors [i] = inflate_method (type, obj); + } - ginst = g_new0 (MonoGenericInst, 1); - ginst->generic_type = reflected_type->type.type; - ginst->type_argc = type_ginst->type_argc; - ginst->type_argv = type_ginst->type_argv; - - inflated = g_new0 (MonoClassField, 1); - *inflated = *field; - inflated->type = mono_class_inflate_generic_type (field->type, ginst); - - domain = mono_object_domain (obj); - - res = (MonoReflectionInflatedField *)mono_object_new (domain, System_Reflection_MonoInflatedField); - res->declaring = field; - res->declaring_type = declaring_type; - res->reflected_type = reflected_type; - res->rfield.klass = klass; - res->rfield.field = inflated; - res->rfield.name = mono_string_new (domain, inflated->name); - res->rfield.attrs = inflated->type->attrs; - res->rfield.type = mono_type_get_object (domain, inflated->type); - CACHE_OBJECT (inflated, res, field->parent); - return res; + for (i = 0; i < dginst->count_fields; i++) { + MonoObject *obj = mono_array_get (fields, gpointer, i); + MonoClassField *field; + + if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) + field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj); + else if (!strcmp (obj->vtable->klass->name, "MonoField")) + field = ((MonoReflectionField *) obj)->field; + else { + field = NULL; /* prevent compiler warning */ + g_assert_not_reached (); + } + + dginst->fields [i] = *field; + dginst->fields [i].generic_type = field->type; + dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context); + } + + for (i = 0; i < dginst->count_properties; i++) { + MonoObject *obj = mono_array_get (properties, gpointer, i); + MonoProperty *property = &dginst->properties [i]; + + if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) { + MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj; + + property->parent = klass; + property->attrs = pb->attrs; + property->name = mono_string_to_utf8 (pb->name); + if (pb->get_method) + property->get = inflate_method (type, (MonoObject *) pb->get_method); + if (pb->set_method) + property->set = inflate_method (type, (MonoObject *) pb->set_method); + } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) { + *property = *((MonoReflectionProperty *) obj)->property; + + if (property->get) + property->get = inflate_mono_method (type, property->get, NULL); + if (property->set) + property->set = inflate_mono_method (type, property->set, NULL); + } else + g_assert_not_reached (); + } + + for (i = 0; i < dginst->count_events; i++) { + MonoObject *obj = mono_array_get (events, gpointer, i); + MonoEvent *event = &dginst->events [i]; + + if (!strcmp (obj->vtable->klass->name, "EventBuilder")) { + MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj; + + event->parent = klass; + event->attrs = eb->attrs; + event->name = mono_string_to_utf8 (eb->name); + if (eb->add_method) + event->add = inflate_method (type, (MonoObject *) eb->add_method); + if (eb->remove_method) + event->remove = inflate_method (type, (MonoObject *) eb->remove_method); + } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) { + *event = *((MonoReflectionEvent *) obj)->event; + + if (event->add) + event->add = inflate_mono_method (type, event->add, NULL); + if (event->remove) + event->remove = inflate_mono_method (type, event->remove, NULL); + } else + g_assert_not_reached (); + } + + ginst->initialized = TRUE; } static void @@ -6319,13 +7430,13 @@ ensure_runtime_vtable (MonoClass *klass) ensure_runtime_vtable (klass->parent); num = tb->ctors? mono_array_length (tb->ctors): 0; - num += tb->methods? mono_array_length (tb->methods): 0; + num += tb->num_methods; klass->method.count = num; klass->methods = g_new (MonoMethod*, num); num = tb->ctors? mono_array_length (tb->ctors): 0; for (i = 0; i < num; ++i) klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i)); - num = tb->methods? mono_array_length (tb->methods): 0; + num = tb->num_methods; j = i; for (i = 0; i < num; ++i) klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i)); @@ -6347,7 +7458,7 @@ ensure_runtime_vtable (MonoClass *klass) /* Overrides */ onum = 0; if (tb->methods) { - for (i = 0; i < mono_array_length (tb->methods); ++i) { + for (i = 0; i < tb->num_methods; ++i) { MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i); if (mb->override_method) @@ -6359,7 +7470,7 @@ ensure_runtime_vtable (MonoClass *klass) if (tb->methods) { onum = 0; - for (i = 0; i < mono_array_length (tb->methods); ++i) { + for (i = 0; i < tb->num_methods; ++i) { MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i); if (mb->override_method) { @@ -6389,7 +7500,7 @@ typebuilder_setup_fields (MonoClass *klass) int i; guint32 len, idx; - klass->field.count = tb->fields? mono_array_length (tb->fields): 0; + klass->field.count = tb->num_fields; klass->field.first = 0; klass->field.last = klass->field.count; @@ -6447,6 +7558,7 @@ typebuilder_setup_properties (MonoClass *klass) klass->properties = g_new0 (MonoProperty, klass->property.count); for (i = 0; i < klass->property.count; ++i) { pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i); + klass->properties [i].parent = klass; klass->properties [i].attrs = pb->attrs; klass->properties [i].name = mono_string_to_utf8 (pb->name); if (pb->get_method) @@ -6456,6 +7568,38 @@ typebuilder_setup_properties (MonoClass *klass) } } +MonoReflectionEvent * +mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb) +{ + MonoEvent *event = g_new0 (MonoEvent, 1); + MonoClass *klass; + int j; + + klass = my_mono_class_from_mono_type (tb->type.type); + + event->parent = klass; + event->attrs = eb->attrs; + event->name = mono_string_to_utf8 (eb->name); + if (eb->add_method) + event->add = eb->add_method->mhandle; + if (eb->remove_method) + event->remove = eb->remove_method->mhandle; + if (eb->raise_method) + event->raise = eb->raise_method->mhandle; + + if (eb->other_methods) { + event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods)); + for (j = 0; j < mono_array_length (eb->other_methods); ++j) { + MonoReflectionMethodBuilder *mb = + mono_array_get (eb->other_methods, + MonoReflectionMethodBuilder*, j); + event->other [j] = mb->mhandle; + } + } + + return mono_event_get_object (mono_object_domain (tb), klass, event); +} + static void typebuilder_setup_events (MonoClass *klass) { @@ -6470,6 +7614,7 @@ typebuilder_setup_events (MonoClass *klass) klass->events = g_new0 (MonoEvent, klass->event.count); for (i = 0; i < klass->event.count; ++i) { eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i); + klass->events [i].parent = klass; klass->events [i].attrs = eb->attrs; klass->events [i].name = mono_string_to_utf8 (eb->name); if (eb->add_method) @@ -6509,7 +7654,6 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) * nested_classes */ klass->flags = tb->attrs; - klass->element_class = klass; if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run) /* No need to fully construct the type */ @@ -6545,38 +7689,29 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) return res; } -MonoReflectionType * -mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, guint32 index, MonoReflectionGenericParam *gparam) +void +mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam) { - MonoClass *klass; - MonoImage *image; MonoGenericParam *param; - int count, i; - - param = gparam->param = g_new0 (MonoGenericParam, 1); + MonoImage *image; - if (mb) - tb = (MonoReflectionTypeBuilder *) mb->type; + MONO_ARCH_SAVE_REGS; - image = (MonoImage*)tb->module->dynamic_image; + param = g_new0 (MonoGenericParam, 1); param->method = NULL; param->name = mono_string_to_utf8 (gparam->name); - param->num = index; - - count = gparam->constraints ? mono_array_length (gparam->constraints) : 0; - param->constraints = g_new0 (MonoClass *, count + 1); - for (i = 0; i < count; i++) { - MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i); - - param->constraints [i] = mono_class_from_mono_type (constraint->type); - } + param->num = gparam->index; - klass = mono_class_from_generic_parameter (param, image, mb != NULL); + image = &gparam->tbuilder->module->dynamic_image->image; + mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL); - gparam->type = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg); + param->pklass->reflection_info = gparam; - return gparam->type; + gparam->type.type = g_new0 (MonoType, 1); + gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR; + gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC; + gparam->type.type->data.generic_param = param; } MonoArray * @@ -6636,6 +7771,42 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig) return result; } +void +mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb) +{ + ReflectionMethodBuilder rmb; + MonoMethodSignature *sig; + int i; + + sig = dynamic_method_to_signature (mb); + + reflection_methodbuilder_from_dynamic_method (&rmb, mb); + + /* + * Resolve references. + */ + rmb.nrefs = mb->nrefs; + rmb.refs = g_new0 (gpointer, mb->nrefs + 1); + for (i = 0; i < mb->nrefs; ++i) { + gpointer ref = resolve_object (mb->module->image, + mono_array_get (mb->refs, MonoObject*, i)); + if (!ref) { + g_free (rmb.refs); + mono_raise_exception (mono_get_exception_type_load (NULL)); + return; + } + rmb.refs [i] = ref; + } + + /* FIXME: class */ + mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig); + + g_free (rmb.refs); + + /* ilgen is no longer needed */ + mb->ilgen = NULL; +} + /** * mono_reflection_lookup_dynamic_token: * @@ -6647,11 +7818,18 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token) { MonoDynamicImage *assembly = (MonoDynamicImage*)image; MonoObject *obj; - gpointer result; obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token)); g_assert (obj); + return resolve_object (image, obj); +} + +static gpointer +resolve_object (MonoImage *image, MonoObject *obj) +{ + gpointer result = NULL; + if (strcmp (obj->vtable->klass->name, "String") == 0) { result = mono_string_intern ((MonoString*)obj); g_assert (result); @@ -6768,8 +7946,3 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token) } return result; } - - - - -