-
/*
* reflection.c: Routines for creating an image at runtime.
*
MonoArray *return_modopt;
MonoArray *param_modreq;
MonoArray *param_modopt;
+ MonoArray *permissions;
MonoMethod *mhandle;
guint32 nrefs;
gpointer *refs;
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)
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) {
}
}
+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)
{
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);
*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)
{
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;
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);
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... */
}
}
+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.
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;
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;
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;
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;
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)
{
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) {
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) {
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) {
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 ++;
/*
* 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) {
}
}
+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)
{
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
param = gparam->type.type->data.generic_param;
values [MONO_GENERICPARAM_OWNER] = owner;
- values [MONO_GENERICPARAM_FLAGS] = param->flags;
+ 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
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];
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;
* 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 ||
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:
}
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];
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);
}
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:
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);
}
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;
}
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);
}
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;
}
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);
token = MONO_TOKEN_MEMBER_REF | table->next_idx;
table->next_idx ++;
-
+ g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
return token;
}
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;
}
static void
-mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb,
+mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
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);
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);
}
}
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)
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) {
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 ();
}
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 ();
}
- break;
- default:
- g_error ("got unexpected table 0x%02x in fixup", target [3]);
+ break;
+ default:
+ g_error ("got unexpected table 0x%02x in fixup", target [3]);
+ }
+ target [0] = idx & 0xff;
+ target [1] = (idx >> 8) & 0xff;
+ target [2] = (idx >> 16) & 0xff;
+ }
+}
+
+/*
+ * 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;
+ }
}
- target [0] = idx & 0xff;
- target [1] = (idx >> 8) & 0xff;
- target [2] = (idx >> 16) & 0xff;
}
}
static void
-assembly_add_resource (MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
+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 (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
{
MonoDynamicTable *table;
guint32 *values;
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
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.
MonoReflectionAssemblyBuilder *assemblyb;
MonoDomain *domain;
guint32 *values;
- char *name;
int i;
- guint32 module_index;
assemblyb = moduleb->assemblyb;
assembly = moduleb->dynamic_image;
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 ++;
- 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);
- }
- }
- }
- }
+ mono_image_emit_manifest (moduleb);
}
table = &assembly->tables [MONO_TABLE_TYPEDEF];
/* fixup tokens */
mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
+ fixup_cattrs (assembly);
}
/*
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) {
token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
}
else if (strcmp (klass->name, "MonoType") == 0 ||
- strcmp (klass->name, "MonoGenericParam") == 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));
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;
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) {
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;
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);
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
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++;
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
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;
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 */
*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 ();
}
#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.
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;
}
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
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? */
memset (assembly, 0, sizeof (MonoAssemblyName));
assembly->name = p;
assembly->culture = "";
-
+ assembly->public_tok_value = NULL;
+
while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
p++;
found_sep = 0;
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 != '.')
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;
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++;
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;
}
{
MonoType *type;
MonoTypeNameParse info;
+ MonoAssembly *assembly;
/*g_print ("requested type %s\n", str);*/
if (!mono_reflection_parse_type (name, &info)) {
}
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;
}
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) {
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);
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);
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)
{
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];
{
MonoClass *klass;
MonoArray *result;
- MonoCustomAttrInfo *cinfo;
+ MonoCustomAttrInfo *cinfo = NULL;
MONO_ARCH_SAVE_REGS;
} 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);
} 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);
}
}
}
-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)
{
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);
MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
klass->gen_params [i] = *gparam->type.type->data.generic_param;
}
-
- ensure_runtime_vtable (klass);
}
/*
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;
static MonoMethod*
reflection_methodbuilder_to_mono_method (MonoClass *klass,
- ReflectionMethodBuilder *rmb,
- MonoMethodSignature *sig)
+ ReflectionMethodBuilder *rmb,
+ MonoMethodSignature *sig)
{
MonoMethod *m;
MonoMethodNormal *pm;
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 = NULL;
/* Parameter names */
- if (rmb->parameters) {
+ if (rmb->pinfo) {
if (!method_aux)
method_aux = g_new0 (MonoReflectionMethodAux, 1);
- method_aux->param_names = g_new0 (char *, m->signature->param_count);
- for (i = 0; i < m->signature->param_count; ++i) {
+ 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);
+ }
}
}
}
method_aux->param_marshall = specs;
}
- if (klass->image->assembly->dynamic && method_aux)
+ if (klass->image->dynamic && method_aux)
mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
return m;
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;
- MonoArray *ifaces = NULL;
- MonoReflectionType *ptype = NULL;
- MonoClass *klass, *iklass, *pklass = NULL;
- MonoReflectionGenericInst *res, *parent = NULL;
- MonoReflectionTypeBuilder *tb = 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);
- }
-
- if (klass->wastypebuilder && klass->reflection_info) {
- tb = klass->reflection_info;
-
- ptype = tb->parent;
- if (ptype)
- pklass = mono_class_from_mono_type (ptype->type);
- } else {
- pklass = klass->parent;
- if (pklass)
- ptype = mono_type_get_object (domain, &pklass->byval_arg);
- }
-
- if (pklass && pklass->generic_inst)
- parent = mono_reflection_bind_generic_parameters (ptype, types);
- else if (!pklass) {
- int icount;
-
- pklass = mono_defaults.object_class;
-
- icount = klass->interface_count;
- ifaces = mono_array_new (domain, System_Reflection_MonoGenericInst, icount);
+ mono_loader_lock ();
- for (i = 0; i < icount; i++) {
- MonoReflectionGenericInst *iface;
- MonoReflectionType *itype;
-
- if (tb)
- itype = mono_array_get (tb->interfaces, gpointer, i);
- else
- itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
- iface = mono_reflection_bind_generic_parameters (itype, types);
-
- mono_array_set (ifaces, gpointer, i, iface);
- }
- }
+ domain = mono_object_domain (type);
- geninst = g_new0 (MonoType, 1);
- geninst->type = MONO_TYPE_GENERICINST;
- geninst->data.generic_inst = ginst = g_new0 (MonoGenericInst, 1);
+ ginst = g_new0 (MonoGenericInst, 1);
- if (klass->gen_params) {
- ginst->type_argc = mono_array_length (types);
- ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
+ if (!klass->generic_inst) {
+ ginst->type_argc = type_argc;
+ ginst->type_argv = types;
for (i = 0; i < ginst->type_argc; ++i) {
- MonoReflectionType *garg = mono_array_get (types, gpointer, i);
-
- ginst->type_argv [i] = garg->type;
-
if (!ginst->is_open)
- ginst->is_open = mono_class_is_open_constructed_type (garg->type);
+ ginst->is_open = mono_class_is_open_constructed_type (types [i]);
}
ginst->generic_type = &klass->byval_arg;
} else {
- MonoGenericInst *kginst = klass->generic_inst->data.generic_inst;
+ 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) {
- int num = t->data.generic_param->num;
- MonoReflectionType *garg = mono_array_get (types, gpointer, num);
-
- t = garg->type;
- }
+ 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->generic_type = kginst->generic_type;
}
- iklass = mono_class_from_generic (geninst, FALSE);
+ 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;
- mono_class_setup_parent (iklass, parent ? parent->klass : pklass);
- mono_class_setup_mono_type (iklass);
+ geninst = g_new0 (MonoType, 1);
+ geninst->type = MONO_TYPE_GENERICINST;
+ geninst->data.generic_inst = ginst;
- res = (MonoReflectionGenericInst *)mono_object_new (domain, System_Reflection_MonoGenericInst);
+ if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
+ tb = (MonoReflectionTypeBuilder *) type;
- res->type.type = iklass->generic_inst;
- res->klass = iklass;
- res->parent = parent;
- res->generic_type = type;
- res->interfaces = ifaces;
+ 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;
- return res;
+ 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;
+ }
+
+ mono_class_create_generic (ginst);
+
+ g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
+
+ mono_loader_unlock ();
+
+ return geninst;
+}
+
+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;
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;
}
- inflated = mono_class_inflate_generic_method (method, ginst);
+ context = g_new0 (MonoGenericContext, 1);
+ context->ginst = method->klass->generic_inst;
+ context->gmethod = gmethod;
- return inflated_method_get_object (mono_object_domain (rmethod), inflated, rmethod, ginst);
+ inflated = mono_class_inflate_generic_method (method, context, NULL);
+
+ return mono_method_get_object (
+ mono_object_domain (rmethod), inflated, NULL);
}
-MonoReflectionInflatedMethod*
-mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_type,
- MonoReflectionGenericInst *reflected_type,
- MonoObject *obj)
+static MonoMethod *
+inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
{
- MonoGenericInst *ginst, *type_ginst;
- MonoMethod *method, *inflated;
- MonoReflectionInflatedMethod *res;
- MonoClass *klass;
+ MonoGenericMethod *gmethod;
+ MonoGenericInst *ginst;
+ MonoGenericContext *context;
+ int i;
- MONO_ARCH_SAVE_REGS;
+ 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;
+ }
+
+ context = g_new0 (MonoGenericContext, 1);
+ context->ginst = ginst;
+ context->gmethod = gmethod;
+
+ return mono_class_inflate_generic_method (method, context, ginst->klass);
+}
- klass = mono_class_from_mono_type (reflected_type->type.type);
- type_ginst = reflected_type->type.type->data.generic_inst;
+static MonoMethod *
+inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
+{
+ MonoMethod *method;
+ MonoClass *klass;
+
+ klass = mono_class_from_mono_type (type->type.type);
if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
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;
- ginst->is_open = type_ginst->is_open;
+ return inflate_mono_method (type, method, obj);
+}
+
+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;
+
+ MONO_ARCH_SAVE_REGS;
+
+ klass = mono_class_from_mono_type (type->type.type);
+ ginst = type->type.type->data.generic_inst;
- ginst->klass = mono_class_from_generic (ginst->generic_type, FALSE);
+ if (ginst->initialized)
+ return;
+
+ dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
- if (type_ginst->is_open)
- inflated = method;
+ gklass = mono_class_from_mono_type (ginst->generic_type);
+ mono_class_init (gklass);
+
+ if (ginst->parent)
+ pklass = mono_class_from_mono_type (ginst->parent);
else
- inflated = mono_class_inflate_generic_method (method, ginst);
+ pklass = gklass->parent;
- res = inflated_method_get_object (
- mono_object_domain (reflected_type), inflated, (MonoReflectionMethod *) obj, ginst);
+ mono_class_setup_parent (klass, pklass);
- res->declaring_type = declaring_type;
- res->reflected_type = reflected_type;
+ 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;
- return res;
-}
+ 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);
-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;
+ for (i = 0; i < dginst->count_methods; i++) {
+ MonoObject *obj = mono_array_get (methods, gpointer, i);
- MONO_ARCH_SAVE_REGS;
+ dginst->methods [i] = inflate_method (type, obj);
+ }
- if (!System_Reflection_MonoInflatedField) {
- System_Reflection_MonoInflatedField = mono_class_from_name (
- mono_defaults.corlib, "System.Reflection", "MonoInflatedField");
- g_assert (System_Reflection_MonoInflatedField);
+ for (i = 0; i < dginst->count_ctors; i++) {
+ MonoObject *obj = mono_array_get (ctors, gpointer, i);
+
+ dginst->ctors [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_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
- g_assert_not_reached ();
+ 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 ();
+ }
- 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;
+ 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
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)
}
}
+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)
{
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)
* nested_classes
*/
klass->flags = tb->attrs;
- klass->element_class = klass;
if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
/* No need to fully construct the type */
return res;
}
-MonoReflectionGenericParam *
-mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, MonoString *name, guint32 index)
-{
- static MonoClass *System_Reflection_MonoGenericParam;
- MonoImage *image;
- MonoGenericParam *param;
- MonoReflectionGenericParam *res;
- MonoDomain *domain;
-
- if (!System_Reflection_MonoGenericParam) {
- System_Reflection_MonoGenericParam = mono_class_from_name (
- mono_defaults.corlib, "System.Reflection", "MonoGenericParam");
- g_assert (System_Reflection_MonoGenericParam);
- }
-
- param = g_new0 (MonoGenericParam, 1);
-
- if (mb)
- tb = (MonoReflectionTypeBuilder *) mb->type;
-
- domain = mono_object_domain (tb);
- image = (MonoImage*)tb->module->dynamic_image;
-
- param->method = NULL;
- param->name = mono_string_to_utf8 (name);
- param->num = index;
-
- res = (MonoReflectionGenericParam *)mono_object_new (domain, System_Reflection_MonoGenericParam);
- res->type.type = g_new0 (MonoType, 1);
- res->type.type->type = mb ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
- res->type.type->data.generic_param = param;
-
- res->refobj = mb ? (MonoObject *) mb : (MonoObject *) tb;
- res->index = index;
- res->name = name;
-
- return res;
-}
-
void
mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
{
MonoGenericParam *param;
- MonoReflectionMethodBuilder *mb = NULL;
- MonoReflectionTypeBuilder *tb;
MonoImage *image;
- int count, i;
- param = gparam->type.type->data.generic_param;
- 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);
+ MONO_ARCH_SAVE_REGS;
- param->constraints [i] = mono_class_from_mono_type (constraint->type);
- }
+ param = g_new0 (MonoGenericParam, 1);
- if (!strcmp (gparam->refobj->vtable->klass->name, "MethodBuilder")) {
- mb = (MonoReflectionMethodBuilder *) gparam->refobj;
- tb = (MonoReflectionTypeBuilder *) mb->type;
- } else
- tb = (MonoReflectionTypeBuilder *) gparam->refobj;
+ param->method = NULL;
+ param->name = mono_string_to_utf8 (gparam->name);
+ param->num = gparam->index;
- image = (MonoImage*)tb->module->dynamic_image;
+ image = &gparam->tbuilder->module->dynamic_image->image;
+ mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
- param->pklass = mono_class_from_generic_parameter (param, image, mb != NULL);
+ param->pklass->reflection_info = gparam;
- gparam->initialized = TRUE;
+ 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 *
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));
+ mono_array_get (mb->refs, MonoObject*, i));
if (!ref) {
g_free (rmb.refs);
mono_raise_exception (mono_get_exception_type_load (NULL));
static gpointer
resolve_object (MonoImage *image, MonoObject *obj)
{
- gpointer result;
+ gpointer result = NULL;
if (strcmp (obj->vtable->klass->name, "String") == 0) {
result = mono_string_intern ((MonoString*)obj);