Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mono/metadata/reflection.c')
-rw-r--r--mono/metadata/reflection.c6747
1 files changed, 5845 insertions, 902 deletions
diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c
index c2287c8d20a..0cb30fdac88 100644
--- a/mono/metadata/reflection.c
+++ b/mono/metadata/reflection.c
@@ -1,4 +1,3 @@
-
/*
* reflection.c: Routines for creating an image at runtime.
*
@@ -9,24 +8,29 @@
*
*/
#include <config.h>
+#include "mono/utils/mono-digest.h"
#include "mono/metadata/reflection.h"
#include "mono/metadata/tabledefs.h"
+#include "mono/metadata/metadata-internals.h"
+#include "mono/metadata/class-internals.h"
#include "mono/metadata/tokentype.h"
-#include "mono/metadata/appdomain.h"
+#include "mono/metadata/domain-internals.h"
#include "mono/metadata/opcodes.h"
+#include "mono/metadata/assembly.h"
+#include "mono/metadata/object-internals.h"
+#include <mono/metadata/exception.h>
#include <stdio.h>
#include <glib.h>
#include <errno.h>
#include <time.h>
#include <string.h>
+#include <ctype.h>
#include "image.h"
#include "cil-coff.h"
#include "rawbuffer.h"
#include "mono-endian.h"
#include "private.h"
-#if HAVE_BOEHM_GC
-#include <gc/gc.h>
-#endif
+#include <mono/os/gc_wrapper.h>
#define TEXT_OFFSET 512
#define CLI_H_SIZE 136
@@ -38,7 +42,9 @@ typedef struct {
MonoReflectionILGen *ilgen;
MonoReflectionType *rtype;
MonoArray *parameters;
+ MonoArray *generic_params;
MonoArray *pinfo;
+ MonoArray *opt_types;
guint32 attrs;
guint32 iattrs;
guint32 call_conv;
@@ -47,8 +53,24 @@ 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;
+ /* for PInvoke */
+ int charset, lasterr, native_cc;
+ MonoString *dll, *dllentry;
} ReflectionMethodBuilder;
+typedef struct {
+ guint32 owner;
+ MonoReflectionGenericParam *gparam;
+} GenericParamTableEntry;
+
const unsigned char table_sizes [64] = {
MONO_MODULE_SIZE,
MONO_TYPEREF_SIZE,
@@ -92,21 +114,83 @@ const unsigned char table_sizes [64] = {
MONO_EXP_TYPE_SIZE,
MONO_MANIFEST_SIZE,
MONO_NESTED_CLASS_SIZE,
- 0 /* 0x2A */
+
+ MONO_GENERICPARAM_SIZE, /* 0x2A */
+ MONO_METHODSPEC_SIZE,
+ MONO_GENPARCONSTRAINT_SIZE,
+
+ 0 /* 0x2D */
};
-static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
-static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
-static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
+/**
+ * These macros can be used to allocate long living atomic data so it won't be
+ * tracked by the garbage collector. We use libgc because it's apparently faster
+ * than g_malloc.
+ */
+#ifdef HAVE_BOEHM_GC
+#define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
+#define FREE_ATOMIC(ptr)
+#define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
+#else
+#define ALLOC_ATOMIC(size) g_malloc (size)
+#define FREE_ATOMIC(ptr) g_free (ptr)
+#define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
+#endif
+
+static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
+static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
+static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
+static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
+static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
+static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
+static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
+static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
+static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
+static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
+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 get_default_param_value_blobs (MonoMethod *method, char **blobs);
+static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
+
static void
alloc_table (MonoDynamicTable *table, guint nrows)
{
table->rows = nrows;
g_assert (table->columns);
- table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
+ if (nrows + 1 >= table->alloc_rows) {
+ while (nrows + 1 >= table->alloc_rows) {
+ if (table->alloc_rows == 0)
+ table->alloc_rows = 16;
+ else
+ table->alloc_rows *= 2;
+ }
+
+ if (table->values)
+ table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
+ else
+ table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
+ }
}
+static void
+make_room_in_stream (MonoDynamicStream *stream, int size)
+{
+ while (stream->alloc_size <= size) {
+ if (stream->alloc_size < 4096)
+ stream->alloc_size = 4096;
+ else
+ stream->alloc_size *= 2;
+ }
+ if (stream->data)
+ stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
+ else
+ stream->data = ALLOC_ATOMIC (stream->alloc_size);
+}
+
static guint32
string_heap_insert (MonoDynamicStream *sh, const char *str)
{
@@ -119,10 +203,9 @@ string_heap_insert (MonoDynamicStream *sh, const char *str)
len = strlen (str) + 1;
idx = sh->index;
- if (idx + len > sh->alloc_size) {
- sh->alloc_size += len + 4096;
- sh->data = g_realloc (sh->data, sh->alloc_size);
- }
+ if (idx + len > sh->alloc_size)
+ make_room_in_stream (sh, idx + len);
+
/*
* We strdup the string even if we already copy them in sh->data
* so that the string pointers in the hash remain valid even if
@@ -139,7 +222,7 @@ string_heap_init (MonoDynamicStream *sh)
{
sh->index = 0;
sh->alloc_size = 4096;
- sh->data = g_malloc (4096);
+ sh->data = ALLOC_ATOMIC (4096);
sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
string_heap_insert (sh, "");
}
@@ -148,7 +231,7 @@ string_heap_init (MonoDynamicStream *sh)
static void
string_heap_free (MonoDynamicStream *sh)
{
- g_free (sh->data);
+ FREE_ATOMIC (sh->data);
g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
g_hash_table_destroy (sh->hash);
}
@@ -158,10 +241,8 @@ static guint32
mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
{
guint32 idx;
- if (stream->alloc_size < stream->index + len) {
- stream->alloc_size += len + 4096;
- stream->data = g_realloc (stream->data, stream->alloc_size);
- }
+ if (stream->alloc_size < stream->index + len)
+ make_room_in_stream (stream, stream->index + len);
memcpy (stream->data + stream->index, data, len);
idx = stream->index;
stream->index += len;
@@ -176,10 +257,8 @@ static guint32
mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
{
guint32 idx;
- if (stream->alloc_size < stream->index + len) {
- stream->alloc_size += len + 4096;
- stream->data = g_realloc (stream->data, stream->alloc_size);
- }
+ if (stream->alloc_size < stream->index + len)
+ make_room_in_stream (stream, stream->index + len);
memset (stream->data + stream->index, 0, len);
idx = stream->index;
stream->index += len;
@@ -197,8 +276,211 @@ stream_data_align (MonoDynamicStream *stream)
mono_image_add_stream_data (stream, buf, 4 - count);
}
+static int
+mono_blob_entry_hash (const char* str)
+{
+ guint len, h;
+ const char *end;
+ len = mono_metadata_decode_blob_size (str, &str);
+ if (len > 0) {
+ end = str + len;
+ h = *str;
+ for (str += 1; str < end; str++)
+ h = (h << 5) - h + *str;
+ return h;
+ } else {
+ return 0;
+ }
+}
+
+static gboolean
+mono_blob_entry_equal (const char *str1, const char *str2) {
+ int len, len2;
+ const char *end1;
+ const char *end2;
+ len = mono_metadata_decode_blob_size (str1, &end1);
+ len2 = mono_metadata_decode_blob_size (str2, &end2);
+ if (len != len2)
+ return 0;
+ return memcmp (end1, end2, len) == 0;
+}
+
+static guint32
+add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
+{
+ guint32 idx;
+ char *copy;
+ gpointer oldkey, oldval;
+
+ copy = ALLOC_ATOMIC (s1+s2);
+ memcpy (copy, b1, s1);
+ memcpy (copy + s1, b2, s2);
+ if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
+ FREE_ATOMIC (copy);
+ idx = GPOINTER_TO_UINT (oldval);
+ } else {
+ idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
+ mono_image_add_stream_data (&assembly->blob, b2, s2);
+ mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
+ }
+ 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) {
+ switch (type->type) {
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_GENERICINST:
+ return mono_class_from_mono_type (type);
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ g_assert (type->data.generic_param->pklass);
+ return type->data.generic_param->pklass;
+ default:
+ /* should be always valid when we reach this case... */
+ return type->data.klass;
+ }
+}
+
+static MonoClass *
+default_class_from_mono_type (MonoType *type)
+{
+ switch (type->type) {
+ case MONO_TYPE_OBJECT:
+ return mono_defaults.object_class;
+ case MONO_TYPE_VOID:
+ return mono_defaults.void_class;
+ case MONO_TYPE_BOOLEAN:
+ return mono_defaults.boolean_class;
+ case MONO_TYPE_CHAR:
+ return mono_defaults.char_class;
+ case MONO_TYPE_I1:
+ return mono_defaults.sbyte_class;
+ case MONO_TYPE_U1:
+ return mono_defaults.byte_class;
+ case MONO_TYPE_I2:
+ return mono_defaults.int16_class;
+ case MONO_TYPE_U2:
+ return mono_defaults.uint16_class;
+ case MONO_TYPE_I4:
+ return mono_defaults.int32_class;
+ case MONO_TYPE_U4:
+ return mono_defaults.uint32_class;
+ case MONO_TYPE_I:
+ return mono_defaults.int_class;
+ case MONO_TYPE_U:
+ return mono_defaults.uint_class;
+ case MONO_TYPE_I8:
+ return mono_defaults.int64_class;
+ case MONO_TYPE_U8:
+ return mono_defaults.uint64_class;
+ case MONO_TYPE_R4:
+ return mono_defaults.single_class;
+ case MONO_TYPE_R8:
+ return mono_defaults.double_class;
+ case MONO_TYPE_STRING:
+ return mono_defaults.string_class;
+ default:
+ g_warning ("implement me 0x%02x\n", type->type);
+ g_assert_not_reached ();
+ }
+
+ return NULL;
+}
+
+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 (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
+encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
{
if (!type) {
g_assert_not_reached ();
@@ -230,32 +512,40 @@ encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endb
mono_metadata_encode_value (type->type, p, &p);
break;
case MONO_TYPE_PTR:
- case MONO_TYPE_SZARRAY:
mono_metadata_encode_value (type->type, p, &p);
encode_type (assembly, type->data.type, p, &p);
break;
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_CLASS:
+ case MONO_TYPE_SZARRAY:
mono_metadata_encode_value (type->type, p, &p);
- mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
+ encode_type (assembly, &type->data.klass->byval_arg, p, &p);
break;
-#if 0
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS: {
MonoClass *k = mono_class_from_mono_type (type);
mono_metadata_encode_value (type->type, p, &p);
- /* ensure only non-byref gets passed to mono_image_typedef_or_ref() */
+ /*
+ * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
+ * otherwise two typerefs could point to the same type, leading to
+ * verification errors.
+ */
mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
break;
}
-#endif
case MONO_TYPE_ARRAY:
mono_metadata_encode_value (type->type, p, &p);
- encode_type (assembly, type->data.array->type, p, &p);
+ encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
mono_metadata_encode_value (type->data.array->rank, p, &p);
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:
+ 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);
+ mono_metadata_encode_value (type->data.generic_param->num, p, &p);
+ break;
default:
g_error ("need to encode type %x", type->type);
}
@@ -263,7 +553,7 @@ encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endb
}
static void
-encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
+encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
{
if (!type) {
mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
@@ -278,18 +568,133 @@ encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type,
}
+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
-method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
+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;
+ if (sig->sentinelpos >= 0)
+ size++;
+
+ return size;
+}
+
+static guint32
+method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
{
char *buf;
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;
-
+
+ if (!assembly->save)
+ return 0;
+
p = buf = g_malloc (size);
/*
* FIXME: vararg, explicit_this, differenc call_conv values...
@@ -297,22 +702,28 @@ method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig
*p = sig->call_convention;
if (sig->hasthis)
*p |= 0x20; /* hasthis */
+ if (sig->generic_param_count)
+ *p |= 0x10; /* generic */
p++;
+ if (sig->generic_param_count)
+ mono_metadata_encode_value (sig->generic_param_count, p, &p);
mono_metadata_encode_value (nparams, p, &p);
encode_type (assembly, sig->ret, p, &p);
- for (i = 0; i < nparams; ++i)
+ for (i = 0; i < nparams; ++i) {
+ if (i == sig->sentinelpos)
+ *p++ = MONO_TYPE_SENTINEL;
encode_type (assembly, sig->params [i], p, &p);
+ }
/* store length */
g_assert (p - buf < size);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
static guint32
-method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
+method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
{
/*
* FIXME: reuse code from method_encode_signature().
@@ -321,11 +732,13 @@ method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethod
char *p;
int i;
guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
- guint32 size = 10 + nparams * 10;
+ guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
+ guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
+ guint32 size = 21 + nparams * 20 + notypes * 20;
guint32 idx;
char blob_size [6];
char *b = blob_size;
-
+
p = buf = g_malloc (size);
/* LAMESPEC: all the call conv spec is foobared */
*p = mb->call_conv & 0x60; /* has-this, explicit-this */
@@ -333,24 +746,46 @@ method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethod
*p |= 0x5; /* vararg */
if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
*p |= 0x20; /* hasthis */
+ if (ngparams)
+ *p |= 0x10; /* generic */
p++;
- mono_metadata_encode_value (nparams, p, &p);
+ if (ngparams)
+ mono_metadata_encode_value (ngparams, p, &p);
+ mono_metadata_encode_value (nparams + notypes, 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);
+ }
+ if (notypes)
+ *p++ = MONO_TYPE_SENTINEL;
+ for (i = 0; i < notypes; ++i) {
+ MonoReflectionType *pt;
+
+ pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
encode_reflection_type (assembly, pt, p, &p);
}
+
/* store length */
g_assert (p - buf < size);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
static guint32
-encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
+encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
{
MonoDynamicTable *table;
guint32 *values;
@@ -374,12 +809,15 @@ encode_locals (MonoDynamicAssembly *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);
mono_metadata_encode_value (p-buf, b, &b);
- sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
@@ -388,7 +826,70 @@ encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
}
static guint32
-method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
+method_count_clauses (MonoReflectionILGen *ilgen)
+{
+ guint32 num_clauses = 0;
+ int i;
+
+ MonoILExceptionInfo *ex_info;
+ for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
+ ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
+ if (ex_info->handlers)
+ num_clauses += mono_array_length (ex_info->handlers);
+ else
+ num_clauses++;
+ }
+
+ return num_clauses;
+}
+
+static MonoExceptionClause*
+method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
+{
+ MonoExceptionClause *clauses;
+ MonoExceptionClause *clause;
+ MonoILExceptionInfo *ex_info;
+ MonoILExceptionBlock *ex_block;
+ guint32 finally_start;
+ int i, j, clause_index;;
+
+ clauses = g_new0 (MonoExceptionClause, num_clauses);
+
+ clause_index = 0;
+ for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
+ ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
+ finally_start = ex_info->start + ex_info->len;
+ g_assert (ex_info->handlers);
+ for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
+ ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
+ clause = &(clauses [clause_index]);
+
+ clause->flags = ex_block->type;
+ clause->try_offset = ex_info->start;
+
+ if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
+ clause->try_len = finally_start - ex_info->start;
+ else
+ clause->try_len = ex_info->len;
+ clause->handler_offset = ex_block->start;
+ clause->handler_len = ex_block->len;
+ if (ex_block->extype) {
+ clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
+ } else {
+ /* FIXME: handle filters */
+ clause->data.filter_offset = 0;
+ }
+ finally_start = ex_block->start + ex_block->len;
+
+ clause_index ++;
+ }
+ }
+
+ return clauses;
+}
+
+static guint32
+method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
{
char flags = 0;
guint32 idx;
@@ -405,10 +906,8 @@ method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
guint32 header_size = 12;
MonoArray *code;
- if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
- (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
- (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
- (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
+ if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
+ (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
return 0;
/*if (mb->name)
@@ -418,22 +917,25 @@ method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
code_size = mb->ilgen->code_len;
max_stack = mb->ilgen->max_stack;
num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
- if (mb->ilgen->ex_handlers) {
- MonoILExceptionInfo *ex_info;
- for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
- ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
- if (ex_info->handlers)
- num_exception += mono_array_length (ex_info->handlers);
- else
- num_exception++;
- }
- }
+ if (mb->ilgen->ex_handlers)
+ num_exception = method_count_clauses (mb->ilgen);
} else {
code = mb->code;
+ 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... */
}
+ stream_data_align (&assembly->code);
+
/* check for exceptions, maxstack, locals */
maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
if (maybe_small) {
@@ -479,7 +981,6 @@ fat_header:
mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
if (num_exception) {
unsigned char sheader [4];
- MonoExceptionClause clause;
MonoILExceptionInfo * ex_info;
MonoILExceptionBlock * ex_block;
int j;
@@ -487,7 +988,8 @@ fat_header:
stream_data_align (&assembly->code);
/* always use fat format for now */
sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
- num_exception *= sizeof (MonoExceptionClause);
+ num_exception *= 6 * sizeof (guint32);
+ num_exception += 4; /* include the size of the header */
sheader [1] = num_exception & 0xff;
sheader [2] = (num_exception >> 8) & 0xff;
sheader [3] = (num_exception >> 16) & 0xff;
@@ -499,23 +1001,37 @@ fat_header:
if (ex_info->handlers) {
int finally_start = ex_info->start + ex_info->len;
for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
+ guint32 val;
ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
- clause.flags = GUINT32_TO_LE (ex_block->type);
- clause.try_offset = GUINT32_TO_LE (ex_info->start);
+ /* the flags */
+ val = GUINT32_TO_LE (ex_block->type);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /* try offset */
+ val = GUINT32_TO_LE (ex_info->start);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
/* need fault, too, probably */
if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
- clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
+ val = GUINT32_TO_LE (finally_start - ex_info->start);
else
- clause.try_len = GUINT32_TO_LE (ex_info->len);
- clause.handler_offset = GUINT32_TO_LE (ex_block->start);
- clause.handler_len = GUINT32_TO_LE (ex_block->len);
- finally_start = clause.handler_offset + clause.handler_len;
- clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
- mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
- clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
+ val = GUINT32_TO_LE (ex_info->len);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /* handler offset */
+ val = GUINT32_TO_LE (ex_block->start);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ /* handler len */
+ val = GUINT32_TO_LE (ex_block->len);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
+ finally_start = ex_block->start + ex_block->len;
+ if (ex_block->extype) {
+ val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
+ } else {
+ /* FIXME: handle filters */
+ val = 0;
+ }
+ val = GUINT32_TO_LE (val);
+ mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
/*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
- mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
}
} else {
g_error ("No clauses for ex info block %d", i);
@@ -526,7 +1042,7 @@ fat_header:
}
static guint32
-find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
+find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
{
int i;
MonoDynamicTable *table;
@@ -540,16 +1056,71 @@ find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guin
for (i = 1; i <= table->rows; ++i) {
if (values [col] == token)
return i;
+ values += table->columns;
}
return 0;
}
+static GHashTable *dynamic_custom_attrs = NULL;
+
+static MonoCustomAttrInfo*
+mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
+{
+ int i, count;
+ MonoCustomAttrInfo *ainfo;
+ MonoReflectionCustomAttr *cattr;
+
+ if (!cattrs)
+ return NULL;
+ /* FIXME: check in assembly the Run flag is set */
+
+ count = mono_array_length (cattrs);
+
+ ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
+
+ ainfo->image = image;
+ ainfo->num_attrs = count;
+ for (i = 0; i < count; ++i) {
+ cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
+ ainfo->attrs [i].ctor = cattr->ctor->method;
+ /* FIXME: might want to memdup the data here */
+ ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
+ ainfo->attrs [i].data_size = mono_array_length (cattr->data);
+ }
+
+ return ainfo;
+}
+
+static void
+mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
+{
+ MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
+
+ if (!ainfo)
+ return;
+
+ if (!dynamic_custom_attrs)
+ dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
+
+ g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
+ ainfo->cached = TRUE;
+}
+
+void
+mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
+{
+ /* they are cached, so we don't free them */
+ if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
+ return;
+ g_free (ainfo);
+}
+
/*
* idx is the table index of the object
- * type is one of CUSTOM_ATTR_*
+ * type is one of MONO_CUSTOM_ATTR_*
*/
static void
-mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
+mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
{
MonoDynamicTable *table;
MonoReflectionCustomAttr *cattr;
@@ -566,41 +1137,86 @@ mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type,
table->rows += count;
alloc_table (table, table->rows);
values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
- idx <<= CUSTOM_ATTR_BITS;
+ idx <<= MONO_CUSTOM_ATTR_BITS;
idx |= type;
for (i = 0; i < count; ++i) {
cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
values [MONO_CUSTOM_ATTR_PARENT] = idx;
- token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
+ token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
type = mono_metadata_token_index (token);
- type <<= CUSTOM_ATTR_TYPE_BITS;
+ type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
switch (mono_metadata_token_table (token)) {
case MONO_TABLE_METHOD:
- type |= CUSTOM_ATTR_TYPE_METHODDEF;
+ type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
break;
case MONO_TABLE_MEMBERREF:
- type |= CUSTOM_ATTR_TYPE_MEMBERREF;
+ type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
break;
default:
- g_error ("got wrong token in custom attr");
+ g_warning ("got wrong token in custom attr");
+ continue;
}
values [MONO_CUSTOM_ATTR_TYPE] = type;
p = blob_size;
mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
- values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
- mono_image_add_stream_data (&assembly->blob,
+ values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
values += MONO_CUSTOM_ATTR_SIZE;
++table->next_idx;
}
}
+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 <<= MONO_HAS_DECL_SECURITY_BITS;
+ switch (mono_metadata_token_table (parent_token)) {
+ case MONO_TABLE_TYPEDEF:
+ idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
+ break;
+ case MONO_TABLE_METHOD:
+ idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
+ break;
+ case MONO_TABLE_ASSEMBLY:
+ idx |= MONO_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.
*/
static void
-mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
+mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
guint32 *values;
@@ -610,14 +1226,11 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assem
/* room in this table is already allocated */
table = &assembly->tables [MONO_TABLE_METHOD];
*mb->table_idx = table->next_idx ++;
+ mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
- if (mb->name) {
- name = mono_string_to_utf8 (mb->name);
- values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
- g_free (name);
- } else { /* a constructor */
- values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
- }
+ name = mono_string_to_utf8 (mb->name);
+ values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
+ g_free (name);
values [MONO_METHOD_FLAGS] = mb->attrs;
values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
@@ -626,6 +1239,9 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assem
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;
@@ -646,53 +1262,153 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assem
if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
values [MONO_PARAM_FLAGS] = pb->attrs;
values [MONO_PARAM_SEQUENCE] = i;
- name = mono_string_to_utf8 (pb->name);
- values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
- g_free (name);
+ if (pb->name != NULL) {
+ name = mono_string_to_utf8 (pb->name);
+ values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
+ g_free (name);
+ } else {
+ values [MONO_PARAM_NAME] = 0;
+ }
values += MONO_PARAM_SIZE;
if (pb->marshal_info) {
mtable->rows++;
alloc_table (mtable, mtable->rows);
mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
- mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
+ mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
}
- table->next_idx++;
+ pb->table_idx = table->next_idx++;
+ if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
+ guint32 field_type = 0;
+ mtable = &assembly->tables [MONO_TABLE_CONSTANT];
+ mtable->rows ++;
+ alloc_table (mtable, mtable->rows);
+ mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
+ mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
+ mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
+ mvalues [MONO_CONSTANT_TYPE] = field_type;
+ mvalues [MONO_CONSTANT_PADDING] = 0;
+ }
}
}
}
}
static void
-mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
+reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
+{
+ rmb->ilgen = mb->ilgen;
+ rmb->rtype = mb->rtype;
+ rmb->parameters = mb->parameters;
+ rmb->generic_params = mb->generic_params;
+ rmb->opt_types = NULL;
+ rmb->pinfo = mb->pinfo;
+ rmb->attrs = mb->attrs;
+ rmb->iattrs = mb->iattrs;
+ rmb->call_conv = mb->call_conv;
+ rmb->code = mb->code;
+ rmb->type = mb->type;
+ 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;
+
+ if (mb->dll) {
+ rmb->charset = rmb->charset & 0xf;
+ rmb->lasterr = rmb->charset & 0x40;
+ rmb->native_cc = rmb->native_cc;
+ rmb->dllentry = mb->dllentry;
+ rmb->dll = mb->dll;
+ }
+}
+
+static void
+reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
+{
+ const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
+
+ rmb->ilgen = mb->ilgen;
+ rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
+ rmb->parameters = mb->parameters;
+ rmb->generic_params = NULL;
+ rmb->opt_types = NULL;
+ rmb->pinfo = mb->pinfo;
+ rmb->attrs = mb->attrs;
+ rmb->iattrs = mb->iattrs;
+ rmb->call_conv = mb->call_conv;
+ rmb->code = NULL;
+ rmb->type = mb->type;
+ 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->opt_types = 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)
{
MonoDynamicTable *table;
guint32 *values;
char *name;
ReflectionMethodBuilder rmb;
+ int i;
- rmb.ilgen = mb->ilgen;
- rmb.rtype = mb->rtype;
- rmb.parameters = mb->parameters;
- rmb.pinfo = mb->pinfo;
- rmb.attrs = mb->attrs;
- rmb.iattrs = mb->iattrs;
- rmb.call_conv = mb->call_conv;
- rmb.code = mb->code;
- rmb.type = mb->type;
- rmb.name = mb->name;
- rmb.table_idx = &mb->table_idx;
- rmb.init_locals = mb->init_locals;
+ reflection_methodbuilder_from_method_builder (&rmb, mb);
mono_image_basic_method (&rmb, assembly);
if (mb->dll) { /* It's a P/Invoke method */
guint32 moduleref;
+ int charset = mb->charset & 0xf;
+ int lasterr = mb->charset & 0x40;
table = &assembly->tables [MONO_TABLE_IMPLMAP];
table->rows ++;
alloc_table (table, table->rows);
values = table->values + table->rows * MONO_IMPLMAP_SIZE;
- values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
+ /* map CharSet values to on-disk values */
+
+ values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
name = mono_string_to_utf8 (mb->dllentry);
values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
@@ -708,6 +1424,7 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly
values [MONO_IMPLMAP_SCOPE] = table->rows;
}
}
+
if (mb->override_method) {
MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
guint32 tok;
@@ -716,68 +1433,106 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly
alloc_table (table, table->rows);
values = table->values + table->rows * MONO_METHODIMPL_SIZE;
values [MONO_METHODIMPL_CLASS] = tb->table_idx;
- values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
- tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
+ values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+
+ tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
switch (mono_metadata_token_table (tok)) {
case MONO_TABLE_MEMBERREF:
- tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
+ tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
break;
case MONO_TABLE_METHOD:
- tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
+ tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
break;
default:
g_assert_not_reached ();
}
values [MONO_METHODIMPL_DECLARATION] = tok;
}
+
+ if (mb->generic_params) {
+ table = &assembly->tables [MONO_TABLE_GENERICPARAM];
+ table->rows += mono_array_length (mb->generic_params);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
+ guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
+
+ mono_image_get_generic_param_info (
+ mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
+ }
+ }
+
}
static void
-mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
+mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
{
ReflectionMethodBuilder rmb;
- rmb.ilgen = mb->ilgen;
- rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
- rmb.parameters = mb->parameters;
- rmb.pinfo = mb->pinfo;
- rmb.attrs = mb->attrs;
- rmb.iattrs = mb->iattrs;
- rmb.call_conv = mb->call_conv;
- rmb.code = NULL;
- rmb.type = mb->type;
- rmb.name = NULL;
- rmb.table_idx = &mb->table_idx;
- rmb.init_locals = mb->init_locals;
+ reflection_methodbuilder_from_ctor_builder (&rmb, mb);
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_key_token [0] ? (char *)ta->aname.public_key_token : "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);
+ if (!klass)
+ return mono_type_get_name (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 (MonoDynamicAssembly *assembly, MonoClassField *field)
+fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
{
char blob_size [64];
char *b = blob_size;
char *p;
char* buf;
guint32 idx;
-
+
+ if (!assembly->save)
+ return 0;
+
p = buf = g_malloc (64);
mono_metadata_encode_value (0x06, p, &p);
/* encode custom attributes before the type */
- encode_type (assembly, field->type, p, &p);
+ encode_type (assembly, type, p, &p);
g_assert (p-buf < 64);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
static guint32
-field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
+field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
{
char blob_size [64];
char *b = blob_size;
@@ -788,73 +1543,33 @@ field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilde
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);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
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 (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
+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;
+ guint32 idx = 0, len = 0, dummy = 0;
p = buf = g_malloc (64);
-
- box_val = ((char*)val) + sizeof (MonoObject);
- *ret_type = val->vtable->klass->byval_arg.type;
+ if (!val) {
+ *ret_type = MONO_TYPE_CLASS;
+ len = 4;
+ box_val = (char*)&dummy;
+ } else {
+ box_val = ((char*)val) + sizeof (MonoObject);
+ *ret_type = val->vtable->klass->byval_arg.type;
+ }
handle_enum:
switch (*ret_type) {
case MONO_TYPE_BOOLEAN:
@@ -883,23 +1598,24 @@ handle_enum:
goto handle_enum;
} else
g_error ("we can't encode valuetypes");
+ case MONO_TYPE_CLASS:
+ break;
case MONO_TYPE_STRING: {
MonoString *str = (MonoString*)val;
/* there is no signature */
len = str->length * 2;
mono_metadata_encode_value (len, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
#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));
- mono_image_add_stream_data (&assembly->blob, swapped, len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
g_free (swapped);
}
#else
- mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
#endif
g_free (buf);
@@ -911,12 +1627,12 @@ handle_enum:
/* there is no signature */
mono_metadata_encode_value (len, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
- swap_with_size (blob_size, val, len, 1);
+ idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
+ swap_with_size (blob_size, box_val, len, 1);
mono_image_add_stream_data (&assembly->blob, blob_size, len);
#else
- mono_image_add_stream_data (&assembly->blob, box_val, len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
#endif
g_free (buf);
@@ -924,30 +1640,104 @@ handle_enum:
}
static guint32
-encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo) {
+encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
char blob_size [64];
char *b = blob_size;
- char *p, *buf;
- guint32 idx, len;
+ char *p, *buf, *str;
+ guint32 idx, len, bufsize = 256;
- p = buf = g_malloc (256);
+ p = buf = g_malloc (bufsize);
switch (minfo->type) {
- /* FIXME: handle ARRAY and other unmanaged types that need extra info */
+ case MONO_NATIVE_BYVALTSTR:
+ case MONO_NATIVE_BYVALARRAY:
+ mono_metadata_encode_value (minfo->type, p, &p);
+ mono_metadata_encode_value (minfo->count, p, &p);
+ break;
+ 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) {
+ str = mono_string_to_utf8 (minfo->guid);
+ len = strlen (str);
+ mono_metadata_encode_value (len, p, &p);
+ memcpy (p, str, len);
+ p += len;
+ g_free (str);
+ } else {
+ mono_metadata_encode_value (0, p, &p);
+ }
+ if (minfo->marshaltype) {
+ str = mono_string_to_utf8 (minfo->marshaltype);
+ len = strlen (str);
+ mono_metadata_encode_value (len, p, &p);
+ if (p + len >= buf + bufsize) {
+ idx = p - buf;
+ bufsize *= 2;
+ buf = g_realloc (buf, bufsize);
+ p = buf + idx;
+ }
+ memcpy (p, str, len);
+ p += len;
+ g_free (str);
+ } else {
+ mono_metadata_encode_value (0, p, &p);
+ }
+ if (minfo->marshaltyperef) {
+ str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
+ len = strlen (str);
+ mono_metadata_encode_value (len, p, &p);
+ if (p + len >= buf + bufsize) {
+ idx = p - buf;
+ bufsize *= 2;
+ buf = g_realloc (buf, bufsize);
+ p = buf + idx;
+ }
+ memcpy (p, str, len);
+ p += len;
+ g_free (str);
+ } else {
+ mono_metadata_encode_value (0, p, &p);
+ }
+ if (minfo->mcookie) {
+ str = mono_string_to_utf8 (minfo->mcookie);
+ len = strlen (str);
+ mono_metadata_encode_value (len, p, &p);
+ if (p + len >= buf + bufsize) {
+ idx = p - buf;
+ bufsize *= 2;
+ buf = g_realloc (buf, bufsize);
+ p = buf + idx;
+ }
+ memcpy (p, str, len);
+ p += len;
+ g_free (str);
+ } else {
+ mono_metadata_encode_value (0, p, &p);
+ }
+ break;
default:
mono_metadata_encode_value (minfo->type, p, &p);
break;
}
len = p-buf;
mono_metadata_encode_value (len, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, len);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
g_free (buf);
return idx;
}
static void
-mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
+mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
guint32 *values;
@@ -958,6 +1748,7 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *
fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
table = &assembly->tables [MONO_TABLE_FIELD];
fb->table_idx = table->next_idx ++;
+ mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
values = table->values + fb->table_idx * MONO_FIELD_SIZE;
name = mono_string_to_utf8 (fb->name);
values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
@@ -979,12 +1770,12 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *
table->rows ++;
alloc_table (table, table->rows);
values = table->values + table->rows * MONO_CONSTANT_SIZE;
- values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
+ values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
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 ++;
@@ -994,7 +1785,10 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *
/*
* 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) {
@@ -1002,23 +1796,26 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *
table->rows ++;
alloc_table (table, table->rows);
values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
- values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
+ values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
}
}
static guint32
-property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
+property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
{
char *buf, *p;
char blob_size [6];
char *b = blob_size;
guint32 nparams = 0;
MonoReflectionMethodBuilder *mb = fb->get_method;
+ MonoReflectionMethodBuilder *smb = fb->set_method;
guint32 idx, i, size;
if (mb && mb->parameters)
nparams = mono_array_length (mb->parameters);
+ if (!mb && smb && smb->parameters)
+ nparams = mono_array_length (smb->parameters) - 1;
size = 24 + nparams * 10;
buf = p = g_malloc (size);
*p = 0x08;
@@ -1031,19 +1828,23 @@ property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionProperty
encode_reflection_type (assembly, pt, p, &p);
}
} else {
- *p++ = 1; /* void: a property should probably not be allowed without a getter */
+ /* the property type is the last param */
+ encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
+ for (i = 0; i < nparams; ++i) {
+ MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, p, &p);
+ }
}
/* store length */
g_assert (p - buf < size);
mono_metadata_encode_value (p-buf, b, &b);
- idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, buf, p-buf);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
g_free (buf);
return idx;
}
static void
-mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
+mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
guint32 *values;
@@ -1080,19 +1881,19 @@ mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAsse
values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
}
if (pb->set_method) {
semaidx = table->next_idx ++;
values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
}
}
static void
-mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
+mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
guint32 *values;
@@ -1132,63 +1933,247 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *
values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
}
if (eb->remove_method) {
semaidx = table->next_idx ++;
values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
}
if (eb->raise_method) {
semaidx = table->next_idx ++;
values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
- values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
+ values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
+ }
+}
+
+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 <<= MONO_CUSTOM_ATTR_BITS;
+ owner |= MONO_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 <<= MONO_CUSTOM_ATTR_TYPE_BITS;
+ switch (mono_metadata_token_table (token)) {
+ case MONO_TABLE_METHOD:
+ type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
+ break;
+ case MONO_TABLE_MEMBERREF:
+ type |= MONO_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)
+{
+ MonoDynamicTable *table;
+ guint32 num_constraints, i;
+ guint32 *values;
+ guint32 table_idx;
+
+ table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
+ 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->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);
}
+
+ if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
+ encode_new_constraint (assembly, owner);
+}
+
+static void
+mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
+{
+ GenericParamTableEntry *entry;
+
+ /*
+ * The GenericParam table must be sorted according to the `owner' field.
+ * We need to do this sorting prior to writing the GenericParamConstraint
+ * table, since we have to use the final GenericParam table indices there
+ * and they must also be sorted.
+ */
+
+ entry = g_new0 (GenericParamTableEntry, 1);
+ entry->owner = owner;
+ entry->gparam = gparam;
+
+ g_ptr_array_add (assembly->gen_params, entry);
+}
+
+static void
+write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
+{
+ MonoDynamicTable *table;
+ MonoGenericParam *param;
+ guint32 *values;
+ guint32 table_idx;
+
+ table = &assembly->tables [MONO_TABLE_GENERICPARAM];
+ table_idx = table->next_idx ++;
+ values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
+
+ param = entry->gparam->type.type->data.generic_param;
+
+ values [MONO_GENERICPARAM_OWNER] = entry->owner;
+ values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
+ values [MONO_GENERICPARAM_NUMBER] = param->num;
+ values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
+ values [MONO_GENERICPARAM_KIND] = 0;
+
+ encode_constraints (entry->gparam, table_idx, assembly);
}
static guint32
-resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
+resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
{
MonoDynamicTable *table;
guint32 token;
guint32 *values;
guint32 cols [MONO_ASSEMBLY_SIZE];
+ const char *pubkey;
+ guint32 publen;
if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
return token;
- mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
+ if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
+ table = &assembly->tables [MONO_TABLE_MODULEREF];
+ token = table->next_idx ++;
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + token * MONO_MODULEREF_SIZE;
+ values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
+
+ token <<= MONO_RESOLTION_SCOPE_BITS;
+ token |= MONO_RESOLTION_SCOPE_MODULEREF;
+ g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
+
+ return token;
+ }
+
+ if (image->assembly->dynamic)
+ /* FIXME: */
+ memset (cols, 0, sizeof (cols));
+ else {
+ /* image->assembly->image is the manifest module */
+ image = image->assembly->image;
+ mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
+ }
table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
token = table->next_idx ++;
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_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
values [MONO_ASSEMBLYREF_FLAGS] = 0;
- values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
values [MONO_ASSEMBLYREF_CULTURE] = 0;
values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
- token <<= RESOLTION_SCOPE_BITS;
- token |= RESOLTION_SCOPE_ASSEMBLYREF;
+ 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;
+ mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
+ values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
+ } else {
+ values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
+ }
+ token <<= MONO_RESOLTION_SCOPE_BITS;
+ token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
return token;
}
static guint32
-create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
+create_typespec (MonoDynamicImage *assembly, MonoType *type)
{
MonoDynamicTable *table;
guint32 *values;
@@ -1203,23 +2188,34 @@ create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
case MONO_TYPE_PTR:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_ARRAY:
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ case MONO_TYPE_GENERICINST:
encode_type (assembly, type, p, &p);
break;
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_VALUETYPE: {
+ MonoClass *k = mono_class_from_mono_type (type);
+ if (!k || !k->generic_inst)
+ return 0;
+ encode_generic_inst (assembly, k->generic_inst, p, &p);
+ break;
+ }
default:
return 0;
}
-
- g_assert (p-sig < 128);
- mono_metadata_encode_value (p-sig, b, &b);
- token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
- mono_image_add_stream_data (&assembly->blob, sig, p-sig);
table = &assembly->tables [MONO_TABLE_TYPESPEC];
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
- values [MONO_TYPESPEC_SIGNATURE] = token;
+ if (assembly->save) {
+ g_assert (p-sig < 128);
+ mono_metadata_encode_value (p-sig, b, &b);
+ token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
+ values [MONO_TYPESPEC_SIGNATURE] = token;
+ }
- token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
+ token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
table->next_idx ++;
return token;
@@ -1229,7 +2225,7 @@ create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
* Despite the name, we handle also TypeSpec (with the above helper).
*/
static guint32
-mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
+mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
{
MonoDynamicTable *table;
guint32 *values;
@@ -1242,32 +2238,41 @@ mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
token = create_typespec (assembly, type);
if (token)
return token;
- klass = mono_class_from_mono_type (type);
+ klass = my_mono_class_from_mono_type (type);
+ if (!klass)
+ klass = mono_class_from_mono_type (type);
+
/*
- * If it's in the same module:
+ * If it's in the same module and not a generic type parameter:
*/
- if (klass->image == assembly->assembly.image) {
+ if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
+ (type->type != MONO_TYPE_MVAR)) {
MonoReflectionTypeBuilder *tb = klass->reflection_info;
- return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
+ token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
+ return token;
}
if (klass->nested_in) {
enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
/* get the typeref idx of the enclosing type */
- enclosing >>= TYPEDEFORREF_BITS;
- scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
+ enclosing >>= MONO_TYPEDEFORREF_BITS;
+ scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
} else {
scope = resolution_scope_from_image (assembly, klass->image);
}
table = &assembly->tables [MONO_TABLE_TYPEREF];
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
- values [MONO_TYPEREF_SCOPE] = scope;
- values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
- values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
- token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
+ values [MONO_TYPEREF_SCOPE] = scope;
+ values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
+ values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
+ }
+ token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
table->next_idx ++;
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
return token;
}
@@ -1278,7 +2283,7 @@ mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
* The sig param is an index to an already built signature.
*/
static guint32
-mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, const char *name, guint32 sig)
+mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
{
MonoDynamicTable *table;
guint32 *values;
@@ -1286,27 +2291,33 @@ mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, c
guint32 parent;
parent = mono_image_typedef_or_ref (assembly, type);
- switch (parent & TYPEDEFORREF_MASK) {
- case TYPEDEFORREF_TYPEREF:
- pclass = MEMBERREF_PARENT_TYPEREF;
+ switch (parent & MONO_TYPEDEFORREF_MASK) {
+ case MONO_TYPEDEFORREF_TYPEREF:
+ pclass = MONO_MEMBERREF_PARENT_TYPEREF;
break;
- case TYPEDEFORREF_TYPESPEC:
- pclass = MEMBERREF_PARENT_TYPESPEC;
+ case MONO_TYPEDEFORREF_TYPESPEC:
+ pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
+ break;
+ case MONO_TYPEDEFORREF_TYPEDEF:
+ pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
break;
- case TYPEDEFORREF_TYPEDEF:
- /* should never get here */
default:
- g_error ("unknow typeref or def token");
+ g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
+ return 0;
}
/* extract the index */
- parent >>= TYPEDEFORREF_BITS;
+ parent >>= MONO_TYPEDEFORREF_BITS;
table = &assembly->tables [MONO_TABLE_MEMBERREF];
- alloc_table (table, table->rows + 1);
- values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
- values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
- values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
- values [MONO_MEMBERREF_SIGNATURE] = sig;
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+ values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
+ values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
+ values [MONO_MEMBERREF_SIGNATURE] = sig;
+ }
+
token = MONO_TOKEN_MEMBER_REF | table->next_idx;
table->next_idx ++;
@@ -1314,33 +2325,397 @@ mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, c
}
static guint32
-mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
+mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
{
guint32 token;
+ MonoMethodSignature *sig;
token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
if (token)
return token;
+
+ /*
+ * A methodref signature can't contain an unmanaged calling convention.
+ */
+ sig = mono_metadata_signature_dup (method->signature);
+ if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
+ sig->call_convention = MONO_CALL_DEFAULT;
token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
- method->name, method_encode_signature (assembly, method->signature));
+ method->name, method_encode_signature (assembly, sig));
+ g_free (sig);
g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
return token;
}
static guint32
-mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
+mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
+ const gchar *name, guint32 sig)
+{
+ MonoDynamicTable *table;
+ guint32 token;
+ guint32 *values;
+
+ table = &assembly->tables [MONO_TABLE_MEMBERREF];
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+ values [MONO_MEMBERREF_CLASS] = original;
+ values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
+ values [MONO_MEMBERREF_SIGNATURE] = sig;
+ }
+
+ token = MONO_TOKEN_MEMBER_REF | table->next_idx;
+ table->next_idx ++;
+
+ return token;
+}
+
+static guint32
+mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
{
guint32 token;
+ ReflectionMethodBuilder rmb;
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
if (token)
return token;
- token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
- field->name, fieldref_encode_signature (assembly, field));
- g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(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), method_builder_encode_signature (assembly, &rmb));
+ g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
return token;
}
+static guint32
+mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
+{
+ guint32 token;
+ ReflectionMethodBuilder rmb;
+
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
+ if (token)
+ return token;
+
+ reflection_methodbuilder_from_ctor_builder (&rmb, mb);
+
+ token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
+ mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
+ g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
+ return token;
+}
+
+static guint32
+mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
+{
+ MonoType *type;
+ guint32 token;
+
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
+ if (token)
+ return token;
+ g_assert (f->field->parent);
+ type = f->field->generic_info ? f->field->generic_info->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, MonoGenericMethod *gmethod)
+{
+ char *buf;
+ char *p;
+ int i;
+ guint32 nparams = gmethod->mtype_argc;
+ guint32 size = 10 + nparams * 10;
+ guint32 idx;
+ char blob_size [6];
+ char *b = blob_size;
+
+ if (!assembly->save)
+ return 0;
+
+ p = buf = g_malloc (size);
+ /*
+ * FIXME: vararg, explicit_this, differenc call_conv values...
+ */
+ mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
+ mono_metadata_encode_value (nparams, p, &p);
+
+ for (i = 0; i < nparams; i++)
+ encode_type (assembly, gmethod->mtype_argv [i], p, &p);
+
+ /* store length */
+ g_assert (p - buf < size);
+ mono_metadata_encode_value (p-buf, b, &b);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
+ g_free (buf);
+ return idx;
+}
+
+static guint32
+method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ guint32 token, mtoken = 0, sig;
+ MonoMethodInflated *imethod;
+ MonoMethod *declaring;
+
+ table = &assembly->tables [MONO_TABLE_METHODSPEC];
+
+ g_assert (method->signature->is_inflated);
+ imethod = (MonoMethodInflated *) method;
+ declaring = imethod->declaring;
+
+ sig = method_encode_signature (assembly, declaring->signature);
+ mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
+
+ if (!declaring->signature->generic_param_count)
+ return mtoken;
+
+ switch (mono_metadata_token_table (mtoken)) {
+ case MONO_TABLE_MEMBERREF:
+ mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
+ break;
+ case MONO_TABLE_METHOD:
+ mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
+ values [MONO_METHODSPEC_METHOD] = mtoken;
+ values [MONO_METHODSPEC_SIGNATURE] = sig;
+ }
+
+ token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
+ table->next_idx ++;
+
+ return token;
+}
+
+static guint32
+mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
+{
+ MonoMethodInflated *imethod;
+ guint32 token;
+
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
+ if (token)
+ return 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;
+}
+
+static guint32
+mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
+{
+ MonoMethodInflated *imethod = (MonoMethodInflated *) m;
+ guint32 sig, token;
+
+ sig = method_encode_signature (assembly, imethod->declaring->signature);
+ token = mono_image_get_memberref_token (
+ assembly, &m->klass->byval_arg, m->name, sig);
+
+ return token;
+}
+
+static guint32
+create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
+{
+ MonoDynamicTable *table;
+ MonoClass *klass;
+ guint32 *values;
+ guint32 token;
+ char sig [128];
+ char *p = sig;
+ char blob_size [6];
+ 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);
+
+ mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
+ encode_type (assembly, &klass->byval_arg, p, &p);
+
+ count = mono_array_length (tb->generic_params);
+ mono_metadata_encode_value (count, p, &p);
+ for (i = 0; i < count; i++) {
+ MonoReflectionGenericParam *gparam;
+
+ gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
+
+ encode_type (assembly, gparam->type.type, p, &p);
+ }
+
+ table = &assembly->tables [MONO_TABLE_TYPESPEC];
+ if (assembly->save) {
+ g_assert (p-sig < 128);
+ mono_metadata_encode_value (p-sig, b, &b);
+ token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
+ values [MONO_TYPESPEC_SIGNATURE] = token;
+ }
+
+ token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
+ g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
+ table->next_idx ++;
+ return token;
+}
+
+static guint32
+mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
+{
+ MonoDynamicTable *table;
+ MonoClass *klass;
+ guint32 *values;
+ 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);
+
+ sig = fieldref_encode_signature (assembly, fb->type->type);
+
+ parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
+ g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
+
+ pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
+ parent >>= MONO_TYPEDEFORREF_BITS;
+
+ table = &assembly->tables [MONO_TABLE_MEMBERREF];
+
+ if (assembly->save) {
+ alloc_table (table, table->rows + 1);
+ values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
+ values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
+ values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
+ values [MONO_MEMBERREF_SIGNATURE] = sig;
+ }
+
+ token = MONO_TOKEN_MEMBER_REF | table->next_idx;
+ table->next_idx ++;
+ g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
+ return token;
+}
+
+static guint32
+mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
+{
+ char *buf;
+ char *p;
+ guint32 nargs;
+ guint32 size;
+ guint32 i, idx;
+ char blob_size [6];
+ char *b = blob_size;
+
+ if (!assembly->save)
+ return 0;
+
+ /* FIXME: */
+ g_assert (helper->type == 2);
+
+ if (helper->arguments)
+ nargs = mono_array_length (helper->arguments);
+ else
+ nargs = 0;
+
+ size = 10 + (nargs * 10);
+
+ p = buf = g_malloc (size);
+
+ /* Encode calling convention */
+ /* Change Any to Standard */
+ if ((helper->call_conv & 0x03) == 0x03)
+ helper->call_conv = 0x01;
+ /* explicit_this implies has_this */
+ if (helper->call_conv & 0x40)
+ helper->call_conv &= 0x20;
+
+ if (helper->call_conv == 0) { /* Unmanaged */
+ *p = helper->unmanaged_call_conv - 1;
+ } else {
+ /* Managed */
+ *p = helper->call_conv & 0x60; /* has_this + explicit_this */
+ if (helper->call_conv & 0x02) /* varargs */
+ *p += 0x05;
+ }
+
+ p++;
+ mono_metadata_encode_value (nargs, p, &p);
+ encode_reflection_type (assembly, helper->return_type, p, &p);
+ for (i = 0; i < nargs; ++i) {
+ MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
+ encode_reflection_type (assembly, pt, p, &p);
+ }
+ /* store length */
+ g_assert (p - buf < size);
+ mono_metadata_encode_value (p-buf, b, &b);
+ idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
+ g_free (buf);
+
+ return idx;
+}
+
+static guint32
+mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
+{
+ guint32 idx;
+ MonoDynamicTable *table;
+ guint32 *values;
+
+ table = &assembly->tables [MONO_TABLE_STANDALONESIG];
+ idx = table->next_idx ++;
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
+
+ values [MONO_STAND_ALONE_SIGNATURE] =
+ mono_reflection_encode_sighelper (assembly, helper);
+
+ return idx;
+}
+
static int
reflection_cc_to_file (int call_conv) {
switch (call_conv & 0x3) {
@@ -1361,7 +2736,7 @@ typedef struct {
} ArrayMethod;
static guint32
-mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMethod *m)
+mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
{
guint32 nparams, i;
GList *tmp;
@@ -1373,6 +2748,7 @@ mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMe
nparams = mono_array_length (m->parameters);
sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
sig->hasthis = 1;
+ sig->sentinelpos = -1;
sig->call_convention = reflection_cc_to_file (m->call_conv);
sig->param_count = nparams;
sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
@@ -1388,6 +2764,7 @@ mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMe
mono_metadata_signature_equal (am->sig, sig)) {
g_free (name);
g_free (sig);
+ m->table_idx = am->token & 0xffffff;
return am->token;
}
}
@@ -1395,8 +2772,8 @@ mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMe
am->name = name;
am->sig = sig;
am->parent = m->parent->type;
- am->token = mono_image_get_memberref_token (assembly, am->parent,
- name, method_encode_signature (assembly, sig));
+ am->token = mono_image_get_memberref_token (assembly, am->parent, name,
+ method_encode_signature (assembly, sig));
assembly->array_methods = g_list_prepend (assembly->array_methods, am);
m->table_idx = am->token & 0xffffff;
return am->token;
@@ -1407,26 +2784,32 @@ mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMe
* Data in the tables is inserted in a predefined order, since some tables need to be sorted.
*/
static void
-mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
+mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
guint *values;
- int i;
+ int i, is_object = 0, is_system = 0;
char *n;
table = &assembly->tables [MONO_TABLE_TYPEDEF];
values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
values [MONO_TYPEDEF_FLAGS] = tb->attrs;
- if (tb->parent) { /* interfaces don't have a parent */
- values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
- } else
- values [MONO_TYPEDEF_EXTENDS] = 0;
n = mono_string_to_utf8 (tb->name);
+ if (strcmp (n, "Object") == 0)
+ is_object++;
values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
g_free (n);
n = mono_string_to_utf8 (tb->nspace);
+ if (strcmp (n, "System") == 0)
+ is_system++;
values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
g_free (n);
+ if (tb->parent && !(is_system && is_object) &&
+ !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
+ values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
+ } else {
+ values [MONO_TYPEDEF_EXTENDS] = 0;
+ }
values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
@@ -1434,7 +2817,8 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
* if we have explicitlayout or sequentiallayouts, output data in the
* ClassLayout table.
*/
- if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
+ if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
+ ((tb->class_size > 0) || (tb->packing_size > 0))) {
table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
table->rows++;
alloc_table (table, table->rows);
@@ -1462,9 +2846,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);
}
@@ -1482,9 +2866,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);
}
@@ -1518,13 +2902,26 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
mono_image_get_property_info (
mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
}
+
+ /* handle generic parameters */
+ if (tb->generic_params) {
+ table = &assembly->tables [MONO_TABLE_GENERICPARAM];
+ table->rows += mono_array_length (tb->generic_params);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
+ guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
+
+ mono_image_get_generic_param_info (
+ mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
+ }
+ }
+
+ mono_image_add_decl_security (assembly,
+ mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
+
if (tb->subtypes) {
MonoDynamicTable *ntable;
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows += mono_array_length (tb->subtypes);
- alloc_table (table, table->rows);
-
ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
ntable->rows += mono_array_length (tb->subtypes);
alloc_table (ntable, ntable->rows);
@@ -1542,30 +2939,39 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
values += MONO_NESTED_CLASS_SIZE;
ntable->next_idx++;
}
- for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
-
- mono_image_get_type_info (domain, subtype, assembly);
- }
}
}
static void
-assign_type_idx (MonoReflectionTypeBuilder *type, MonoDynamicTable *table)
+collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
{
- int j;
-
- type->table_idx = table->next_idx ++;
+ int i;
+
+ g_ptr_array_add (types, type);
+
if (!type->subtypes)
return;
- for (j = 0; j < mono_array_length (type->subtypes); ++j) {
- MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
- assign_type_idx (subtype, table);
+
+ for (i = 0; i < mono_array_length (type->subtypes); ++i) {
+ MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
+ collect_types (types, subtype);
}
}
+static gint
+compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
+{
+ if ((*type1)->table_idx < (*type2)->table_idx)
+ return -1;
+ else
+ if ((*type1)->table_idx > (*type2)->table_idx)
+ return 1;
+ else
+ return 0;
+}
+
static void
-params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
+params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
int i;
if (!pinfo)
@@ -1575,50 +2981,50 @@ params_add_cattrs (MonoDynamicAssembly *assembly, MonoArray *pinfo) {
pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
if (!pb)
continue;
- mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
+ mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
}
}
static void
-type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
+type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
int i;
- mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
+ mono_image_add_cattrs (assembly, tb->table_idx, MONO_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);
+ mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
}
}
if (tb->events) {
for (i = 0; i < mono_array_length (tb->events); ++i) {
MonoReflectionEventBuilder* eb;
eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
- mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
+ mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
}
}
if (tb->properties) {
for (i = 0; i < mono_array_length (tb->properties); ++i) {
MonoReflectionPropertyBuilder* pb;
pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
- mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
+ mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
}
}
if (tb->ctors) {
for (i = 0; i < mono_array_length (tb->ctors); ++i) {
MonoReflectionCtorBuilder* cb;
cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
- mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
+ mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
params_add_cattrs (assembly, cb->pinfo);
}
}
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);
+ mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
params_add_cattrs (assembly, mb->pinfo);
}
}
@@ -1630,17 +3036,54 @@ type_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionTypeBuilder *tb) {
}
static void
-module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *mb) {
+module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
int i;
- mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
+ mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
+
+ /* no types in the module */
+ 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_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
+mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
+{
+ MonoDynamicTable *table;
+ guint32 *values;
+ char blob_size [6];
+ guchar hash [20];
+ char *b = blob_size;
+ char *dir, *path;
+
+ table = &assembly->tables [MONO_TABLE_FILE];
+ table->rows++;
+ 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, 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);
+ mono_metadata_encode_value (20, b, &b);
+ values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
+ mono_image_add_stream_data (&assembly->blob, hash, 20);
+ table->next_idx ++;
+}
+
+static void
+mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
int i;
@@ -1657,23 +3100,89 @@ mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *m
table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
+}
- /*
- * fill-in info in other tables as well.
- */
- table = &assembly->tables [MONO_TABLE_TYPEDEF];
- table->rows += mono_array_length (mb->types);
+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, res;
+
+ visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+ if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
+ return 0;
+
+ table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
+ table->rows++;
alloc_table (table, table->rows);
- /*
- * We assign here the typedef indexes to avoid mismatches if a type that
- * has not yet been stored in the tables is referenced by another type.
+ values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
+
+ 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 << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
+ else
+ values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
+ 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);
+
+ 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.
*/
- for (i = 0; i < mono_array_length (mb->types); ++i) {
- MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
- assign_type_idx (type, table);
+ 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, 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);
}
- for (i = 0; i < mono_array_length (mb->types); ++i)
- mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
}
#define align_pointer(base,p)\
@@ -1721,6 +3230,39 @@ compare_nested (const void *a, const void *b)
return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
}
+static int
+compare_genericparam (const void *a, const void *b)
+{
+ const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
+ const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
+
+ return (*a_entry)->owner - (*b_entry)->owner;
+}
+
+static int
+compare_declsecurity_attrs (const void *a, const void *b)
+{
+ const guint32 *a_values = a;
+ const guint32 *b_values = b;
+
+ return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
+}
+
+static void
+pad_heap (MonoDynamicStream *sh)
+{
+ if (sh->index & 3) {
+ int sz = 4 - (sh->index & 3);
+ memset (sh->data + sh->index, 0, sz);
+ sh->index += sz;
+ }
+}
+
+struct StreamDesc {
+ const char *name;
+ MonoDynamicStream *stream;
+};
+
/*
* build_compressed_metadata() fills in the blob of data that represents the
* raw metadata as it will be saved in the PE file. The five streams are output
@@ -1728,7 +3270,7 @@ compare_nested (const void *a, const void *b)
* to the compressed on-disk format.
*/
static void
-build_compressed_metadata (MonoDynamicAssembly *assembly)
+build_compressed_metadata (MonoDynamicImage *assembly)
{
MonoDynamicTable *table;
int i;
@@ -1743,22 +3285,24 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
guint16 *int16val;
MonoImage *meta;
unsigned char *p;
- /*
- * We need to use the current ms version or the ms runtime it won't find
- * the support dlls. D'oh!
- * const char *version = "mono-" VERSION;
- */
- const char *version = "v1.0.3705";
- struct StreamDesc {
- const char *name;
- MonoDynamicStream *stream;
- } stream_desc [] = {
- {"#~", &assembly->tstream},
- {"#Strings", &assembly->sheap},
- {"#US", &assembly->us},
- {"#Blob", &assembly->blob},
- {"#GUID", &assembly->guid}
- };
+ struct StreamDesc stream_desc [5];
+
+ qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
+ for (i = 0; i < assembly->gen_params->len; i++){
+ GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
+ write_generic_param_entry (assembly, entry);
+ }
+
+ stream_desc [0].name = "#~";
+ stream_desc [0].stream = &assembly->tstream;
+ stream_desc [1].name = "#Strings";
+ stream_desc [1].stream = &assembly->sheap;
+ stream_desc [2].name = "#US";
+ stream_desc [2].stream = &assembly->us;
+ stream_desc [3].name = "#Blob";
+ stream_desc [3].stream = &assembly->blob;
+ stream_desc [4].name = "#GUID";
+ stream_desc [4].stream = &assembly->guid;
/* tables that are sorted */
sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
@@ -1766,12 +3310,18 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
| ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
| ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
| ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
- | ((guint64)1 << MONO_TABLE_DECLSECURITY);
+ | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
/* Compute table sizes */
/* the MonoImage has already been created in mono_image_basic_init() */
- meta = assembly->assembly.image;
-
+ meta = &assembly->image;
+
+ /* sizes should be multiple of 4 */
+ pad_heap (&assembly->blob);
+ pad_heap (&assembly->guid);
+ pad_heap (&assembly->sheap);
+ pad_heap (&assembly->us);
+
/* Setup the info used by compute_sizes () */
meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
@@ -1796,6 +3346,9 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
}
heapt_size += 24; /* #~ header size */
heapt_size += ntables * 4;
+ /* make multiple of 4 */
+ heapt_size += 3;
+ heapt_size &= ~3;
meta_size += heapt_size;
meta->raw_metadata = g_malloc0 (meta_size);
p = meta->raw_metadata;
@@ -1808,9 +3361,9 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
p += 8;
/* version string */
int32val = (guint32*)p;
- *int32val = GUINT32_TO_LE ((strlen (version) + 3) & (~3)); /* needs to be multiple of 4 */
+ *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
p += 4;
- memcpy (p, version, GUINT32_FROM_LE (*int32val));
+ memcpy (p, meta->version, strlen (meta->version));
p += GUINT32_FROM_LE (*int32val);
align_pointer (meta->raw_metadata, p);
int16val = (guint16*)p;
@@ -1845,8 +3398,17 @@ build_compressed_metadata (MonoDynamicAssembly *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)
@@ -1854,7 +3416,7 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
if (meta->idx_blob_wide)
*p |= 0x04;
++p;
- *p++ = 0; /* reserved */
+ *p++ = 1; /* reserved */
int64val = (guint64*)p;
*int64val++ = GUINT64_TO_LE (valid_mask);
*int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
@@ -1880,6 +3442,10 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
if (table->rows)
qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
+ /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
+ table = &assembly->tables [MONO_TABLE_DECLSECURITY];
+ if (table->rows)
+ qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
/* compress the tables */
for (i = 0; i < 64; i++){
@@ -1899,14 +3465,14 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
*p++ = values [col];
break;
case 2:
- int16val = (guint16*)p;
- *int16val = GUINT16_TO_LE (values [col]);
- p += 2;
+ *p++ = values [col] & 0xff;
+ *p++ = (values [col] >> 8) & 0xff;
break;
case 4:
- int32val = (guint32*)p;
- *int32val = GUINT32_TO_LE (values [col]);
- p += 4;
+ *p++ = values [col] & 0xff;
+ *p++ = (values [col] >> 8) & 0xff;
+ *p++ = (values [col] >> 16) & 0xff;
+ *p++ = (values [col] >> 24) & 0xff;
break;
default:
g_assert_not_reached ();
@@ -1935,13 +3501,15 @@ build_compressed_metadata (MonoDynamicAssembly *assembly)
* tokens for the method with ILGenerator @ilgen.
*/
static void
-fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
+fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
guint32 code_idx = GPOINTER_TO_UINT (value);
MonoReflectionILTokenInfo *iltoken;
MonoReflectionFieldBuilder *field;
MonoReflectionCtorBuilder *ctor;
MonoReflectionMethodBuilder *method;
- guint32 i, idx;
+ MonoReflectionTypeBuilder *tb;
+ MonoReflectionArrayMethod *am;
+ guint32 i, idx = 0;
unsigned char *target;
for (i = 0; i < ilgen->num_token_fixups; ++i) {
@@ -1949,10 +3517,15 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
target = assembly->code.data + code_idx + iltoken->code_pos;
switch (target [3]) {
case MONO_TABLE_FIELD:
- if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
+ if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
+ field = (MonoReflectionFieldBuilder *)iltoken->member;
+ idx = field->table_idx;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
+ MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
+ idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
+ } else {
g_assert_not_reached ();
- field = (MonoReflectionFieldBuilder *)iltoken->member;
- idx = field->table_idx;
+ }
break;
case MONO_TABLE_METHOD:
if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
@@ -1961,6 +3534,46 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
} 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") ||
+ !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 {
+ g_assert_not_reached ();
+ }
+ break;
+ case MONO_TABLE_TYPEDEF:
+ if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
+ g_assert_not_reached ();
+ tb = (MonoReflectionTypeBuilder *)iltoken->member;
+ idx = tb->table_idx;
+ break;
+ case MONO_TABLE_MEMBERREF:
+ if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
+ am = (MonoReflectionArrayMethod*)iltoken->member;
+ idx = am->table_idx;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
+ !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
+ MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
+ g_assert (m->klass->generic_inst);
+ 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_info);
+ continue;
+ } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
+ continue;
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ case MONO_TABLE_METHODSPEC:
+ if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
+ MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
+ g_assert (m->signature->generic_param_count);
+ continue;
} else {
g_assert_not_reached ();
}
@@ -1975,62 +3588,278 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
}
/*
- * mono_image_build_metadata() will fill the info in all the needed metadata tables
- * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
- * and recursively outputs the info for a module. Each module will output all the info
- * about it's types etc.
- * At the end of the process, method and field tokens are fixed up and the on-disk
- * compressed metadata representation is created.
+ * fixup_cattrs:
+ *
+ * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
+ * value is not known when the table is emitted.
*/
static void
-mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
+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 & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
+ idx = type >> MONO_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 << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
+ }
+ }
+ }
+}
+
+static void
+assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
{
MonoDynamicTable *table;
- MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
- MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
- guint32 len;
guint32 *values;
char *name;
- int i;
+
+ 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;
+ char blob_size [6];
+ guchar hash [20];
+ char *b = blob_size;
+ char *name, *sname;
+ guint32 idx, offset;
+
+ if (rsrc->filename) {
+ name = mono_string_to_utf8 (rsrc->filename);
+ sname = g_path_get_basename (name);
- assembly->text_rva = START_TEXT_RVA;
+ table = &assembly->tables [MONO_TABLE_FILE];
+ table->rows++;
+ alloc_table (table, table->rows);
+ values = table->values + table->next_idx * MONO_FILE_SIZE;
+ values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
+ values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
+ g_free (sname);
+
+ mono_sha1_get_digest_from_file (name, hash);
+ mono_metadata_encode_value (20, b, &b);
+ values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
+ mono_image_add_stream_data (&assembly->blob, hash, 20);
+ g_free (name);
+ idx = table->next_idx++;
+ rsrc->offset = 0;
+ idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
+ } 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;
+ 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));
+
+ 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;
+ }
+
+ assembly_add_resource_manifest (mb, assembly, rsrc, idx);
+}
+
+static void
+set_version_from_string (MonoString *version, guint32 *values)
+{
+ gchar *ver, *p, *str;
+ guint32 i;
+
+ values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
+ values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
+ values [MONO_ASSEMBLY_REV_NUMBER] = 0;
+ values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
+ if (!version)
+ return;
+ ver = str = mono_string_to_utf8 (version);
+ for (i = 0; i < 4; ++i) {
+ values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
+ switch (*p) {
+ case '.':
+ p++;
+ break;
+ case '*':
+ /* handle Revision and Build */
+ p++;
+ break;
+ }
+ ver = p;
+ }
+ g_free (str);
+}
+static guint32
+load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
+ gsize len;
+ guint32 token = 0;
+ char blob_size [6];
+ char *b = blob_size;
+
+ if (!pkey)
+ return token;
+
+ len = mono_array_length (pkey);
+ mono_metadata_encode_value (len, b, &b);
+ token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
+ mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
+
+ /* need to get the actual value from the key type... */
+ assembly->strong_name_size = 128;
+ assembly->strong_name = g_malloc0 (assembly->strong_name_size);
+
+ 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] = 0x8004;
+ 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);
- values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
- values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
- values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
- values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
- values [MONO_ASSEMBLY_REV_NUMBER] = 0;
- values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
- values [MONO_ASSEMBLY_FLAGS] = 0;
+ 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);
- assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
- assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
+ /* 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);
+ }
+ }
- if (assemblyb->modules) {
- len = mono_array_length (assemblyb->modules);
- table = &assembly->tables [MONO_TABLE_MODULE];
- alloc_table (table, len);
- for (i = 0; i < len; ++i)
- mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
- } else {
- table = &assembly->tables [MONO_TABLE_MODULE];
- table->rows++;
- alloc_table (table, table->rows);
- table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
- table->next_idx ++;
+ /* 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, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
+ }
+ }
+ }
+ }
+}
+
+/*
+ * mono_image_build_metadata() will fill the info in all the needed metadata tables
+ * for the modulebuilder @moduleb.
+ * At the end of the process, method and field tokens are fixed up and the
+ * on-disk compressed metadata representation is created.
+ */
+void
+mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
+{
+ MonoDynamicTable *table;
+ MonoDynamicImage *assembly;
+ MonoReflectionAssemblyBuilder *assemblyb;
+ MonoDomain *domain;
+ guint32 *values;
+ int i;
+
+ assemblyb = moduleb->assemblyb;
+ assembly = moduleb->dynamic_image;
+ domain = mono_object_domain (assemblyb);
+
+ if (assembly->text_rva)
+ return;
+
+ assembly->text_rva = START_TEXT_RVA;
+
+ if (moduleb->is_main) {
+ mono_image_emit_manifest (moduleb);
}
table = &assembly->tables [MONO_TABLE_TYPEDEF];
- /*
- * table->rows is already set above and in mono_image_fill_module_table.
- */
+ table->rows = 1; /* .<Module> */
+ table->next_idx++;
alloc_table (table, table->rows);
/*
* Set the first entry.
@@ -2043,55 +3872,191 @@ mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
values [MONO_TYPEDEF_FIELD_LIST] = 1;
values [MONO_TYPEDEF_METHOD_LIST] = 1;
- /* add all the custom attributes at the end, once all the indexes are stable */
- mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
+ /*
+ * handle global methods
+ * FIXME: test what to do when global methods are defined in multiple modules.
+ */
+ if (moduleb->global_methods) {
+ table = &assembly->tables [MONO_TABLE_METHOD];
+ table->rows += mono_array_length (moduleb->global_methods);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
+ mono_image_get_method_info (
+ mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
+ }
+ if (moduleb->global_fields) {
+ table = &assembly->tables [MONO_TABLE_FIELD];
+ table->rows += mono_array_length (moduleb->global_fields);
+ alloc_table (table, table->rows);
+ for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
+ mono_image_get_field_info (
+ mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
+ }
- if (assemblyb->modules) {
- len = mono_array_length (assemblyb->modules);
- for (i = 0; i < len; ++i)
- module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
+ table = &assembly->tables [MONO_TABLE_MODULE];
+ alloc_table (table, 1);
+ mono_image_fill_module_table (domain, moduleb, assembly);
+
+ /* Emit types */
+ {
+ /* Collect all types into a list sorted by their table_idx */
+ GPtrArray *types = g_ptr_array_new ();
+
+ if (moduleb->types)
+ for (i = 0; i < moduleb->num_types; ++i) {
+ MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
+ collect_types (types, type);
+ }
+
+ g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
+ table = &assembly->tables [MONO_TABLE_TYPEDEF];
+ table->rows += types->len;
+ alloc_table (table, table->rows);
+
+ for (i = 0; i < types->len; ++i) {
+ MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
+ mono_image_get_type_info (domain, type, assembly);
+ }
+ g_ptr_array_free (types, TRUE);
}
-
+
+ /*
+ * table->rows is already set above and in mono_image_fill_module_table.
+ */
+ /* add all the custom attributes at the end, once all the indexes are stable */
+ mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
+
+ /* CAS assembly permissions */
+ if (assemblyb->permissions_minimum)
+ mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
+ if (assemblyb->permissions_optional)
+ mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
+ if (assemblyb->permissions_refused)
+ mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
+
+ module_add_cattrs (assembly, moduleb);
+
/* fixup tokens */
mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
-
- build_compressed_metadata (assembly);
+ fixup_cattrs (assembly);
}
/*
* mono_image_insert_string:
- * @assembly: assembly builder object
+ * @module: module builder object
* @str: a string
*
- * Insert @str into the user string stream of @assembly.
+ * Insert @str into the user string stream of @module.
*/
guint32
-mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
+mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
{
+ MonoDynamicImage *assembly;
guint32 idx;
char buf [16];
char *b = buf;
- if (!assembly->dynamic_assembly)
- mono_image_basic_init (assembly);
- mono_metadata_encode_value (1 | (str->length * 2), b, &b);
- idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
+ MONO_ARCH_SAVE_REGS;
+
+ if (!module->dynamic_image)
+ mono_image_module_basic_init (module);
+
+ assembly = module->dynamic_image;
+
+ if (assembly->save) {
+ mono_metadata_encode_value (1 | (str->length * 2), b, &b);
+ idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
#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));
- mono_image_add_stream_data (&assembly->dynamic_assembly->us, swapped, str->length * 2);
+ mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
g_free (swapped);
}
#else
- mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
+ mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
#endif
- mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
+ mono_image_add_stream_data (&assembly->us, "", 1);
+ } else {
+ idx = assembly->us.index ++;
+ }
+
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
+
return MONO_TOKEN_STRING | idx;
}
+guint32
+mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
+{
+ MonoClass *klass;
+ guint32 token = 0;
+
+ klass = obj->vtable->klass;
+ if (strcmp (klass->name, "MonoMethod") == 0) {
+ MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
+ MonoMethodSignature *sig, *old;
+ guint32 sig_token, parent;
+ int nargs, i;
+
+ g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
+
+ nargs = mono_array_length (opt_param_types);
+ old = method->signature;
+ sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
+
+ sig->hasthis = old->hasthis;
+ sig->explicit_this = old->explicit_this;
+ sig->call_convention = old->call_convention;
+ sig->generic_param_count = old->generic_param_count;
+ sig->param_count = old->param_count + nargs;
+ sig->sentinelpos = old->param_count;
+ sig->ret = old->ret;
+
+ for (i = 0; i < old->param_count; i++)
+ sig->params [i] = old->params [i];
+
+ for (i = 0; i < nargs; i++) {
+ MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
+ sig->params [old->param_count + i] = rt->type;
+ }
+
+ parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
+ g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
+ parent >>= MONO_TYPEDEFORREF_BITS;
+
+ parent <<= MONO_MEMBERREF_PARENT_BITS;
+ parent |= MONO_MEMBERREF_PARENT_TYPEREF;
+
+ sig_token = method_encode_signature (assembly, sig);
+ token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
+ } else if (strcmp (klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
+ ReflectionMethodBuilder rmb;
+ guint32 parent, sig;
+
+ reflection_methodbuilder_from_method_builder (&rmb, mb);
+ rmb.opt_types = opt_param_types;
+
+ sig = method_builder_encode_signature (assembly, &rmb);
+
+ parent = mono_image_create_token (assembly, obj, TRUE);
+ g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
+
+ parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
+ parent |= MONO_MEMBERREF_PARENT_METHODDEF;
+
+ token = mono_image_get_varargs_method_token (
+ assembly, parent, mono_string_to_utf8 (rmb.name), sig);
+ } else {
+ g_error ("requested method token for %s\n", klass->name);
+ }
+
+ return token;
+}
+
/*
* mono_image_create_token:
* @assembly: a dynamic assembly
@@ -2109,60 +4074,103 @@ mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *s
* TypeBuilder
*/
guint32
-mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
+mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
{
MonoClass *klass;
- guint32 token;
+ guint32 token = 0;
- if (!obj)
- g_error ("System.Array methods not yet supported");
-
klass = obj->vtable->klass;
if (strcmp (klass->name, "MethodBuilder") == 0) {
MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+
+ if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ else
+ token = mono_image_get_methodbuilder_token (assembly, mb);
/*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- return token;
- }
- if (strcmp (klass->name, "ConstructorBuilder") == 0) {
+ } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
- token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+
+ if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ else
+ token = mono_image_get_ctorbuilder_token (assembly, mb);
/*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
- return token;
- }
- if (strcmp (klass->name, "FieldBuilder") == 0) {
- MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
- return mb->table_idx | MONO_TOKEN_FIELD_DEF;
- }
- if (strcmp (klass->name, "TypeBuilder") == 0) {
+ } else if (strcmp (klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
+ if (tb->generic_params) {
+ token = mono_image_get_generic_field_token (assembly, fb);
+ } else {
+ token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
+ }
+ } else if (strcmp (klass->name, "TypeBuilder") == 0) {
MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
- return tb->table_idx | MONO_TOKEN_TYPE_DEF;
- }
- if (strcmp (klass->name, "MonoType") == 0) {
+ token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
+ } else if (strcmp (klass->name, "MonoType") == 0 ||
+ strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
MonoReflectionType *tb = (MonoReflectionType *)obj;
- return mono_metadata_token_from_dor (
+ token = mono_metadata_token_from_dor (
mono_image_typedef_or_ref (assembly, tb->type));
- }
- if (strcmp (klass->name, "MonoCMethod") == 0 ||
+ } 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;
- token = mono_image_get_methodref_token (assembly, m->method);
+ if (m->method->signature->is_inflated) {
+ if (create_methodspec)
+ token = mono_image_get_methodspec_token (assembly, m->method);
+ else
+ token = mono_image_get_inflated_method_token (assembly, m->method);
+ } else if (m->method->signature->generic_param_count) {
+ g_assert_not_reached ();
+ } else if ((m->method->klass->image == &assembly->image) &&
+ !m->method->klass->generic_inst) {
+ static guint32 method_table_idx = 0xffffff;
+ if (m->method->klass->wastypebuilder) {
+ /* we use the same token as the one that was assigned
+ * to the Methodbuilder.
+ * FIXME: do the equivalent for Fields.
+ */
+ token = m->method->token;
+ } else {
+ /*
+ * Each token should have a unique index, but the indexes are
+ * assigned by managed code, so we don't know about them. An
+ * easy solution is to count backwards...
+ */
+ method_table_idx --;
+ token = MONO_TOKEN_METHOD_DEF | method_table_idx;
+ }
+ } else {
+ token = mono_image_get_methodref_token (assembly, m->method);
+ }
/*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
- return token;
- }
- if (strcmp (klass->name, "MonoField") == 0) {
+ } else if (strcmp (klass->name, "MonoField") == 0) {
MonoReflectionField *f = (MonoReflectionField *)obj;
- token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
+ if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
+ 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);
+ }
/*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
- return token;
- }
- if (strcmp (klass->name, "MonoArrayMethod") == 0) {
+ } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
token = mono_image_get_array_token (assembly, m);
- return token;
+ } else if (strcmp (klass->name, "SignatureHelper") == 0) {
+ MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
+ token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
+ } else {
+ g_error ("requested token for %s\n", klass->name);
}
- g_print ("requested token for %s\n", klass->name);
- return 0;
+
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
+
+ return token;
}
typedef struct {
@@ -2178,8 +4186,77 @@ typedef struct {
guint32 flags;
} MonoILT;
+static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
+
+static MonoDynamicImage*
+create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
+{
+ static const guchar entrycode [16] = {0xff, 0x25, 0};
+ MonoDynamicImage *image;
+ int i;
+
+ const char *version = mono_get_runtime_version ();
+
+#if HAVE_BOEHM_GC
+ image = GC_MALLOC (sizeof (MonoDynamicImage));
+#else
+ image = g_new0 (MonoDynamicImage, 1);
+#endif
+
+ /* keep in sync with image.c */
+ image->image.name = assembly_name;
+ 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;
+
+ mono_image_init (&image->image);
+
+ image->token_fixups = mono_g_hash_table_new (NULL, NULL);
+ image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
+ image->field_to_table_idx = mono_g_hash_table_new (NULL, 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);
+ image->gen_params = g_ptr_array_new ();
+
+ string_heap_init (&image->sheap);
+ mono_image_add_stream_data (&image->us, "", 1);
+ add_to_blob_cached (image, (char*) "", 1, NULL, 0);
+ /* import tables... */
+ mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
+ image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
+ image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
+ image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
+ mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
+ mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
+ image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
+ stream_data_align (&image->code);
+
+ image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
+
+ for (i=0; i < 64; ++i) {
+ image->tables [i].next_idx = 1;
+ image->tables [i].columns = table_sizes [i];
+ }
+
+ image->image.assembly = (MonoAssembly*)assembly;
+ image->run = assembly->run;
+ image->save = assembly->save;
+ image->pe_kind = 0x1; /* ILOnly */
+ image->machine = 0x14c; /* I386 */
+
+ return image;
+}
+
/*
- * mono_image_basic_ini:
+ * mono_image_basic_init:
* @assembly: an assembly builder object
*
* Create the MonoImage that represents the assembly builder and setup some
@@ -2188,61 +4265,42 @@ typedef struct {
void
mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
{
- static const guchar entrycode [16] = {0xff, 0x25, 0};
MonoDynamicAssembly *assembly;
- MonoImage *image;
- int i;
+ MonoDynamicImage *image;
+ MONO_ARCH_SAVE_REGS;
+
if (assemblyb->dynamic_assembly)
return;
#if HAVE_BOEHM_GC
- assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
+ assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
#else
- assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
+ assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
#endif
- assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
- assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
- assembly->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
-
- string_heap_init (&assembly->sheap);
- mono_image_add_stream_data (&assembly->us, "", 1);
- mono_image_add_stream_data (&assembly->blob, "", 1);
- /* import tables... */
- mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
- assembly->iat_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two IAT entries */
- assembly->idt_offset = mono_image_add_stream_zero (&assembly->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
- mono_image_add_stream_zero (&assembly->code, 2); /* flags for name entry */
- assembly->imp_names_offset = mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
- mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
- assembly->ilt_offset = mono_image_add_stream_zero (&assembly->code, 8); /* two ILT entries */
- stream_data_align (&assembly->code);
-
- assembly->cli_header_offset = mono_image_add_stream_zero (&assembly->code, sizeof (MonoCLIHeader));
-
- for (i=0; i < 64; ++i) {
- assembly->tables [i].next_idx = 1;
- assembly->tables [i].columns = table_sizes [i];
- }
+ assembly->assembly.dynamic = TRUE;
+ assemblyb->assembly.assembly = (MonoAssembly*)assembly;
+ assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
+ if (assemblyb->culture)
+ assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
+ else
+ assembly->assembly.aname.culture = g_strdup ("");
- image = g_new0 (MonoImage, 1);
-
- /* keep in sync with image.c */
- image->name = mono_string_to_utf8 (assemblyb->name);
- image->assembly_name = image->name; /* they may be different */
+ assembly->run = assemblyb->access != 2;
+ assembly->save = assemblyb->access != 1;
- image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
- image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
- image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
- image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+ image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
+ image->initial_image = TRUE;
+ assembly->assembly.aname.name = image->image.name;
+ assembly->assembly.image = &image->image;
- assembly->assembly.image = image;
-
+ register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
+ mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
}
static int
-calc_section_size (MonoDynamicAssembly *assembly)
+calc_section_size (MonoDynamicImage *assembly)
{
int nsections = 0;
@@ -2251,11 +4309,21 @@ calc_section_size (MonoDynamicAssembly *assembly)
assembly->code.index &= ~3;
assembly->meta_size += 3;
assembly->meta_size &= ~3;
+ assembly->resources.index += 3;
+ assembly->resources.index &= ~3;
- assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index;
+ assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
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++;
@@ -2263,28 +4331,249 @@ calc_section_size (MonoDynamicAssembly *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:
- * @assemblyb: an assembly builder object
+ * @mb: a module builder object
*
- * When we need to save an assembly, we first call this function that ensures the metadata
- * tables are built for all the modules in the assembly. This function creates the PE-COFF
- * header, the image sections, the CLI header etc. all the data is written in
+ * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
* assembly->pefile where it can be easily retrieved later in chunks.
*/
void
-mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
+mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
MonoMSDOSHeader *msdos;
MonoDotNetHeader *header;
MonoSectionTable *section;
MonoCLIHeader *cli_header;
- guint32 size, image_size, virtual_base;
+ guint32 size, image_size, virtual_base, text_offset;
guint32 header_start, section_start, file_offset, virtual_offset;
- MonoDynamicAssembly *assembly;
+ MonoDynamicImage *assembly;
+ MonoReflectionAssemblyBuilder *assemblyb;
MonoDynamicStream *pefile;
int i, nsections;
- guint32 *rva;
+ guint32 *rva, value;
guint16 *data16;
+ guchar *p;
static const unsigned char msheader[] = {
0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -2296,14 +4585,39 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ assemblyb = mb->assemblyb;
+
mono_image_basic_init (assemblyb);
- assembly = assemblyb->dynamic_assembly;
+ assembly = mb->dynamic_image;
+
+ assembly->pe_kind = assemblyb->pe_kind;
+ assembly->machine = assemblyb->machine;
+ ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
+ ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
/* already created */
if (assembly->pefile.index)
return;
- mono_image_build_metadata (assemblyb);
+ mono_image_build_metadata (mb);
+
+ if (mb->is_main && assemblyb->resources) {
+ int len = mono_array_length (assemblyb->resources);
+ for (i = 0; i < len; ++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;
@@ -2355,14 +4669,17 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
header->pesig [0] = 'P';
header->pesig [1] = 'E';
- header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
+ header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
header->coff.coff_sections = GUINT16_FROM_LE (nsections);
header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
- /* it's an exe */
- header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
- /* FIXME: it's a dll */
- /*header->coff.coff_attributes = GUINT16_FROM_LE (0x210e); */
+ if (assemblyb->pekind == 1) {
+ /* it's a dll */
+ header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
+ } else {
+ /* it's an exe */
+ header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
+ }
virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
@@ -2372,16 +4689,16 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
size = assembly->sections [MONO_SECTION_TEXT].size;
size += FILE_ALIGN - 1;
size &= ~(FILE_ALIGN - 1);
- header->pe.pe_code_size = size;
+ header->pe.pe_code_size = GUINT32_FROM_LE(size);
size = assembly->sections [MONO_SECTION_RSRC].size;
size += FILE_ALIGN - 1;
size &= ~(FILE_ALIGN - 1);
- header->pe.pe_data_size = size;
+ header->pe.pe_data_size = GUINT32_FROM_LE(size);
g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
- header->pe.pe_rva_code_base = assembly->sections [MONO_SECTION_TEXT].rva;
- header->pe.pe_rva_data_base = assembly->sections [MONO_SECTION_RSRC].rva;
+ header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
+ header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
/* pe_rva_entry_point always at the beginning of the text section */
- header->pe.pe_rva_entry_point = assembly->sections [MONO_SECTION_TEXT].rva;
+ header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
@@ -2397,7 +4714,29 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
size += VIRT_ALIGN - 1;
size &= ~(VIRT_ALIGN - 1);
header->nt.pe_image_size = GUINT32_FROM_LE (size);
- header->nt.pe_subsys_required = GUINT16_FROM_LE (3); /* 3 -> cmdline app, 2 -> GUI app */
+
+ /*
+ // Translate the PEFileKind value to the value expected by the Windows loader
+ */
+ {
+ short kind;
+
+ /*
+ // PEFileKinds.Dll == 1
+ // PEFileKinds.ConsoleApplication == 2
+ // PEFileKinds.WindowApplication == 3
+ //
+ // need to get:
+ // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
+ // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
+ */
+ if (assemblyb->pekind == 3)
+ kind = 2;
+ else
+ kind = 3;
+
+ header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
+ }
header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
@@ -2417,6 +4756,11 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
+ /* patch entrypoint name */
+ if (assemblyb->pekind == 1)
+ memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
+ else
+ memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
/* patch imported function RVA name */
rva = (guint32*)(assembly->code.data + assembly->iat_offset);
*rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
@@ -2426,26 +4770,49 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
/* patch imported dll RVA name and other entries in the dir */
rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
+ *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
*rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
*rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
- rva = (guint32*)(assembly->code.data + assembly->ilt_offset);
- *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset - 2);
+ p = (assembly->code.data + assembly->ilt_offset);
+ value = (assembly->text_rva + assembly->imp_names_offset);
+ *p++ = (value) & 0xff;
+ *p++ = (value >> 8) & (0xff);
+ *p++ = (value >> 16) & (0xff);
+ *p++ = (value >> 24) & (0xff);
/* the CLI header info */
cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
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);
- else
+ cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
+ 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);
- cli_header->ch_metadata.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->code.index);
+ }
+ /* The embedded managed resources */
+ text_offset = assembly->text_rva + assembly->code.index;
+ cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
+ cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
+ text_offset += assembly->resources.index;
+ cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
+ text_offset += assembly->meta_size;
+ if (assembly->strong_name_size) {
+ cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
+ cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
+ text_offset += assembly->strong_name_size;
+ }
/* write the section tables and section content */
section = (MonoSectionTable*)(pefile->data + section_start);
@@ -2466,10 +4833,23 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
switch (i) {
case MONO_SECTION_TEXT:
/* patch entry point */
- rva = (guint32*)(assembly->code.data + 2);
- *rva = GUINT32_FROM_LE (virtual_base + assembly->text_rva + assembly->iat_offset);
- memcpy (pefile->data + assembly->sections [i].offset, assembly->code.data, assembly->code.index);
- memcpy (pefile->data + assembly->sections [i].offset + assembly->code.index, assembly->assembly.image->raw_metadata, assembly->meta_size);
+ p = (assembly->code.data + 2);
+ value = (virtual_base + assembly->text_rva + assembly->iat_offset);
+ *p++ = (value) & 0xff;
+ *p++ = (value >> 8) & 0xff;
+ *p++ = (value >> 16) & 0xff;
+ *p++ = (value >> 24) & 0xff;
+
+ text_offset = assembly->sections [i].offset;
+ memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
+ text_offset += assembly->code.index;
+ memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
+ text_offset += assembly->resources.index;
+ memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
+ text_offset += assembly->meta_size;
+ memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
+
+ g_free (assembly->image.raw_metadata);
break;
case MONO_SECTION_RELOC:
rva = (guint32*)(pefile->data + assembly->sections [i].offset);
@@ -2488,6 +4868,15 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
*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 ();
}
@@ -2504,27 +4893,145 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
#endif
}
+MonoReflectionModule *
+mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
+{
+ char *name;
+ MonoImage *image;
+ MonoImageOpenStatus status;
+ MonoDynamicAssembly *assembly;
+ guint32 module_count;
+ MonoImage **new_modules;
+
+ 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;
+
+ module_count = image->assembly->image->module_count;
+ new_modules = g_new0 (MonoImage *, module_count + 1);
+
+ if (image->assembly->image->modules)
+ memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
+ new_modules [module_count] = image;
+
+ g_free (image->assembly->image->modules);
+ image->assembly->image->modules = new_modules;
+ image->assembly->image->module_count ++;
+
+ 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.
* type uses a different hash, since it uses custom hash/equal functions.
*/
-static MonoGHashTable *object_cache = NULL;
-static MonoGHashTable *type_cache = NULL;
-#define CHECK_OBJECT(t,p) \
+typedef struct {
+ gpointer item;
+ MonoClass *refclass;
+} ReflectedEntry;
+
+static gboolean
+reflected_equal (gconstpointer a, gconstpointer b) {
+ const ReflectedEntry *ea = a;
+ const ReflectedEntry *eb = b;
+
+ return (ea->item == eb->item) && (ea->refclass == eb->refclass);
+}
+
+static guint
+reflected_hash (gconstpointer a) {
+ const ReflectedEntry *ea = a;
+ return GPOINTER_TO_UINT (ea->item);
+}
+
+#define CHECK_OBJECT(t,p,k) \
do { \
t _obj; \
- if (!object_cache) \
- object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal); \
- if ((_obj = mono_g_hash_table_lookup (object_cache, (p)))) \
+ ReflectedEntry e; \
+ e.item = (p); \
+ e.refclass = (k); \
+ mono_domain_lock (domain); \
+ if (!domain->refobject_hash) \
+ domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
+ if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
+ mono_domain_unlock (domain); \
return _obj; \
+ } \
} while (0)
-#define CACHE_OBJECT(p,o) \
+#if HAVE_BOEHM_GC
+#define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
+#else
+#define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
+#endif
+
+#define CACHE_OBJECT(p,o,k) \
do { \
- mono_g_hash_table_insert (object_cache, p,o); \
+ ReflectedEntry *e = ALLOC_REFENTRY; \
+ e->item = (p); \
+ e->refclass = (k); \
+ mono_g_hash_table_insert (domain->refobject_hash, e,o); \
+ mono_domain_unlock (domain); \
} while (0)
+static void
+register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
+{
+ /* this is done only once */
+ mono_domain_lock (domain);
+ CACHE_OBJECT (assembly, res, NULL);
+}
+
+static void
+register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
+{
+ /* this is done only once */
+ mono_domain_lock (domain);
+ CACHE_OBJECT (module, res, NULL);
+}
+
+void
+mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
+{
+ MonoDynamicImage *image = moduleb->dynamic_image;
+ MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
+ if (!image) {
+ /*
+ * FIXME: we already created an image in mono_image_basic_init (), but
+ * we don't know which module it belongs to, since that is only
+ * determined at assembly save time.
+ */
+ /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
+ image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
+
+ moduleb->module.image = &image->image;
+ moduleb->dynamic_image = image;
+ register_module (mono_object_domain (moduleb), moduleb, image);
+ }
+}
+
/*
* mono_assembly_get_object:
* @domain: an app domain
@@ -2538,13 +5045,98 @@ mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
static MonoClass *System_Reflection_Assembly;
MonoReflectionAssembly *res;
- CHECK_OBJECT (MonoReflectionAssembly *, assembly);
+ CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
if (!System_Reflection_Assembly)
System_Reflection_Assembly = mono_class_from_name (
mono_defaults.corlib, "System.Reflection", "Assembly");
res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
res->assembly = assembly;
- CACHE_OBJECT (assembly, res);
+ CACHE_OBJECT (assembly, res, NULL);
+ return res;
+}
+
+
+
+MonoReflectionModule*
+mono_module_get_object (MonoDomain *domain, MonoImage *image)
+{
+ static MonoClass *System_Reflection_Module;
+ MonoReflectionModule *res;
+ char* basename;
+
+ CHECK_OBJECT (MonoReflectionModule *, image, NULL);
+ if (!System_Reflection_Module)
+ System_Reflection_Module = mono_class_from_name (
+ mono_defaults.corlib, "System.Reflection", "Module");
+ res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
+
+ res->image = 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, basename = g_path_get_basename (image->name));
+ res->scopename = mono_string_new (domain, image->module_name);
+
+ g_free (basename);
+
+ if (image->assembly->image == image) {
+ res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
+ } else {
+ int i;
+ g_assert (image->assembly->image->modules);
+ res->token = 0;
+ for (i = 0; i < image->assembly->image->module_count; i++) {
+ if (image->assembly->image->modules [i] == image)
+ res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
+ }
+ g_assert (res->token);
+ }
+
+ mono_image_addref (image);
+
+ CACHE_OBJECT (image, res, NULL);
+ return res;
+}
+
+MonoReflectionModule*
+mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
+{
+ static MonoClass *System_Reflection_Module;
+ MonoReflectionModule *res;
+ MonoTableInfo *table;
+ guint32 cols [MONO_FILE_SIZE];
+ const char *name;
+ guint32 i, name_idx;
+ const char *val;
+
+ if (!System_Reflection_Module)
+ System_Reflection_Module = mono_class_from_name (
+ mono_defaults.corlib, "System.Reflection", "Module");
+ res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
+
+ table = &image->tables [MONO_TABLE_FILE];
+ g_assert (table_index < table->rows);
+ mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
+
+ res->image = 0;
+ res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
+ name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
+
+ /* Check whenever the row has a corresponding row in the moduleref table */
+ table = &image->tables [MONO_TABLE_MODULEREF];
+ for (i = 0; i < table->rows; ++i) {
+ name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
+ val = mono_metadata_string_heap (image, name_idx);
+ if (strcmp (val, name) == 0)
+ res->image = image->modules [i];
+ }
+
+ res->fqname = mono_string_new (domain, name);
+ res->name = mono_string_new (domain, name);
+ res->scopename = mono_string_new (domain, name);
+ res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
+ res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
+
return res;
}
@@ -2573,17 +5165,33 @@ mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_OBJECT:
+ case MONO_TYPE_TYPEDBYREF:
return TRUE;
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
+ case MONO_TYPE_SZARRAY:
return t1->data.klass == t2->data.klass;
case MONO_TYPE_PTR:
- case MONO_TYPE_SZARRAY:
return mymono_metadata_type_equal (t1->data.type, t2->data.type);
case MONO_TYPE_ARRAY:
if (t1->data.array->rank != t2->data.array->rank)
return FALSE;
- return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
+ return t1->data.array->eklass == t2->data.array->eklass;
+ case MONO_TYPE_GENERICINST: {
+ int i;
+ if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
+ return FALSE;
+ if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
+ return FALSE;
+ for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
+ if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
+ return FALSE;
+ }
+ return TRUE;
+ }
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ return t1->data.generic_param == t2->data.generic_param;
default:
g_error ("implement type compare for %0x!", t1->type);
return FALSE;
@@ -2603,15 +5211,45 @@ mymono_metadata_type_hash (MonoType *t1)
switch (t1->type) {
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
+ case MONO_TYPE_SZARRAY:
/* check if the distribution is good enough */
- return hash << 7 | g_str_hash (t1->data.klass->name);
+ return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
case MONO_TYPE_PTR:
- case MONO_TYPE_SZARRAY:
- return hash << 7 | mymono_metadata_type_hash (t1->data.type);
+ return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
}
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
@@ -2625,20 +5263,33 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
MonoReflectionType *res;
MonoClass *klass = mono_class_from_mono_type (type);
- if (!type_cache)
- type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
+ mono_domain_lock (domain);
+ if (!domain->type_hash)
+ domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
(GCompareFunc)mymono_metadata_type_equal);
- if ((res = mono_g_hash_table_lookup (type_cache, type)))
+ if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
+ mono_domain_unlock (domain);
return res;
- if (klass->reflection_info) {
+ }
+ 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? */
- if (!type->byref)
+ if (!type->byref) {
+ mono_domain_unlock (domain);
return klass->reflection_info;
+ }
}
mono_class_init (klass);
res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
res->type = type;
- mono_g_hash_table_insert (type_cache, type, res);
+ mono_g_hash_table_insert (domain->type_hash, type, res);
+ mono_domain_unlock (domain);
return res;
}
@@ -2646,11 +5297,12 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
* mono_method_get_object:
* @domain: an app domain
* @method: a method
+ * @refclass: the reflected type (can be NULL)
*
* Return an System.Reflection.MonoMethod object representing the method @method.
*/
MonoReflectionMethod*
-mono_method_get_object (MonoDomain *domain, MonoMethod *method)
+mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
{
/*
* We use the same C representation for methods and constructors, but the type
@@ -2660,7 +5312,10 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method)
MonoClass *klass;
MonoReflectionMethod *ret;
- CHECK_OBJECT (MonoReflectionMethod *, method);
+ if (!refclass)
+ refclass = method->klass;
+
+ CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
cname = "MonoCMethod";
else
@@ -2670,7 +5325,8 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method)
ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
ret->method = method;
ret->name = mono_string_new (domain, method->name);
- CACHE_OBJECT (method, ret);
+ ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
+ CACHE_OBJECT (method, ret, refclass);
return ret;
}
@@ -2689,12 +5345,18 @@ mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *fie
MonoReflectionField *res;
MonoClass *oklass;
- CHECK_OBJECT (MonoReflectionField *, field);
+ CHECK_OBJECT (MonoReflectionField *, field, klass);
oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
res = (MonoReflectionField *)mono_object_new (domain, oklass);
res->klass = klass;
res->field = field;
- CACHE_OBJECT (field, res);
+ res->name = mono_string_new (domain, field->name);
+ if (field->generic_info)
+ res->attrs = field->generic_info->generic_type->attrs;
+ else
+ res->attrs = field->type->attrs;
+ res->type = mono_type_get_object (domain, field->type);
+ CACHE_OBJECT (field, res, klass);
return res;
}
@@ -2713,12 +5375,12 @@ mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *pr
MonoReflectionProperty *res;
MonoClass *oklass;
- CHECK_OBJECT (MonoReflectionProperty *, property);
+ CHECK_OBJECT (MonoReflectionProperty *, property, klass);
oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
res->klass = klass;
res->property = property;
- CACHE_OBJECT (property, res);
+ CACHE_OBJECT (property, res, klass);
return res;
}
@@ -2737,12 +5399,12 @@ mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
MonoReflectionEvent *res;
MonoClass *oklass;
- CHECK_OBJECT (MonoReflectionEvent *, event);
+ CHECK_OBJECT (MonoReflectionEvent *, event, klass);
oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
res->klass = klass;
res->event = event;
- CACHE_OBJECT (event, res);
+ CACHE_OBJECT (event, res, klass);
return res;
}
@@ -2754,47 +5416,327 @@ mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
* Return an System.Reflection.ParameterInfo array object representing the parameters
* in the method @method.
*/
-MonoReflectionParameter**
+MonoArray*
mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
{
- MonoReflectionParameter **res;
- MonoReflectionMethod *member;
- MonoClass *oklass;
- char **names;
+ static MonoClass *System_Reflection_ParameterInfo;
+ MonoArray *res = NULL;
+ MonoReflectionMethod *member = NULL;
+ MonoReflectionParameter *param = NULL;
+ char **names, **blobs = NULL;
+ MonoObject *dbnull = mono_get_dbnull_object (domain);
+ MonoMarshalSpec **mspecs;
int i;
+ if (!System_Reflection_ParameterInfo)
+ System_Reflection_ParameterInfo = mono_class_from_name (
+ mono_defaults.corlib, "System.Reflection", "ParameterInfo");
+
if (!method->signature->param_count)
- return NULL;
+ return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
- member = mono_method_get_object (domain, method);
- names = g_new (char *, method->signature->param_count);
- mono_method_get_param_names (method, (const char **) names);
-
/* Note: the cache is based on the address of the signature into the method
* since we already cache MethodInfos with the method as keys.
*/
- CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
- oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
-#if HAVE_BOEHM_GC
- res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
-#else
- res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
-#endif
+ CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
+
+ member = mono_method_get_object (domain, method, NULL);
+ names = g_new (char *, method->signature->param_count);
+ mono_method_get_param_names (method, (const char **) names);
+
+ mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
+ mono_method_get_marshal_info (method, mspecs);
+
+ res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
for (i = 0; i < method->signature->param_count; ++i) {
- res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
- res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
- res [i]->DefaultValueImpl = NULL; /* FIXME */
- res [i]->MemberImpl = (MonoObject*)member;
- res [i]->NameImpl = mono_string_new (domain, names [i]);
- res [i]->PositionImpl = i + 1;
- res [i]->AttrsImpl = method->signature->params [i]->attrs;
+ param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
+ param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
+ param->MemberImpl = (MonoObject*)member;
+ param->NameImpl = mono_string_new (domain, names [i]);
+ param->PositionImpl = i;
+ param->AttrsImpl = method->signature->params [i]->attrs;
+
+ if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
+ param->DefaultValueImpl = dbnull;
+ } else {
+ MonoType *type = param->ClassImpl->type;
+
+ if (!blobs) {
+ blobs = g_new0 (char *, method->signature->param_count);
+ get_default_param_value_blobs (method, blobs);
+ }
+
+ param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
+
+ if (!param->DefaultValueImpl) {
+ param->DefaultValueImpl = dbnull;
+ }
+ }
+
+ if (mspecs [i + 1])
+ param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
+
+ mono_array_set (res, gpointer, i, param);
}
g_free (names);
- CACHE_OBJECT (&(method->signature), res);
+ g_free (blobs);
+
+ for (i = method->signature->param_count; i >= 0; i--)
+ if (mspecs [i])
+ mono_metadata_free_marshal_spec (mspecs [i]);
+ g_free (mspecs);
+
+ CACHE_OBJECT (&(method->signature), res, NULL);
return res;
}
/*
+ * mono_method_body_get_object:
+ * @domain: an app domain
+ * @method: a method
+ *
+ * Return an System.Reflection.MethodBody object representing the method @method.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
+{
+ static MonoClass *System_Reflection_MethodBody = NULL;
+ static MonoClass *System_Reflection_LocalVariableInfo = NULL;
+ MonoReflectionMethodBody *ret;
+ MonoMethodNormal *mn;
+ MonoMethodHeader *header;
+ int i;
+
+ if (!System_Reflection_MethodBody)
+ System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
+ if (!System_Reflection_LocalVariableInfo)
+ System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
+
+ CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
+
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+ return NULL;
+ mn = (MonoMethodNormal *)method;
+ header = mono_method_get_header (method);
+
+ ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
+ /* FIXME: Other fields */
+ ret->init_locals = header->init_locals;
+ ret->max_stack = header->max_stack;
+ ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
+ memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
+ ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
+ for (i = 0; i < header->num_locals; ++i) {
+ MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
+ info->local_type = mono_type_get_object (domain, header->locals [i]);
+ info->is_pinned = header->locals [i]->pinned;
+ info->local_index = 0;
+ }
+
+ CACHE_OBJECT (method, ret, NULL);
+ return ret;
+}
+
+MonoObject *
+mono_get_dbnull_object (MonoDomain *domain)
+{
+ MonoObject *obj;
+ MonoClass *klass;
+ static MonoClassField *dbnull_value_field = NULL;
+
+ if (!dbnull_value_field) {
+ klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
+ mono_class_init (klass);
+ dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
+ g_assert (dbnull_value_field);
+ }
+ obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
+ g_assert (obj);
+ return obj;
+}
+
+
+static void
+get_default_param_value_blobs (MonoMethod *method, char **blobs)
+{
+ guint32 param_index, i, lastp, crow = 0;
+ guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
+ gint32 idx = -1;
+
+ MonoClass *klass = method->klass;
+ MonoImage *image = klass->image;
+ MonoMethodSignature *methodsig = method->signature;
+
+ MonoTableInfo *constt;
+ MonoTableInfo *methodt;
+ MonoTableInfo *paramt;
+
+ if (!methodsig->param_count)
+ return;
+
+ if (klass->generic_inst) {
+ return; /* FIXME - ??? */
+ }
+
+ mono_class_init (klass);
+
+ if (klass->image->dynamic) {
+ MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+ if (aux && aux->param_defaults)
+ memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
+ return;
+ }
+
+ methodt = &klass->image->tables [MONO_TABLE_METHOD];
+ paramt = &klass->image->tables [MONO_TABLE_PARAM];
+ constt = &image->tables [MONO_TABLE_CONSTANT];
+
+ for (i = 0; i < klass->method.count; ++i) {
+ if (method == klass->methods [i]) {
+ idx = klass->method.first + i;
+ break;
+ }
+ }
+
+ g_assert (idx != -1);
+
+ param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
+ if (idx + 1 < methodt->rows)
+ lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
+ else
+ lastp = paramt->rows + 1;
+
+ for (i = param_index; i < lastp; ++i) {
+ guint32 paramseq;
+
+ mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
+ paramseq = param_cols [MONO_PARAM_SEQUENCE];
+
+ if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
+ continue;
+
+ crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
+ if (!crow) {
+ continue;
+ }
+
+ mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
+ blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
+ }
+
+ return;
+}
+
+static MonoObject *
+mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
+{
+ void *retval;
+ MonoClass *klass;
+ MonoObject *object;
+
+ if (!blob)
+ return NULL;
+
+ klass = mono_class_from_mono_type (type);
+ if (klass->valuetype) {
+ object = mono_object_new (domain, klass);
+ retval = ((gchar *) object + sizeof (MonoObject));
+ } else {
+ retval = &object;
+ }
+
+ if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
+ return object;
+ else
+ return NULL;
+}
+
+static int
+assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
+ int found_sep;
+ char *s;
+
+ memset (assembly, 0, sizeof (MonoAssemblyName));
+ assembly->name = p;
+ assembly->culture = "";
+ memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
+
+ while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
+ p++;
+ found_sep = 0;
+ while (*p == ' ' || *p == ',') {
+ *p++ = 0;
+ found_sep = 1;
+ continue;
+ }
+ /* failed */
+ if (!found_sep)
+ return 1;
+ while (*p) {
+ if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
+ p += 8;
+ assembly->major = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->minor = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->build = strtoul (p, &s, 10);
+ if (s == p || *s != '.')
+ return 1;
+ p = ++s;
+ assembly->revision = strtoul (p, &s, 10);
+ if (s == p)
+ return 1;
+ p = s;
+ } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
+ p += 8;
+ if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
+ assembly->culture = "";
+ p += 7;
+ } else {
+ assembly->culture = p;
+ while (*p && *p != ',') {
+ p++;
+ }
+ }
+ } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
+ p += 15;
+ if (strncmp (p, "null", 4) == 0) {
+ p += 4;
+ } else {
+ int len;
+ gchar *start = p;
+ while (*p && *p != ',') {
+ p++;
+ }
+ len = (p - start + 1);
+ if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
+ len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
+ g_strlcpy (assembly->public_key_token, start, len);
+ }
+ } else {
+ while (*p && *p != ',')
+ p++;
+ }
+ found_sep = 0;
+ while (*p == ' ' || *p == ',') {
+ *p++ = 0;
+ found_sep = 1;
+ continue;
+ }
+ /* failed */
+ if (!found_sep)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
* mono_reflection_parse_type:
* @name: type name
*
@@ -2814,7 +5756,8 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
start = p = w = name;
- info->name = info->name_space = info->assembly = NULL;
+ memset (&info->assembly, 0, sizeof (MonoAssemblyName));
+ info->name = info->name_space = NULL;
info->nested = NULL;
info->modifiers = NULL;
@@ -2826,11 +5769,10 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
case '+':
*p = 0; /* NULL terminate the name */
startn = p + 1;
+ info->nested = g_list_append (info->nested, startn);
/* we have parsed the nesting namespace + name */
- if (info->name) {
- info->nested = g_list_append (info->nested, startn);
+ if (info->name)
break;
- }
if (last_point) {
info->name_space = start;
*last_point = 0;
@@ -2860,9 +5802,7 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
*w++ = *p++;
}
- if (info->name) {
- info->nested = g_list_append (info->nested, startn);
- } else {
+ if (!info->name) {
if (last_point) {
info->name_space = start;
*last_point = 0;
@@ -2912,12 +5852,14 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
}
if (!*p)
return 0; /* missing assembly name */
- info->assembly = p;
+ if (!assembly_name_to_aname (&info->assembly, p))
+ return 0;
break;
default:
+ return 0;
break;
}
- if (info->assembly)
+ if (info->assembly.name)
break;
}
*w = 0; /* terminate class name */
@@ -2927,75 +5869,8 @@ mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
return 1;
}
-static void
-mono_type_get_name_recurse (MonoType *type, GString *str)
-{
- MonoClass *klass;
-
- switch (type->type) {
- case MONO_TYPE_ARRAY: {
- int i, rank = type->data.array->rank;
-
- mono_type_get_name_recurse (type->data.array->type, str);
- g_string_append_c (str, '[');
- for (i = 1; i < rank; i++)
- g_string_append_c (str, ',');
- g_string_append_c (str, ']');
- break;
- }
- case MONO_TYPE_SZARRAY:
- mono_type_get_name_recurse (type->data.type, str);
- g_string_append (str, "[]");
- break;
- case MONO_TYPE_PTR:
- mono_type_get_name_recurse (type->data.type, str);
- g_string_append_c (str, '*');
- break;
- default:
- klass = mono_class_from_mono_type (type);
- if (klass->nested_in) {
- mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
- g_string_append_c (str, '+');
- }
- if (*klass->name_space) {
- g_string_append (str, klass->name_space);
- g_string_append_c (str, '.');
- }
- g_string_append (str, klass->name);
- break;
- }
-}
-
-/*
- * mono_type_get_name:
- * @type: a type
- *
- * Returns the string representation for type as required by System.Reflection.
- * The inverse of mono_reflection_parse_type ().
- */
-char*
-mono_type_get_name (MonoType *type)
-{
- GString* result = g_string_new ("");
- mono_type_get_name_recurse (type, result);
-
- if (type->byref)
- g_string_append_c (result, '&');
-
- return g_string_free (result, FALSE);
-}
-
-/*
- * mono_reflection_get_type:
- * @image: a metadata context
- * @info: type description structure
- * @ignorecase: flag for case-insensitive string compares
- *
- * Build a MonoType from the type description in @info.
- *
- */
-MonoType*
-mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
+static MonoType*
+mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
{
MonoClass *klass;
GList *mod;
@@ -3041,90 +5916,437 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
} else if (modval == -1) {
klass = mono_ptr_class_get (&klass->byval_arg);
} else { /* array rank */
- klass = mono_array_class_get (&klass->byval_arg, modval);
+ klass = mono_array_class_get (klass, modval);
}
mono_class_init (klass);
}
+
return &klass->byval_arg;
}
/*
- * Optimization we could avoid mallocing() an little-endian archs that
- * don't crash with unaligned accesses.
+ * mono_reflection_get_type:
+ * @image: a metadata context
+ * @info: type description structure
+ * @ignorecase: flag for case-insensitive string compares
+ * @type_resolve: whenever type resolve was already tried
+ *
+ * Build a MonoType from the type description in @info.
+ *
*/
-static void
-fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
- int len, i, slen, type;
- const char *p = mono_metadata_blob_heap (image, blobidx);
- len = mono_metadata_decode_value (p, &p);
- if (len < 2 || read16 (p) != 0x0001) /* Prolog */
- return;
+MonoType*
+mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
+{
+ MonoType *type;
+ MonoReflectionAssembly *assembly;
+ GString *fullName;
+ GList *mod;
- /* skip prolog */
- p += 2;
- for (i = 0; i < sig->param_count; ++i) {
- type = sig->params [i]->type;
-handle_enum:
- switch (type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN: {
- MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
- *bval = *p;
- ++p;
- break;
+ type = mono_reflection_get_type_internal (image, info, ignorecase);
+ if (type)
+ return type;
+ if (!mono_domain_has_type_resolve (mono_domain_get ()))
+ return NULL;
+
+ if (type_resolve) {
+ if (*type_resolve)
+ return NULL;
+ else
+ *type_resolve = TRUE;
+ }
+
+ /* Reconstruct the type name */
+ fullName = g_string_new ("");
+ if (info->name_space && (info->name_space [0] != '\0'))
+ g_string_printf (fullName, "%s.%s", info->name_space, info->name);
+ else
+ g_string_printf (fullName, info->name);
+ for (mod = info->nested; mod; mod = mod->next)
+ g_string_append_printf (fullName, "+%s", (char*)mod->data);
+
+ assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
+ if (assembly) {
+ 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;
+ }
+ }
}
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2: {
- guint16 *val = params [i] = g_malloc (sizeof (guint16));
- *val = read16 (p);
- p += 2;
- break;
+ else
+ type = mono_reflection_get_type_internal (assembly->assembly->image,
+ info, ignorecase);
+ }
+ g_string_free (fullName, TRUE);
+ return type;
+}
+
+/*
+ * mono_reflection_type_from_name:
+ * @name: type name.
+ * @image: a metadata context (can be NULL).
+ *
+ * Retrieves a MonoType from its @name. If the name is not fully qualified,
+ * it defaults to get the type from @image or, if @image is NULL or loading
+ * from it fails, uses corlib.
+ *
+ */
+MonoType*
+mono_reflection_type_from_name (char *name, MonoImage *image)
+{
+ MonoType *type;
+ MonoTypeNameParse info;
+ MonoAssembly *assembly;
+ char *tmp;
+ gboolean type_resolve = FALSE;
+
+ /* Make a copy since parse_type modifies its argument */
+ tmp = g_strdup (name);
+
+ /*g_print ("requested type %s\n", str);*/
+ if (!mono_reflection_parse_type (tmp, &info)) {
+ g_free (tmp);
+ g_list_free (info.modifiers);
+ g_list_free (info.nested);
+ return NULL;
+ }
+
+ if (info.assembly.name) {
+ assembly = mono_assembly_loaded (&info.assembly);
+ if (!assembly) {
+ /* then we must load the assembly ourselve - see #60439 */
+ assembly = mono_assembly_load (&info.assembly, NULL, NULL);
+ if (!assembly) {
+ g_free (tmp);
+ g_list_free (info.modifiers);
+ g_list_free (info.nested);
+ return NULL;
+ }
+ }
+ image = assembly->image;
+ } else if (image == NULL) {
+ image = mono_defaults.corlib;
+ }
+
+ type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
+ if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
+ image = mono_defaults.corlib;
+ type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
+ }
+
+ g_free (tmp);
+ g_list_free (info.modifiers);
+ g_list_free (info.nested);
+ return type;
+}
+
+/*
+ * mono_reflection_get_token:
+ *
+ * Return the metadata token of OBJ which should be an object
+ * representing a metadata element.
+ */
+guint32
+mono_reflection_get_token (MonoObject *obj)
+{
+ MonoClass *klass;
+ guint32 token = 0;
+
+ klass = obj->vtable->klass;
+
+ if (strcmp (klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
+
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
+ MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
+
+ token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
+ } else if (strcmp (klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
+ if (tb->generic_params) {
+ g_assert_not_reached ();
+ } else {
+ token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
}
+ } else if (strcmp (klass->name, "TypeBuilder") == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
+ token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
+ } else if (strcmp (klass->name, "MonoType") == 0) {
+ MonoReflectionType *tb = (MonoReflectionType *)obj;
+ token = mono_class_from_mono_type (tb->type)->type_token;
+ } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
+ strcmp (klass->name, "MonoMethod") == 0) {
+ MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
+ if (m->method->signature->is_inflated) {
+ g_assert_not_reached ();
+ } else if (m->method->signature->generic_param_count) {
+ g_assert_not_reached ();
+ } else if (m->method->klass->generic_inst) {
+ g_assert_not_reached ();
+ } else {
+ token = m->method->token;
+ }
+ } else if (strcmp (klass->name, "MonoField") == 0) {
+ MonoReflectionField *f = (MonoReflectionField*)obj;
+
+ token = mono_class_get_field_token (f->field);
+ } else if (strcmp (klass->name, "MonoProperty") == 0) {
+ MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
+
+ token = mono_class_get_property_token (p->property);
+ } else if (strcmp (klass->name, "MonoEvent") == 0) {
+ MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
+
+ token = mono_class_get_event_token (p->event);
+ } else if (strcmp (klass->name, "ParameterInfo") == 0) {
+ MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
+
+ token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
+ } else if (strcmp (klass->name, "Module") == 0) {
+ MonoReflectionModule *m = (MonoReflectionModule*)obj;
+
+ token = m->token;
+ } else if (strcmp (klass->name, "Assembly") == 0) {
+ token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
+ } else {
+ gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
+ MonoException *ex = mono_get_exception_not_implemented (msg);
+ g_free (msg);
+ mono_raise_exception (ex);
+ }
+
+ return token;
+}
+
+static void*
+load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
+{
+ int slen, type = t->type;
+handle_enum:
+ switch (type) {
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_BOOLEAN: {
+ MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
+ *bval = *p;
+ *end = p + 1;
+ return bval;
+ }
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2: {
+ guint16 *val = g_malloc (sizeof (guint16));
+ *val = read16 (p);
+ *end = p + 2;
+ return val;
+ }
#if SIZEOF_VOID_P == 4
- case MONO_TYPE_U:
- case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_I:
#endif
- case MONO_TYPE_R4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4: {
- guint32 *val = params [i] = g_malloc (sizeof (guint32));
- *val = read32 (p);
- p += 4;
- break;
- }
+ case MONO_TYPE_R4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4: {
+ guint32 *val = g_malloc (sizeof (guint32));
+ *val = read32 (p);
+ *end = p + 4;
+ return val;
+ }
#if SIZEOF_VOID_P == 8
- case MONO_TYPE_U: /* error out instead? this should probably not happen */
- case MONO_TYPE_I:
+ case MONO_TYPE_U: /* error out instead? this should probably not happen */
+ case MONO_TYPE_I:
#endif
- case MONO_TYPE_R8:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8: {
- guint64 *val = params [i] = g_malloc (sizeof (guint64));
- *val = read64 (p);
- p += 8;
- break;
+ case MONO_TYPE_R8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8: {
+ guint64 *val = g_malloc (sizeof (guint64));
+ *val = read64 (p);
+ *end = p + 8;
+ return val;
+ }
+ case MONO_TYPE_VALUETYPE:
+ if (t->data.klass->enumtype) {
+ type = t->data.klass->enum_basetype->type;
+ goto handle_enum;
+ } else {
+ g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
}
- case MONO_TYPE_VALUETYPE:
- if (sig->params [i]->data.klass->enumtype) {
- type = sig->params [i]->data.klass->enum_basetype->type;
- goto handle_enum;
- } else {
- g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
- }
- break;
- case MONO_TYPE_STRING: {
+ break;
+ case MONO_TYPE_STRING:
+ if (*p == (char)0xFF) {
+ *end = p + 1;
+ return NULL;
+ }
+ slen = mono_metadata_decode_value (p, &p);
+ *end = p + slen;
+ return mono_string_new_len (mono_domain_get (), p, slen);
+ case MONO_TYPE_CLASS: {
+ char *n;
+ MonoType *t;
+ if (*p == (char)0xFF) {
+ *end = p + 1;
+ return NULL;
+ }
+handle_type:
+ slen = mono_metadata_decode_value (p, &p);
+ n = g_memdup (p, slen + 1);
+ n [slen] = 0;
+ t = mono_reflection_type_from_name (n, image);
+ if (!t)
+ g_warning ("Cannot load type '%s'", n);
+ g_free (n);
+ *end = p + slen;
+ 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 = NULL;
+ void *val;
+
+ if (subt == 0x50) {
+ goto handle_type;
+ } else if (subt == 0x0E) {
+ type = MONO_TYPE_STRING;
+ goto handle_enum;
+ } else if (subt == 0x55) {
+ char *n;
+ MonoType *t;
slen = mono_metadata_decode_value (p, &p);
- params [i] = mono_string_new_len (mono_domain_get (), p, slen);
+ n = g_memdup (p, slen + 1);
+ n [slen] = 0;
+ t = mono_reflection_type_from_name (n, image);
+ if (!t)
+ g_warning ("Cannot load type '%s'", n);
+ g_free (n);
p += slen;
- break;
+ subc = mono_class_from_mono_type (t);
+ } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
+ MonoType simple_type = {{0}};
+ simple_type.type = subt;
+ subc = mono_class_from_mono_type (&simple_type);
+ } else {
+ g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
}
- default:
- g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
- break;
+ val = load_cattr_value (image, &subc->byval_arg, p, end);
+ obj = mono_object_new (mono_domain_get (), subc);
+ memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
+ g_free (val);
+ return obj;
+ }
+ case MONO_TYPE_SZARRAY: {
+ MonoArray *arr;
+ guint32 i, alen, basetype;
+ alen = read32 (p);
+ p += 4;
+ if (alen == 0xffffffff) {
+ *end = p;
+ return NULL;
+ }
+ arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
+ basetype = t->data.klass->byval_arg.type;
+ switch (basetype)
+ {
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_BOOLEAN:
+ for (i = 0; i < alen; i++) {
+ MonoBoolean val = *p++;
+ mono_array_set (arr, MonoBoolean, i, val);
+ }
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2:
+ for (i = 0; i < alen; i++) {
+ guint16 val = read16 (p);
+ mono_array_set (arr, guint16, i, val);
+ p += 2;
+ }
+ break;
+ case MONO_TYPE_R4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4:
+ for (i = 0; i < alen; i++) {
+ guint32 val = read32 (p);
+ mono_array_set (arr, guint32, i, val);
+ p += 4;
+ }
+ break;
+ case MONO_TYPE_R8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8:
+ for (i = 0; i < alen; i++) {
+ guint64 val = read64 (p);
+ mono_array_set (arr, guint64, i, val);
+ p += 8;
+ }
+ break;
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ for (i = 0; i < alen; i++) {
+ MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
+ mono_array_set (arr, gpointer, i, item);
+ }
+ break;
+ default:
+ g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
}
+ *end=p;
+ return arr;
+ }
+ default:
+ g_error ("Type 0x%02x not handled in custom attr value decoding", type);
+ }
+ return NULL;
+}
+
+static gboolean
+type_is_reference (MonoType *type)
+{
+ switch (type->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_VALUETYPE:
+ return FALSE;
+ default:
+ return TRUE;
}
}
@@ -3132,27 +6354,8 @@ static void
free_param_data (MonoMethodSignature *sig, void **params) {
int i;
for (i = 0; i < sig->param_count; ++i) {
- switch (sig->params [i]->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8:
- case MONO_TYPE_R4:
- case MONO_TYPE_VALUETYPE:
+ if (!type_is_reference (sig->params [i]))
g_free (params [i]);
- break;
- default:
- break;
- }
}
}
@@ -3214,6 +6417,311 @@ find_event_index (MonoClass *klass, MonoEvent *event) {
return 0;
}
+static MonoObject*
+create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
+{
+ const char *p = data;
+ const char *named;
+ guint32 i, j, num_named;
+ 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;
+
+ /*g_print ("got attr %s\n", method->klass->name);*/
+
+ params = g_new (void*, method->signature->param_count);
+
+ /* skip prolog */
+ p += 2;
+ for (i = 0; i < method->signature->param_count; ++i) {
+ params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
+ }
+
+ named = p;
+ attr = mono_object_new (mono_domain_get (), method->klass);
+ mono_runtime_invoke (method, attr, params, NULL);
+ free_param_data (method->signature, params);
+ g_free (params);
+ num_named = read16 (named);
+ named += 2;
+ for (j = 0; j < num_named; j++) {
+ gint name_len;
+ char *name, named_type, data_type;
+ named_type = *named++;
+ data_type = *named++; /* type of data */
+ if (data_type == 0x55) {
+ gint type_len;
+ char *type_name;
+ type_len = mono_metadata_decode_blob_size (named, &named);
+ type_name = g_malloc (type_len + 1);
+ memcpy (type_name, named, type_len);
+ type_name [type_len] = 0;
+ named += type_len;
+ /* FIXME: lookup the type and check type consistency */
+ } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
+ /* this seems to be the type of the element of the array */
+ /* g_print ("skipping 0x%02x after prop\n", *named); */
+ named++;
+ }
+ name_len = mono_metadata_decode_blob_size (named, &named);
+ name = g_malloc (name_len + 1);
+ memcpy (name, named, name_len);
+ name [name_len] = 0;
+ named += name_len;
+ if (named_type == 0x53) {
+ MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
+ void *val = load_cattr_value (image, field->type, named, &named);
+ mono_field_set_value (attr, field, val);
+ if (!type_is_reference (field->type))
+ g_free (val);
+ } else if (named_type == 0x54) {
+ MonoProperty *prop;
+ void *pparams [1];
+ MonoType *prop_type;
+
+ prop = mono_class_get_property_from_name (mono_object_class (attr), name);
+ /* can we have more that 1 arg in a custom attr named property? */
+ prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
+ pparams [0] = load_cattr_value (image, prop_type, named, &named);
+ mono_property_set_value (prop, attr, pparams, NULL);
+ if (!type_is_reference (prop_type))
+ g_free (pparams [0]);
+ }
+ g_free (name);
+ }
+
+ return attr;
+}
+
+MonoArray*
+mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
+{
+ MonoArray *result;
+ MonoClass *klass;
+ MonoObject *attr;
+ int i;
+
+ klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
+ result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
+ for (i = 0; i < cinfo->num_attrs; ++i) {
+ attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
+ mono_array_set (result, gpointer, i, attr);
+ }
+ return result;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
+{
+ guint32 mtoken, i, len;
+ guint32 cols [MONO_CUSTOM_ATTR_SIZE];
+ MonoTableInfo *ca;
+ MonoCustomAttrInfo *ainfo;
+ GList *tmp, *list = NULL;
+ const char *data;
+
+ ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+
+ i = mono_metadata_custom_attrs_from_index (image, idx);
+ if (!i)
+ return NULL;
+ i --;
+ while (i < ca->rows) {
+ if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
+ break;
+ list = g_list_prepend (list, GUINT_TO_POINTER (i));
+ ++i;
+ }
+ len = g_list_length (list);
+ if (!len)
+ return NULL;
+ ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
+ ainfo->num_attrs = len;
+ ainfo->image = image;
+ for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
+ mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
+ mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
+ switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
+ case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
+ mtoken |= MONO_TOKEN_METHOD_DEF;
+ break;
+ case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
+ mtoken |= MONO_TOKEN_MEMBER_REF;
+ break;
+ default:
+ g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
+ break;
+ }
+ ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
+ if (!ainfo->attrs [i].ctor)
+ g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
+ data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
+ ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
+ ainfo->attrs [i].data = data;
+ }
+ g_list_free (list);
+
+ return ainfo;
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_method (MonoMethod *method)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
+ return cinfo;
+ idx = find_method_index (method);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_METHODDEF;
+ return mono_custom_attrs_from_index (method->klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_class (MonoClass *klass)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
+ return cinfo;
+ idx = mono_metadata_token_index (klass->type_token);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_TYPEDEF;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_assembly (MonoAssembly *assembly)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
+ return cinfo;
+ idx = 1; /* there is only one assembly */
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_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 <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_MODULE;
+ return mono_custom_attrs_from_index (image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
+ return cinfo;
+ idx = find_property_index (klass, property);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_PROPERTY;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
+ return cinfo;
+ idx = find_event_index (klass, event);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_EVENT;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
+{
+ MonoCustomAttrInfo *cinfo;
+ guint32 idx;
+
+ if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
+ return cinfo;
+ idx = find_field_index (klass, field);
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_FIELDDEF;
+ return mono_custom_attrs_from_index (klass->image, idx);
+}
+
+MonoCustomAttrInfo*
+mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
+{
+ MonoTableInfo *ca;
+ guint32 i, idx, method_index;
+ guint32 param_list, param_last, param_pos, found;
+ MonoImage *image;
+ 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];
+
+ if (method->klass->generic_inst || method->klass->generic_container ||
+ method->signature->generic_param_count) {
+ /* FIXME FIXME FIXME */
+ return NULL;
+ }
+
+ param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
+ if (method_index == ca->rows) {
+ ca = &image->tables [MONO_TABLE_PARAM];
+ param_last = ca->rows + 1;
+ } else {
+ param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
+ ca = &image->tables [MONO_TABLE_PARAM];
+ }
+ found = FALSE;
+ for (i = param_list; i < param_last; ++i) {
+ param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
+ if (param_pos == param) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ return NULL;
+ idx = i;
+ idx <<= MONO_CUSTOM_ATTR_BITS;
+ idx |= MONO_CUSTOM_ATTR_PARAMDEF;
+ return mono_custom_attrs_from_index (image, idx);
+}
+
/*
* mono_reflection_get_custom_attrs:
* @obj: a reflection object handle
@@ -3224,158 +6732,110 @@ find_event_index (MonoClass *klass, MonoEvent *event) {
MonoArray*
mono_reflection_get_custom_attrs (MonoObject *obj)
{
- guint32 idx, mtoken, i, len;
- guint32 cols [MONO_CUSTOM_ATTR_SIZE];
MonoClass *klass;
- MonoImage *image;
- MonoTableInfo *ca;
- MonoMethod *method;
- MonoObject *attr;
MonoArray *result;
- GList *list = NULL;
- void **params;
+ MonoCustomAttrInfo *cinfo = NULL;
+ MONO_ARCH_SAVE_REGS;
+
klass = obj->vtable->klass;
- /* FIXME: need to handle: Module */
if (klass == mono_defaults.monotype_class) {
MonoReflectionType *rtype = (MonoReflectionType*)obj;
klass = mono_class_from_mono_type (rtype->type);
- idx = mono_metadata_token_index (klass->type_token);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_TYPEDEF;
- image = klass->image;
+ cinfo = mono_custom_attrs_from_class (klass);
} else if (strcmp ("Assembly", klass->name) == 0) {
MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
- idx = 1; /* there is only one assembly */
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_ASSEMBLY;
- image = rassembly->assembly->image;
+ 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;
- idx = find_property_index (rprop->klass, rprop->property);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_PROPERTY;
- image = rprop->klass->image;
+ cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
} else if (strcmp ("MonoEvent", klass->name) == 0) {
MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
- idx = find_event_index (revent->klass, revent->event);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_EVENT;
- image = revent->klass->image;
+ cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
} else if (strcmp ("MonoField", klass->name) == 0) {
MonoReflectionField *rfield = (MonoReflectionField*)obj;
- idx = find_field_index (rfield->klass, rfield->field);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_FIELDDEF;
- image = rfield->klass->image;
+ 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;
- idx = find_method_index (rmethod->method);
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_METHODDEF;
- image = rmethod->method->klass->image;
+ cinfo = mono_custom_attrs_from_method (rmethod->method);
} else if (strcmp ("ParameterInfo", klass->name) == 0) {
MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
- guint32 method_index = find_method_index (rmethod->method);
- guint32 param_list, param_last, param_pos, found;
-
- image = rmethod->method->klass->image;
- ca = &image->tables [MONO_TABLE_METHOD];
-
- param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
- if (method_index == ca->rows) {
- ca = &image->tables [MONO_TABLE_PARAM];
- param_last = ca->rows + 1;
- } else {
- param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
- ca = &image->tables [MONO_TABLE_PARAM];
- }
- found = 0;
- for (i = param_list; i < param_last; ++i) {
- param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
- if (param_pos == param->PositionImpl) {
- found = 1;
- break;
- }
- }
- if (!found)
- return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
- idx = i;
- idx <<= CUSTOM_ATTR_BITS;
- idx |= CUSTOM_ATTR_PARAMDEF;
+ cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
+ } 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);
}
- /* at this point image and index are set correctly for searching the custom attr */
- ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
- /* the table is not sorted */
- for (i = 0; i < ca->rows; ++i) {
- mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
- if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
- continue;
- mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
- switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
- case CUSTOM_ATTR_TYPE_METHODDEF:
- mtoken |= MONO_TOKEN_METHOD_DEF;
- break;
- case CUSTOM_ATTR_TYPE_MEMBERREF:
- mtoken |= MONO_TOKEN_MEMBER_REF;
- break;
- default:
- g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
- break;
- }
- method = mono_get_method (image, mtoken, NULL);
- if (!method)
- g_error ("Can't find custom attr constructor");
- mono_class_init (method->klass);
- /*g_print ("got attr %s\n", method->klass->name);*/
- params = g_new (void*, method->signature->param_count);
- fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
- attr = mono_object_new (mono_domain_get (), method->klass);
- mono_runtime_invoke (method, attr, params, NULL);
- list = g_list_prepend (list, attr);
- free_param_data (method->signature, params);
- g_free (params);
- }
-
- len = g_list_length (list);
- /*
- * The return type is really object[], but System/Attribute.cs does a cast
- * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
- * probably fix that.
- */
- klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
- result = mono_array_new (mono_domain_get (), klass, len);
- for (i = 0; i < len; ++i) {
- mono_array_set (result, gpointer, i, list->data);
- list = list->next;
+ if (cinfo) {
+ result = mono_custom_attrs_construct (cinfo);
+ if (!cinfo->cached)
+ mono_custom_attrs_free (cinfo);
+ } else {
+ klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
+ result = mono_array_new (mono_domain_get (), klass, 0);
}
- g_list_free (g_list_first (list));
return result;
}
static MonoMethodSignature*
-ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
+parameters_to_signature (MonoArray *parameters) {
MonoMethodSignature *sig;
int count, i;
- count = ctor->parameters? mono_array_length (ctor->parameters): 0;
+ count = parameters? mono_array_length (parameters): 0;
sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
- sig->hasthis = 1;
sig->param_count = count;
sig->sentinelpos = -1; /* FIXME */
for (i = 0; i < count; ++i) {
- MonoReflectionType *pt = mono_array_get (ctor->parameters, MonoReflectionType*, i);
+ MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
sig->params [i] = pt->type;
}
return sig;
}
+static MonoMethodSignature*
+ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
+ MonoMethodSignature *sig;
+
+ sig = parameters_to_signature (ctor->parameters);
+ sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ return sig;
+}
+
+static MonoMethodSignature*
+method_builder_to_signature (MonoReflectionMethodBuilder *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 = method->generic_params ? mono_array_length (method->generic_params) : 0;
+ 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)
{
@@ -3409,31 +6869,21 @@ 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 = 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;
-}
-
+/*
+ * Encode a value in a custom attribute stream of bytes.
+ * The value to encode is either supplied as an object in argument val
+ * (valuetypes are boxed), or as a pointer to the data in the
+ * argument argval.
+ * @type represents the type of the value
+ * @buffer is the start of the buffer
+ * @p the current position in the buffer
+ * @buflen contains the size of the buffer and is used to return the new buffer size
+ * if this needs to be realloced.
+ * @retbuffer and @retp return the start and the position of the buffer
+ */
static void
-encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
+encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
{
- char *argval;
MonoTypeEnum simple_type;
if ((p-buffer) + 10 >= *buflen) {
@@ -3443,7 +6893,8 @@ encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint3
p = newbuf + (p-buffer);
buffer = newbuf;
}
- argval = ((char*)arg + sizeof (MonoObject));
+ if (!argval)
+ argval = ((char*)arg + sizeof (MonoObject));
simple_type = type->type;
handle_enum:
switch (simple_type) {
@@ -3479,8 +6930,14 @@ handle_enum:
}
break;
case MONO_TYPE_STRING: {
- char *str = mono_string_to_utf8 ((MonoString*)arg);
- guint32 slen = strlen (str);
+ char *str;
+ guint32 slen;
+ if (!arg) {
+ *p++ = 0xFF;
+ break;
+ }
+ str = mono_string_to_utf8 ((MonoString*)arg);
+ slen = strlen (str);
if ((p-buffer) + 10 + slen >= *buflen) {
char *newbuf;
*buflen *= 2;
@@ -3498,7 +6955,12 @@ handle_enum:
case MONO_TYPE_CLASS: {
char *str;
guint32 slen;
- MonoClass *k = mono_object_class (arg);
+ MonoClass *k;
+ if (!arg) {
+ *p++ = 0xFF;
+ break;
+ }
+ k = mono_object_class (arg);
if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
(strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
g_error ("only types allowed, not %s.%s", k->name_space, k->name);
@@ -3519,6 +6981,37 @@ handle_type:
g_free (str);
break;
}
+ case MONO_TYPE_SZARRAY: {
+ int len, i;
+ MonoClass *eclass, *arg_eclass;
+
+ if (!arg) {
+ *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
+ break;
+ }
+ len = mono_array_length ((MonoArray*)arg);
+ *p++ = len & 0xff;
+ *p++ = (len >> 8) & 0xff;
+ *p++ = (len >> 16) & 0xff;
+ *p++ = (len >> 24) & 0xff;
+ *retp = p;
+ *retbuffer = buffer;
+ eclass = type->data.klass;
+ arg_eclass = mono_object_class (arg)->element_class;
+ if (eclass->valuetype && arg_eclass->valuetype) {
+ char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
+ int elsize = mono_class_array_element_size (eclass);
+ for (i = 0; i < len; ++i) {
+ encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
+ elptr += elsize;
+ }
+ } else {
+ for (i = 0; i < len; ++i) {
+ encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
+ }
+ }
+ break;
+ }
/* it may be a boxed value or a Type */
case MONO_TYPE_OBJECT: {
MonoClass *klass = mono_object_class (arg);
@@ -3530,13 +7023,17 @@ handle_type:
goto handle_type;
} else if (klass->enumtype) {
*p++ = 0x55;
+ } else if (klass == mono_defaults.string_class) {
+ simple_type = MONO_TYPE_STRING;
+ *p++ = 0x0E;
+ goto handle_enum;
} else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
*p++ = simple_type = klass->byval_arg.type;
goto handle_enum;
} else {
g_error ("unhandled type in custom attr");
}
- str = type_get_qualified_name (klass->enum_basetype, NULL);
+ str = type_get_qualified_name (mono_class_get_type(klass), NULL);
slen = strlen (str);
if ((p-buffer) + 10 + slen >= *buflen) {
char *newbuf;
@@ -3574,26 +7071,30 @@ handle_type:
* Returns: a Byte array representing the blob of data.
*/
MonoArray*
-mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
+mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
+{
MonoArray *result;
MonoMethodSignature *sig;
MonoObject *arg;
char *buffer, *p;
guint32 buflen, i;
+ MONO_ARCH_SAVE_REGS;
+
if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
} else {
sig = ((MonoReflectionMethod*)ctor)->method->signature;
}
+ g_assert (mono_array_length (ctorArgs) == sig->param_count);
buflen = 256;
p = buffer = g_malloc (buflen);
/* write the prolog */
*p++ = 1;
*p++ = 0;
for (i = 0; i < sig->param_count; ++i) {
- arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
- encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
+ arg = mono_array_get (ctorArgs, MonoObject*, i);
+ encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
}
i = 0;
if (properties)
@@ -3612,11 +7113,49 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo
prop = mono_array_get (properties, gpointer, i);
get_prop_name_and_type (prop, &pname, &ptype);
*p++ = 0x54; /* PROPERTY signature */
+
+ /* Preallocate a large enough buffer */
+ if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
+ char *str = type_get_qualified_name (ptype, NULL);
+ len = strlen (str);
+ g_free (str);
+ }
+ else
+ len = 0;
+ len += strlen (pname);
+
+ if ((p-buffer) + 20 + len >= buflen) {
+ char *newbuf;
+ buflen *= 2;
+ buflen += len;
+ newbuf = g_realloc (buffer, buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+
+ if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
+ char *str = type_get_qualified_name (ptype, NULL);
+ int slen = strlen (str);
+
+ *p++ = 0x55;
+ /*
+ * This seems to be optional...
+ * *p++ = 0x80;
+ */
+ mono_metadata_encode_value (slen, p, &p);
+ memcpy (p, str, slen);
+ p += slen;
+ 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);
memcpy (p, pname, len);
p += len;
- encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
+ encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
g_free (pname);
}
}
@@ -3631,11 +7170,36 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo
field = mono_array_get (fields, gpointer, i);
get_field_name_and_type (field, &fname, &ftype);
*p++ = 0x53; /* FIELD signature */
+ if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
+ char *str = type_get_qualified_name (ftype, NULL);
+ int slen = strlen (str);
+ if ((p-buffer) + 10 + slen >= buflen) {
+ char *newbuf;
+ buflen *= 2;
+ buflen += slen;
+ newbuf = g_realloc (buffer, buflen);
+ p = newbuf + (p-buffer);
+ buffer = newbuf;
+ }
+ *p++ = 0x55;
+ /*
+ * This seems to be optional...
+ * *p++ = 0x80;
+ */
+ mono_metadata_encode_value (slen, p, &p);
+ memcpy (p, str, slen);
+ p += slen;
+ g_free (str);
+ } else {
+ mono_metadata_encode_value (ftype->type, p, &p);
+ if (ftype->type == MONO_TYPE_SZARRAY)
+ mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
+ }
len = strlen (fname);
mono_metadata_encode_value (len, p, &p);
memcpy (p, fname, len);
p += len;
- encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
+ encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
g_free (fname);
}
}
@@ -3664,15 +7228,36 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
{
MonoClass *klass, *parent;
- klass = g_new0 (MonoClass, 1);
+ MONO_ARCH_SAVE_REGS;
- klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
-
- if (tb->parent)
- parent = mono_class_from_mono_type (tb->parent->type);
- else
+ if (tb->parent) {
+ /* check so we can compile corlib correctly */
+ if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
+ /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
+ parent = tb->parent->type->data.klass;
+ } else {
+ parent = my_mono_class_from_mono_type (tb->parent->type);
+ }
+ } else {
parent = NULL;
+ }
+ /* the type has already being created: it means we just have to change the parent */
+ if (tb->type.type) {
+ klass = mono_class_from_mono_type (tb->type.type);
+ klass->parent = NULL;
+ /* fool mono_class_setup_parent */
+ g_free (klass->supertypes);
+ klass->supertypes = NULL;
+ mono_class_setup_parent (klass, parent);
+ mono_class_setup_mono_type (klass);
+ return;
+ }
+
+ klass = g_new0 (MonoClass, 1);
+
+ klass->image = &tb->module->dynamic_image->image;
+
klass->inited = 1; /* we lie to the runtime */
klass->name = mono_string_to_utf8 (tb->name);
klass->name_space = mono_string_to_utf8 (tb->nspace);
@@ -3682,20 +7267,108 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
klass->element_class = klass;
klass->reflection_info = tb; /* need to pin. */
- if (parent != NULL)
+ /* Put into cache so mono_class_get () will find it */
+ mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
+
+ mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
+ GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
+
+ if (parent != NULL) {
mono_class_setup_parent (klass, parent);
+ } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
+ const char *old_n = klass->name;
+ /* trick to get relative numbering right when compiling corlib */
+ klass->name = "BuildingObject";
+ mono_class_setup_parent (klass, mono_defaults.object_class);
+ klass->name = old_n;
+ }
+
+ if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
+ (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
+ (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
+ klass->instance_size = sizeof (MonoObject);
+ klass->size_inited = 1;
+ mono_class_setup_vtable (klass, NULL, 0);
+ }
+
mono_class_setup_mono_type (klass);
+ mono_class_setup_supertypes (klass);
+
/*
* FIXME: handle interfaces.
*/
tb->type.type = &klass->byval_arg;
+ if (tb->nesting_type) {
+ g_assert (tb->nesting_type->type);
+ klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
+ }
+
/*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
}
/*
+ * mono_reflection_setup_generic_class:
+ * @tb: a TypeBuilder object
+ *
+ * Setup the generic class before adding the first generic parameter.
+ */
+void
+mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoClass *klass;
+
+ MONO_ARCH_SAVE_REGS;
+
+ klass = my_mono_class_from_mono_type (tb->type.type);
+ if (tb->generic_container)
+ return;
+
+ tb->generic_container = g_new0 (MonoGenericContainer, 1);
+ tb->generic_container->klass = klass;
+
+ tb->generic_container->context = g_new0 (MonoGenericContext, 1);
+ tb->generic_container->context->container = tb->generic_container;
+}
+
+/*
+ * mono_reflection_create_generic_class:
+ * @tb: a TypeBuilder object
+ *
+ * Creates the generic class after all generic parameters have been added.
+ */
+void
+mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoClass *klass;
+ int count, i;
+
+ MONO_ARCH_SAVE_REGS;
+
+ klass = my_mono_class_from_mono_type (tb->type.type);
+
+ count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
+
+ if (klass->generic_container || (count == 0))
+ return;
+
+ g_assert (tb->generic_container && (tb->generic_container->klass == klass));
+
+ klass->generic_container = tb->generic_container;
+
+ klass->generic_container->type_argc = count;
+ klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
+
+ for (i = 0; i < count; i++) {
+ MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
+ klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
+ g_assert (klass->generic_container->type_params [i].owner);
+ }
+}
+
+/*
* mono_reflection_create_internal_class:
* @tb: a TypeBuilder object
*
@@ -3706,10 +7379,13 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
{
MonoClass *klass;
- klass = mono_class_from_mono_type (tb->type.type);
+ MONO_ARCH_SAVE_REGS;
+
+ klass = my_mono_class_from_mono_type (tb->type.type);
if (klass->enumtype && klass->enum_basetype == NULL) {
MonoReflectionFieldBuilder *fb;
+ MonoClass *ec;
g_assert (tb->fields != NULL);
g_assert (mono_array_length (tb->fields) >= 1);
@@ -3717,19 +7393,1118 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
klass->enum_basetype = fb->type->type;
- klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
+ klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
+ if (!klass->element_class)
+ klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
+
+ /*
+ * get the element_class from the current corlib.
+ */
+ ec = default_class_from_mono_type (klass->enum_basetype);
+ klass->instance_size = ec->instance_size;
+ klass->size_inited = 1;
+ /*
+ * this is almost safe to do with enums and it's needed to be able
+ * to create objects of the enum type (for use in SetConstant).
+ */
+ /* FIXME: Does this mean enums can't have method overrides ? */
+ mono_class_setup_vtable (klass, NULL, 0);
+ }
+}
+
+static MonoMarshalSpec*
+mono_marshal_spec_from_builder (MonoAssembly *assembly,
+ MonoReflectionMarshal *minfo)
+{
+ MonoMarshalSpec *res;
+
+ res = g_new0 (MonoMarshalSpec, 1);
+ res->native = minfo->type;
+
+ switch (minfo->type) {
+ case MONO_NATIVE_LPARRAY:
+ res->data.array_data.elem_type = minfo->eltype;
+ res->data.array_data.param_num = 0; /* Not yet */
+ res->data.array_data.num_elem = minfo->count;
+ break;
+
+ case MONO_NATIVE_BYVALTSTR:
+ case MONO_NATIVE_BYVALARRAY:
+ res->data.array_data.num_elem = minfo->count;
+ break;
+
+ case MONO_NATIVE_CUSTOM:
+ if (minfo->marshaltyperef)
+ res->data.custom_data.custom_name =
+ type_get_fully_qualified_name (minfo->marshaltyperef->type);
+ if (minfo->mcookie)
+ res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
+ break;
+
+ default:
+ break;
+ }
+
+ return res;
+}
+
+MonoReflectionMarshal*
+mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
+ MonoMarshalSpec *spec)
+{
+ static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
+ MonoReflectionMarshal *minfo;
+ MonoType *mtype;
+
+ if (!System_Reflection_Emit_UnmanagedMarshalClass) {
+ System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
+ mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
+ g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
+ }
+
+ minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
+ minfo->type = spec->native;
+
+ switch (minfo->type) {
+ case MONO_NATIVE_LPARRAY:
+ minfo->eltype = spec->data.array_data.elem_type;
+ minfo->count = spec->data.array_data.num_elem;
+ break;
+
+ case MONO_NATIVE_BYVALTSTR:
+ case MONO_NATIVE_BYVALARRAY:
+ minfo->count = spec->data.array_data.num_elem;
+ break;
+
+ case MONO_NATIVE_CUSTOM:
+ if (spec->data.custom_data.custom_name) {
+ mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
+ if (mtype)
+ minfo->marshaltyperef = mono_type_get_object (domain, mtype);
+
+ minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
+ }
+ if (spec->data.custom_data.cookie)
+ minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
+ break;
+
+ default:
+ break;
+ }
+
+ return minfo;
+}
+
+static MonoMethod*
+reflection_methodbuilder_to_mono_method (MonoClass *klass,
+ ReflectionMethodBuilder *rmb,
+ MonoMethodSignature *sig)
+{
+ MonoMethod *m;
+ MonoMethodNormal *pm;
+ MonoMarshalSpec **specs;
+ MonoReflectionMethodAux *method_aux;
+ int i;
+
+ if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (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;
+
+ m->slot = -1;
+ m->flags = rmb->attrs;
+ m->iflags = rmb->iattrs;
+ m->name = mono_string_to_utf8 (rmb->name);
+ m->klass = klass;
+ m->signature = sig;
+ 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"))
+ m->string_ctor = 1;
+
+ m->signature->pinvoke = 1;
+ } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ m->signature->pinvoke = 1;
+
+ method_aux = g_new0 (MonoReflectionMethodAux, 1);
+
+ method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
+ method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
+
+ ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
+
+ if (klass->image->dynamic)
+ mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
+
+ return m;
+ } else if (!m->klass->dummy &&
+ !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
+ !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
+ MonoMethodHeader *header;
+ guint32 code_size;
+ gint32 max_stack, i;
+ gint32 num_locals = 0;
+ gint32 num_clauses = 0;
+ guint8 *code;
+
+ if (rmb->ilgen) {
+ code = mono_array_addr (rmb->ilgen->code, guint8, 0);
+ code_size = rmb->ilgen->code_len;
+ max_stack = rmb->ilgen->max_stack;
+ num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
+ if (rmb->ilgen->ex_handlers)
+ num_clauses = method_count_clauses (rmb->ilgen);
+ } else {
+ if (rmb->code) {
+ code = mono_array_addr (rmb->code, guint8, 0);
+ code_size = mono_array_length (rmb->code);
+ /* we probably need to run a verifier on the code... */
+ max_stack = 8;
+ }
+ else {
+ code = NULL;
+ code_size = 0;
+ max_stack = 8;
+ }
+ }
+
+ header = g_malloc0 (sizeof (MonoMethodHeader) +
+ (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ header->code_size = code_size;
+ header->code = g_malloc (code_size);
+ memcpy ((char*)header->code, code, code_size);
+ header->max_stack = max_stack;
+ header->init_locals = rmb->init_locals;
+ header->num_locals = num_locals;
+
+ for (i = 0; i < num_locals; ++i) {
+ MonoReflectionLocalBuilder *lb =
+ mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
+
+ header->locals [i] = g_new0 (MonoType, 1);
+ memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
+ }
+
+ header->num_clauses = num_clauses;
+ if (num_clauses) {
+ header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
+ rmb->ilgen, num_clauses);
+ }
+
+ pm->header = header;
+ }
+
+ if (rmb->generic_params) {
+ int count = mono_array_length (rmb->generic_params);
+ MonoGenericContainer *container;
+
+ pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
+ container->type_argc = count;
+ container->type_params = g_new0 (MonoGenericParam, count);
+
+ for (i = 0; i < count; i++) {
+ MonoReflectionGenericParam *gp =
+ mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
+
+ container->type_params [i] = *gp->type.type->data.generic_param;
+ }
+ }
+
+ 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 info */
+ 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->pinfo, MonoReflectionParamBuilder*, i))) {
+ if (i > 0)
+ m->signature->params [i - 1]->attrs = pb->attrs;
+
+ if (pb->def_value) {
+ MonoDynamicImage *assembly;
+ guint32 idx, def_type, len;
+ char *p;
+ const char *p2;
+
+ if (!method_aux->param_defaults)
+ method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
+ assembly = (MonoDynamicImage*)klass->image;
+ idx = encode_constant (assembly, pb->def_value, &def_type);
+ /* Copy the data from the blob since it might get realloc-ed */
+ p = assembly->blob.data + idx;
+ len = mono_metadata_decode_blob_size (p, &p2);
+ len += p2 - p;
+ method_aux->param_defaults [i] = g_malloc (len);
+ memcpy ((gpointer)method_aux->param_defaults [i], p, len);
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+
+ /* Parameter marshalling */
+ specs = NULL;
+ if (rmb->pinfo)
+ for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
+ MonoReflectionParamBuilder *pb;
+ if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
+ if (pb->marshal_info) {
+ if (specs == NULL)
+ specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
+ specs [pb->position] =
+ mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
+ }
+ }
+ }
+ if (specs != NULL) {
+ if (!method_aux)
+ method_aux = g_new0 (MonoReflectionMethodAux, 1);
+ method_aux->param_marshall = specs;
+ }
+
+ if (klass->image->dynamic && method_aux)
+ mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
+
+ return m;
+}
+
+static MonoMethod*
+ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
+{
+ ReflectionMethodBuilder rmb;
+ MonoMethodSignature *sig;
+
+ sig = ctor_builder_to_signature (mb);
+
+ reflection_methodbuilder_from_ctor_builder (&rmb, mb);
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+
+ return mb->mhandle;
+}
+
+static MonoMethod*
+methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
+{
+ ReflectionMethodBuilder rmb;
+ MonoMethodSignature *sig;
+
+ sig = method_builder_to_signature (mb);
+
+ reflection_methodbuilder_from_method_builder (&rmb, mb);
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+ return mb->mhandle;
+}
+
+static MonoClassField*
+fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
+{
+ MonoClassField *field;
+ const char *p, *p2;
+ guint32 len, idx;
+
+ if (fb->handle)
+ return fb->handle;
+
+ field = g_new0 (MonoClassField, 1);
+
+ field->name = mono_string_to_utf8 (fb->name);
+ if (fb->attrs) {
+ /* FIXME: handle type modifiers */
+ field->type = g_memdup (fb->type->type, sizeof (MonoType));
+ field->type->attrs = fb->attrs;
+ } else {
+ field->type = fb->type->type;
+ }
+ if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
+ field->data = mono_array_addr (fb->rva_data, char, 0);
+ if (fb->offset != -1)
+ field->offset = fb->offset;
+ field->parent = klass;
+ fb->handle = field;
+ mono_save_custom_attrs (klass->image, field, fb->cattrs);
+
+ if (fb->def_value) {
+ MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
+ field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+ idx = encode_constant (assembly, fb->def_value, &field->def_type);
+ /* Copy the data from the blob since it might get realloc-ed */
+ p = assembly->blob.data + idx;
+ len = mono_metadata_decode_blob_size (p, &p2);
+ len += p2 - p;
+ field->data = g_malloc (len);
+ memcpy ((gpointer)field->data, p, len);
}
+
+ return field;
+}
+
+static MonoType*
+do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
+{
+ MonoClass *klass, *gklass;
+ MonoReflectionTypeBuilder *tb = NULL;
+ MonoGenericInst *ginst, *cached;
+ MonoDomain *domain;
+ MonoType *geninst;
+ int icount, i;
+
+ klass = mono_class_from_mono_type (type->type);
+ if (!klass->generic_container && !klass->generic_inst &&
+ !(klass->nested_in && klass->nested_in->generic_container))
+ return NULL;
+
+ mono_loader_lock ();
+
+ domain = mono_object_domain (type);
+
+ ginst = g_new0 (MonoGenericInst, 1);
+
+ ginst->type_argc = type_argc;
+ ginst->type_argv = types;
+
+ 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;
+
+ if (klass->generic_inst) {
+ MonoGenericInst *kginst = klass->generic_inst;
+ MonoGenericInst *oginst = ginst;
+
+ oginst->context = g_new0 (MonoGenericContext, 1);
+ oginst->context->ginst = oginst;
+
+ ginst = g_new0 (MonoGenericInst, 1);
+
+ 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];
+
+ t = mono_class_inflate_generic_type (t, oginst->context);
+
+ 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;
+ }
+
+ geninst = g_new0 (MonoType, 1);
+ geninst->type = MONO_TYPE_GENERICINST;
+
+ cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
+ if (cached) {
+ g_free (ginst);
+ mono_loader_unlock ();
+ geninst->data.generic_inst = cached;
+ return geninst;
+ }
+
+ gklass = mono_class_from_mono_type (ginst->generic_type);
+ g_assert ((ginst->container = gklass->generic_container) != NULL);
+
+ geninst->data.generic_inst = ginst;
+
+ ginst->context = g_new0 (MonoGenericContext, 1);
+ ginst->context->ginst = ginst;
+
+ 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;
+ }
+
+ mono_class_create_generic (ginst);
+
+ g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
+
+ 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);
+ else if (klass->generic_inst && klass->generic_inst->parent) {
+ parent = mono_type_get_object (domain, klass->generic_inst->parent);
+ pklass = mono_class_from_mono_type (klass->generic_inst->parent);
+ }
+ }
+
+ 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;
+}
+
+MonoReflectionMethod*
+mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
+{
+ MonoMethod *method, *inflated;
+ MonoReflectionMethodBuilder *mb = NULL;
+ MonoGenericMethod *gmethod;
+ MonoGenericContext *context;
+ int count, i;
+
+ MONO_ARCH_SAVE_REGS;
+ if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
+ MonoReflectionTypeBuilder *tb;
+ MonoClass *klass;
+
+ mb = (MonoReflectionMethodBuilder *) rmethod;
+ tb = (MonoReflectionTypeBuilder *) mb->type;
+ klass = mono_class_from_mono_type (tb->type.type);
+
+ method = methodbuilder_to_mono_method (klass, mb);
+ } else {
+ method = rmethod->method;
+ }
+
+ count = method->signature->generic_param_count;
+ if (count != mono_array_length (types))
+ return NULL;
+
+ 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);
+ gmethod->mtype_argv [i] = garg->type;
+ }
+
+ gmethod->reflection_info = rmethod;
+
+ 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->generic_container->type_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);
+}
+
+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, "ConstructorBuilder"))
+ method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
+ else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
+ method = ((MonoReflectionMethod *) obj)->method;
+ else {
+ method = NULL; /* prevent compiler warning */
+ g_assert_not_reached ();
+ }
+
+ 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;
+
+ if (ginst->initialized)
+ return;
+
+ dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
+
+ 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
+ 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;
+
+ 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);
+ }
+
+ for (i = 0; i < dginst->count_ctors; i++) {
+ MonoObject *obj = mono_array_get (ctors, gpointer, i);
+
+ dginst->ctors [i] = inflate_method (type, obj);
+ }
+
+ for (i = 0; i < dginst->count_fields; i++) {
+ MonoObject *obj = mono_array_get (fields, gpointer, i);
+ MonoClassField *field;
+ MonoInflatedField *ifield;
+
+ 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 ();
+ }
+
+ ifield = g_new0 (MonoInflatedField, 1);
+ ifield->generic_type = field->type;
+ ifield->reflection_info = obj;
+
+ dginst->fields [i] = *field;
+ dginst->fields [i].generic_info = ifield;
+ 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
+ensure_runtime_vtable (MonoClass *klass)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ int i, num, j, onum;
+ MonoMethod **overrides;
+
+ if (!tb || klass->wastypebuilder)
+ return;
+ if (klass->parent)
+ ensure_runtime_vtable (klass->parent);
+
+ num = tb->ctors? mono_array_length (tb->ctors): 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->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));
+
+ if (tb->interfaces) {
+ klass->interface_count = mono_array_length (tb->interfaces);
+ klass->interfaces = g_new (MonoClass*, klass->interface_count);
+ for (i = 0; i < klass->interface_count; ++i) {
+ MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
+ klass->interfaces [i] = mono_class_from_mono_type (iface->type);
+ }
+ }
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+ for (i = 0; i < klass->method.count; ++i)
+ klass->methods [i]->slot = i;
+
+ /* Overrides */
+ onum = 0;
+ if (tb->methods) {
+ for (i = 0; i < tb->num_methods; ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_method)
+ onum ++;
+ }
+ }
+
+ overrides = g_new0 (MonoMethod*, onum * 2);
+
+ if (tb->methods) {
+ onum = 0;
+ for (i = 0; i < tb->num_methods; ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_method) {
+ /* FIXME: What if 'override_method' is a MethodBuilder ? */
+ overrides [onum * 2] =
+ mb->override_method->method;
+ overrides [onum * 2 + 1] =
+ mb->mhandle;
+
+ g_assert (mb->mhandle);
+
+ onum ++;
+ }
+ }
+ }
+
+ mono_class_setup_vtable (klass, overrides, onum);
+ g_free (overrides);
+}
+
+static void
+typebuilder_setup_fields (MonoClass *klass)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionFieldBuilder *fb;
+ MonoClassField *field;
+ const char *p, *p2;
+ int i;
+ guint32 len, idx;
+
+ klass->field.count = tb->num_fields;
+ klass->field.first = 0;
+ klass->field.last = klass->field.count;
+
+ if (!klass->field.count)
+ return;
+
+ klass->fields = g_new0 (MonoClassField, klass->field.count);
+
+ for (i = 0; i < klass->field.count; ++i) {
+ fb = mono_array_get (tb->fields, gpointer, i);
+ field = &klass->fields [i];
+ field->name = mono_string_to_utf8 (fb->name);
+ if (fb->attrs) {
+ /* FIXME: handle type modifiers */
+ field->type = g_memdup (fb->type->type, sizeof (MonoType));
+ field->type->attrs = fb->attrs;
+ } else {
+ field->type = fb->type->type;
+ }
+ if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
+ field->data = mono_array_addr (fb->rva_data, char, 0);
+ if (fb->offset != -1)
+ field->offset = fb->offset;
+ field->parent = klass;
+ fb->handle = field;
+ mono_save_custom_attrs (klass->image, field, fb->cattrs);
+
+ if (fb->def_value) {
+ MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
+ field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+ idx = encode_constant (assembly, fb->def_value, &field->def_type);
+ /* Copy the data from the blob since it might get realloc-ed */
+ p = assembly->blob.data + idx;
+ len = mono_metadata_decode_blob_size (p, &p2);
+ len += p2 - p;
+ field->data = g_malloc (len);
+ memcpy ((gpointer)field->data, p, len);
+ }
+ }
+ mono_class_layout_fields (klass);
+}
+
+static void
+typebuilder_setup_properties (MonoClass *klass)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionPropertyBuilder *pb;
+ int i;
+
+ klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
+ klass->property.first = 0;
+ klass->property.last = klass->property.count;
+
+ 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)
+ klass->properties [i].get = pb->get_method->mhandle;
+ if (pb->set_method)
+ klass->properties [i].set = pb->set_method->mhandle;
+ }
+}
+
+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) + 1);
+ 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)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionEventBuilder *eb;
+ int i, j;
+
+ klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
+ klass->event.first = 0;
+ klass->event.last = klass->event.count;
+
+ 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)
+ klass->events [i].add = eb->add_method->mhandle;
+ if (eb->remove_method)
+ klass->events [i].remove = eb->remove_method->mhandle;
+ if (eb->raise_method)
+ klass->events [i].raise = eb->raise_method->mhandle;
+
+ if (eb->other_methods) {
+ klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
+ for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (eb->other_methods,
+ MonoReflectionMethodBuilder*, j);
+ klass->events [i].other [j] = mb->mhandle;
+ }
+ }
+ }
+}
+
+MonoReflectionType*
+mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoClass *klass;
+ MonoReflectionType* res;
+ int i;
+
+ MONO_ARCH_SAVE_REGS;
+
+ klass = my_mono_class_from_mono_type (tb->type.type);
+
+ mono_save_custom_attrs (klass->image, klass, tb->cattrs);
+
+ /*
+ * Fields to set in klass:
+ * the various flags: delegate/unicode/contextbound etc.
+ */
+ klass->flags = tb->attrs;
+
+ if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
+ /* No need to fully construct the type */
+ return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+
+ /* enums are done right away */
+ if (!klass->enumtype)
+ ensure_runtime_vtable (klass);
+
+ if (tb->subtypes) {
+ for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
+ MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
+ klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
+ }
+ }
+
+ /* fields and object layout */
+ if (klass->parent) {
+ if (!klass->parent->size_inited)
+ mono_class_init (klass->parent);
+ klass->instance_size += klass->parent->instance_size;
+ klass->class_size += klass->parent->class_size;
+ klass->min_align = klass->parent->min_align;
+ } else {
+ klass->instance_size = sizeof (MonoObject);
+ klass->min_align = 1;
+ }
+
+ /* FIXME: handle packing_size and instance_size */
+ typebuilder_setup_fields (klass);
+
+ typebuilder_setup_properties (klass);
+
+ typebuilder_setup_events (klass);
+
+ klass->wastypebuilder = TRUE;
+
+ res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+ g_assert (res != (MonoReflectionType*)tb);
+ return res;
+}
+
+void
+mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
+{
+ MonoGenericParam *param;
+ MonoImage *image;
+
+ MONO_ARCH_SAVE_REGS;
+
+ param = g_new0 (MonoGenericParam, 1);
+
+ if (gparam->mbuilder) {
+ if (!gparam->mbuilder->generic_container)
+ gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
+ param->owner = gparam->mbuilder->generic_container;
+ } else if (gparam->tbuilder) {
+ MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
+ MonoGenericContainer *container = gparam->tbuilder->generic_container;
+
+ while (nesting) {
+ int count;
+
+ count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
+ if (gparam->index >= count)
+ break;
+
+ container = nesting->generic_container;
+ nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
+ }
+
+ g_assert (container);
+ param->owner = container;
+ }
+
+ param->method = NULL;
+ param->name = mono_string_to_utf8 (gparam->name);
+ param->num = gparam->index;
+
+ image = &gparam->tbuilder->module->dynamic_image->image;
+ mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
+
+ param->pklass->reflection_info = gparam;
+
+ 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 *
mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
{
- MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
+ MonoDynamicImage *assembly = sig->module->dynamic_image;
guint32 na = mono_array_length (sig->arguments);
guint32 buflen, i;
MonoArray *result;
char *buf, *p;
+ MONO_ARCH_SAVE_REGS;
+
p = buf = g_malloc (10 + na * 10);
mono_metadata_encode_value (0x07, p, &p);
@@ -3751,12 +8526,14 @@ mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
MonoArray *
mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
{
- MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
+ MonoDynamicImage *assembly = sig->module->dynamic_image;
guint32 na = mono_array_length (sig->arguments);
guint32 buflen, i;
MonoArray *result;
char *buf, *p;
+ MONO_ARCH_SAVE_REGS;
+
p = buf = g_malloc (10 + na * 10);
mono_metadata_encode_value (0x06, p, &p);
@@ -3774,3 +8551,169 @@ 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:
+ *
+ * Finish the Builder object pointed to by TOKEN and return the corresponding
+ * runtime structure.
+ */
+gpointer
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
+{
+ MonoDynamicImage *assembly = (MonoDynamicImage*)image;
+ MonoObject *obj;
+
+ 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);
+ } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
+ MonoReflectionType *tb = (MonoReflectionType*)obj;
+ result = mono_class_from_mono_type (tb->type);
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
+ result = ((MonoReflectionMethod*)obj)->method;
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
+ result = ((MonoReflectionMethod*)obj)->method;
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
+ MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
+ result = mb->mhandle;
+ if (!result) {
+ /* Type is not yet created */
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
+
+ mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
+
+ /*
+ * Hopefully this has been filled in by calling CreateType() on the
+ * TypeBuilder.
+ */
+ /**
+ * TODO: This won't work if the application finishes another
+ * TypeBuilder instance instead of this one.
+ */
+ result = mb->mhandle;
+ }
+ } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
+ MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
+
+ result = cb->mhandle;
+ if (!result) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
+
+ mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
+ result = cb->mhandle;
+ }
+ } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
+ result = ((MonoReflectionField*)obj)->field;
+ g_assert (result);
+ } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
+ MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
+ result = fb->handle;
+
+ if (!result) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
+
+ mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
+ result = fb->handle;
+ }
+ } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
+ MonoClass *klass;
+
+ klass = tb->type.type->data.klass;
+ if (klass->wastypebuilder) {
+ /* Already created */
+ result = klass;
+ }
+ else {
+ mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
+ result = tb->type.type->data.klass;
+ g_assert (result);
+ }
+ } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
+ MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
+ MonoMethodSignature *sig;
+ int nargs, i;
+
+ if (helper->arguments)
+ nargs = mono_array_length (helper->arguments);
+ else
+ nargs = 0;
+
+ sig = mono_metadata_signature_alloc (image, nargs);
+ sig->explicit_this = helper->call_conv & 64;
+ sig->hasthis = helper->call_conv & 32;
+
+ if (helper->call_conv == 0) /* unmanaged */
+ sig->call_convention = helper->unmanaged_call_conv - 1;
+ else
+ if (helper->call_conv & 0x02)
+ sig->call_convention = MONO_CALL_VARARG;
+ else
+ sig->call_convention = MONO_CALL_DEFAULT;
+
+ sig->param_count = nargs;
+ /* TODO: Copy type ? */
+ sig->ret = helper->return_type->type;
+ for (i = 0; i < nargs; ++i) {
+ MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
+ sig->params [i] = rt->type;
+ }
+
+ result = sig;
+ } else {
+ g_print (obj->vtable->klass->name);
+ g_assert_not_reached ();
+ }
+ return result;
+}
+