2003-05-14 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / reflection.c
index c7af2ffdfbeb2f541d0912a632ffb32ad7b76f26..56d9719f4fb3651bc3175c7e71839f2bac112cc7 100644 (file)
@@ -9,24 +9,26 @@
  *
  */
 #include <config.h>
+#include "mono/utils/mono-digest.h"
 #include "mono/metadata/reflection.h"
 #include "mono/metadata/tabledefs.h"
 #include "mono/metadata/tokentype.h"
 #include "mono/metadata/appdomain.h"
 #include "mono/metadata/opcodes.h"
+#include "mono/metadata/assembly.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
@@ -47,6 +49,7 @@ typedef struct {
        MonoObject *type;
        MonoString *name;
        MonoBoolean init_locals;
+       MonoMethod *mhandle;
 } ReflectionMethodBuilder;
 
 const unsigned char table_sizes [64] = {
@@ -95,8 +98,23 @@ const unsigned char table_sizes [64] = {
        0       /* 0x2A */
 };
 
+/**
+ * These macros can be used to allocate long living atomic data so it won't be
+ * tracked by the garbage collector.
+ */
+#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 guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
+static guint32 mono_image_get_sighelper_token (MonoDynamicAssembly *assembly, MonoReflectionSigHelper *helper);
 static guint32 encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo);
 
 static void
@@ -104,9 +122,29 @@ 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;
+
+               table->values = REALLOC_ATOMIC (table->values, (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;
+       }
+       stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
+}      
+
 static guint32
 string_heap_insert (MonoDynamicStream *sh, const char *str)
 {
@@ -119,10 +157,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 +176,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 +185,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 +195,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 +211,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,6 +230,70 @@ 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 (MonoDynamicAssembly *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;
+}
+
+/* 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:
+               return mono_class_from_mono_type (type);
+       default:
+               /* should be always valid when we reach this case... */
+               return type->data.klass;
+       }
+}
+
 static void
 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
 {
@@ -289,7 +386,10 @@ method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *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...
@@ -305,8 +405,7 @@ method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig
        /* 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;
 }
@@ -343,8 +442,7 @@ method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethod
        /* 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;
 }
@@ -378,8 +476,7 @@ encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
        }
        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;
@@ -387,6 +484,71 @@ encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
        return idx;
 }
 
+static guint32
+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 (MonoDynamicAssembly *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;
+                       clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
+                               mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
+                       if (ex_block->extype) {
+                               mono_g_hash_table_insert (assembly->tokens,
+                                                                                 GUINT_TO_POINTER (clause->token_or_filter),
+                                                                                 ex_block->extype);
+                       }
+                       finally_start = ex_block->start + ex_block->len;
+
+                       clause_index ++;
+               }
+       }
+
+       return clauses;
+}
+
 static guint32
 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
 {
@@ -418,18 +580,13 @@ 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)
+                       mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
+
                code_size = mono_array_length (code);
                max_stack = 8; /* we probably need to run a verifier on the code... */
        }
@@ -488,6 +645,7 @@ fat_header:
                /* always use fat format for now */
                sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
                num_exception *= sizeof (MonoExceptionClause);
+               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;
@@ -509,7 +667,7 @@ fat_header:
                                                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;
+                                       finally_start = ex_block->start + ex_block->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);
@@ -540,10 +698,64 @@ 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);
+}
+
+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_*
@@ -582,13 +794,13 @@ mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type,
                        type |= 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;
@@ -610,6 +822,7 @@ 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);
@@ -617,6 +830,8 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assem
                g_free (name);
        } else { /* a constructor */
                values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
+               // MS.NET adds this automatically
+               mb->attrs |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
        }
        values [MONO_METHOD_FLAGS] = mb->attrs;
        values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
@@ -646,9 +861,13 @@ 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++;
@@ -657,7 +876,7 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assem
                                        mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | 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++;
                        }
                }
        }
@@ -683,6 +902,7 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly
        rmb.name = mb->name;
        rmb.table_idx = &mb->table_idx;
        rmb.init_locals = mb->init_locals;
+       rmb.mhandle = mb->mhandle;
 
        mono_image_basic_method (&rmb, assembly);
 
@@ -692,7 +912,8 @@ mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly
                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) | (mb->charset ? (mb->charset - 1) * 2: 1);
                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 +929,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;
@@ -749,6 +971,7 @@ mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, Mon
        rmb.name = NULL;
        rmb.table_idx = &mb->table_idx;
        rmb.init_locals = mb->init_locals;
+       rmb.mhandle = mb->mhandle;
 
        mono_image_basic_method (&rmb, assembly);
 
@@ -762,7 +985,10 @@ fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
        char *p;
        char* buf;
        guint32 idx;
-       
+
+       if (!assembly->save)
+               return 0;
+
        p = buf = g_malloc (64);
        
        mono_metadata_encode_value (0x06, p, &p);
@@ -770,8 +996,7 @@ fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
        encode_type (assembly, field->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;
 }
@@ -792,8 +1017,7 @@ field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilde
        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;
 }
@@ -849,12 +1073,17 @@ encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_ty
        char *b = blob_size;
        char *p, *box_val;
        char* buf;
-       guint32 idx, len;
+       guint32 idx, len, 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 +1112,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 +1141,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);
@@ -933,15 +1163,19 @@ encode_marshal_blob (MonoDynamicAssembly *assembly, MonoReflectionMarshal *minfo
        p = buf = g_malloc (256);
 
        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;
+               /* FIXME: handle ARRAY and other unmanaged types that need extra info */
        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;
 }
@@ -958,6 +1192,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);
@@ -1015,10 +1250,13 @@ property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionProperty
        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,13 +1269,17 @@ 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;
 }
@@ -1157,11 +1399,17 @@ resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
        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)
+               /* FIXME: */
+               memset (cols, 0, sizeof (cols));
+       else
+               mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
 
        table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
        token = table->next_idx ++;
@@ -1177,13 +1425,42 @@ resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
        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;
 
+       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 {
+               /* 
+                * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
+                * This is currently only a problem with references to System.Xml (see bug#27706),
+                * but there may be other cases that makes this necessary. Note, we need to set 
+                * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken 
+                * recognized by ms, yuck!
+                * FIXME: need to add more assembly names, as needed.
+                */
+               if (strcmp (image->assembly_name, "corlib") == 0 ||
+                               strcmp (image->assembly_name, "mscorlib") == 0 ||
+                               strcmp (image->assembly_name, "System") == 0 ||
+                               strcmp (image->assembly_name, "System.Xml") == 0 ||
+                               strcmp (image->assembly_name, "System.Data") == 0 ||
+                               strcmp (image->assembly_name, "System.Drawing") == 0 ||
+                               strcmp (image->assembly_name, "System.Web") == 0) {
+                       static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
+                       values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
+                       values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
+                       values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
+               } else {
+                       values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
+               }
+       }
        token <<= RESOLTION_SCOPE_BITS;
        token |= RESOLTION_SCOPE_ASSEMBLYREF;
        g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
+       mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), image);
        return token;
 }
 
@@ -1208,16 +1485,16 @@ create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
        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);
        g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
@@ -1236,19 +1513,30 @@ mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
        guint32 token, scope, enclosing;
        MonoClass *klass;
 
+#define COMPILE_CORLIB 0
+#if COMPILE_CORLIB
+       /* nasty hack, need to find the proper solution */
+       if (type->type == MONO_TYPE_OBJECT)
+               return TYPEDEFORREF_TYPEDEF | (2 << TYPEDEFORREF_BITS);
+#endif
        token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
        if (token)
                return token;
        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 (klass->image == assembly->assembly.image) {
                MonoReflectionTypeBuilder *tb = klass->reflection_info;
-               return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
+               token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
+               mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass);
+               return token;
        }
 
        if (klass->nested_in) {
@@ -1260,14 +1548,17 @@ mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
                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);
+       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 = TYPEDEFORREF_TYPEREF | (table->next_idx << 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);
        return token;
 }
 
@@ -1296,17 +1587,22 @@ mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoType *type, c
        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;
 
        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 << 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 ++;
 
@@ -1335,12 +1631,91 @@ mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *fi
        token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
        if (token)
                return token;
+       field->parent = klass;
        token = mono_image_get_memberref_token (assembly, &klass->byval_arg, 
                field->name,  fieldref_encode_signature (assembly, field));
        g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
        return token;
 }
 
+static guint32
+mono_reflection_encode_sighelper (MonoDynamicAssembly *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 (MonoDynamicAssembly *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) {
@@ -1388,6 +1763,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;
                }
        }
@@ -1396,7 +1772,7 @@ mono_image_get_array_token (MonoDynamicAssembly *assembly, MonoReflectionArrayMe
        am->sig = sig;
        am->parent = m->parent->type;
        am->token = mono_image_get_memberref_token (assembly, am->parent,
-               name,  method_encode_signature (assembly, sig));
+                       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;
@@ -1411,22 +1787,27 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
 {
        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;
 
@@ -1521,10 +1902,6 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
        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,28 +1919,38 @@ 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) {
        int i;
@@ -1635,6 +2022,10 @@ module_add_cattrs (MonoDynamicAssembly *assembly, MonoReflectionModuleBuilder *m
        
        mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
        
+       /* no types in the module */
+       if (!mb->types)
+               return;
+       
        for (i = 0; i < mono_array_length (mb->types); ++i)
                type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
 }
@@ -1657,23 +2048,6 @@ 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);
-       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.
-        */
-       for (i = 0; i < mono_array_length (mb->types); ++i) {
-               MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
-               assign_type_idx (type, table);
-       }
-       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)\
@@ -1899,14 +2273,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 ();
@@ -1941,6 +2315,8 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *a
        MonoReflectionFieldBuilder *field;
        MonoReflectionCtorBuilder *ctor;
        MonoReflectionMethodBuilder *method;
+       MonoReflectionTypeBuilder *tb;
+       MonoReflectionArrayMethod *am;
        guint32 i, idx;
        unsigned char *target;
 
@@ -1949,10 +2325,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,10 +2342,25 @@ 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")) {
+                               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"))
+                               g_assert_not_reached ();
+                       am = (MonoReflectionArrayMethod*)iltoken->member;
+                       idx = am->table_idx;
+                       break;
                default:
                        g_error ("got unexpected table 0x%02x in fixup", target [3]);
                }
@@ -1974,44 +2370,187 @@ 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.
- */
 static void
-mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
+assembly_add_resource (MonoDynamicAssembly *assembly, MonoReflectionResource *rsrc)
 {
        MonoDynamicTable *table;
-       MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
-       MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
-       guint32 len;
        guint32 *values;
-       char *name;
-       int i;
+       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++;
+               idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
+               offset = 0;
+       } else {
+               char sizebuf [4];
+               offset = mono_array_length (rsrc->data);
+               sizebuf [0] = offset; sizebuf [1] = offset >> 8;
+               sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
+               offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
+               mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
+               idx = 0;
+       }
 
-       table = &assembly->tables [MONO_TABLE_ASSEMBLY];
-       alloc_table (table, 1);
-       values = table->values + MONO_ASSEMBLY_SIZE;
-       values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
-       name = mono_string_to_utf8 (assemblyb->name);
-       values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
+       table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
+       table->rows++;
+       alloc_table (table, table->rows);
+       values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
+       values [MONO_MANIFEST_OFFSET] = 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_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
-       values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
+       values [MONO_MANIFEST_IMPLEMENTATION] = idx;
+       table->next_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;
-       values [MONO_ASSEMBLY_FLAGS] = 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 (MonoString *fname, MonoDynamicAssembly *assembly) {
+       char *name, *content;
+       gsize len;
+       guint32 token = 0;
+
+       if (!fname)
+               return token;
+       name = mono_string_to_utf8 (fname);
+       if (g_file_get_contents (name, &content, &len, NULL)) {
+               char blob_size [6];
+               char *b = blob_size;
+               /* check it's a public key or keypair */
+               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, content, len);
+               g_free (content);
+               /* need to get the actual value from the key type... */
+               assembly->strong_name_size = 128;
+               assembly->strong_name = g_malloc0 (assembly->strong_name_size);
+       }
+       /* FIXME: how do we tell mcs if loading fails? */
+       g_free (name);
+       return token;
+}
+
+/*
+ * 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.
+ */
+void
+mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
+{
+       MonoDynamicTable *table;
+       MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
+       MonoDomain *domain = mono_object_domain (assemblyb);
+       guint32 len;
+       guint32 *values;
+       char *name;
+       int i;
+
+       if (assembly->text_rva)
+               return;
+
+       assembly->text_rva = START_TEXT_RVA;
+
+       table = &assembly->tables [MONO_TABLE_ASSEMBLY];
+       alloc_table (table, 1);
+       values = table->values + MONO_ASSEMBLY_SIZE;
+       values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
+       name = mono_string_to_utf8 (assemblyb->name);
+       values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
+       g_free (name);
+       if (assemblyb->culture) {
+               name = mono_string_to_utf8 (assemblyb->culture);
+               values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
+               g_free (name);
+       } else {
+               values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
+       }
+       values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->keyfile, assembly);
+       values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
+       set_version_from_string (assemblyb->version, values);
+
+       table = &assembly->tables [MONO_TABLE_TYPEDEF];
+       table->rows = 1; /* .<Module> */
+       table->next_idx++;
+       alloc_table (table, table->rows);
+       /*
+        * Set the first entry.
+        */
+       values = table->values + table->columns;
+       values [MONO_TYPEDEF_FLAGS] = 0;
+       values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
+       values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
+       values [MONO_TYPEDEF_EXTENDS] = 0;
+       values [MONO_TYPEDEF_FIELD_LIST] = 1;
+       values [MONO_TYPEDEF_METHOD_LIST] = 1;
 
-       assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
-       assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
+       /* 
+        * handle global methods 
+        * FIXME: test what to do when global methods are defined in multiple modules.
+        */
+       if (assemblyb->modules) {
+               MonoReflectionModuleBuilder *mod = mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, 0);
+               if (mod->global_methods) {
+                       table = &assembly->tables [MONO_TABLE_METHOD];
+                       table->rows += mono_array_length (mod->global_methods);
+                       alloc_table (table, table->rows);
+                       for (i = 0; i < mono_array_length (mod->global_methods); ++i)
+                               mono_image_get_method_info (
+                                       mono_array_get (mod->global_methods, MonoReflectionMethodBuilder*, i), assembly);
+               }
+       }
 
        if (assemblyb->modules) {
                len = mono_array_length (assemblyb->modules);
@@ -2027,22 +2566,37 @@ mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
                table->next_idx ++;
        }
 
-       table = &assembly->tables [MONO_TABLE_TYPEDEF];
+       /* Emit types */
+       if (assemblyb->modules) {
+               /* Collect all types into a list sorted by their table_idx */
+               GPtrArray *types = g_ptr_array_new ();
+
+               len = mono_array_length (assemblyb->modules);
+               for (i = 0; i < len; ++i) {
+                       MonoReflectionModuleBuilder *mb =
+                               mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
+                       if (mb->types)
+                               for (i = 0; i < mono_array_length (mb->types); ++i) {
+                                       MonoReflectionTypeBuilder *type = mono_array_get (mb->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.
         */
-       alloc_table (table, table->rows);
-       /*
-        * Set the first entry.
-        */
-       values = table->values + table->columns;
-       values [MONO_TYPEDEF_FLAGS] = 0;
-       values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
-       values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
-       values [MONO_TYPEDEF_EXTENDS] = 0;
-       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);
 
@@ -2051,11 +2605,9 @@ mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
                for (i = 0; i < len; ++i)
                        module_add_cattrs (assembly, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i));
        }
-       
+
        /* fixup tokens */
        mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
-       
-       build_compressed_metadata (assembly);
 }
 
 /*
@@ -2072,10 +2624,14 @@ mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *s
        char buf [16];
        char *b = buf;
        
+       MONO_ARCH_SAVE_REGS;
+
        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);
+
+       if (assembly->dynamic_assembly->save) {
+               mono_metadata_encode_value (1 | (str->length * 2), b, &b);
+               idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
        {
                char *swapped = g_malloc (2 * mono_string_length (str));
@@ -2089,6 +2645,13 @@ mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *s
        mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
 #endif
        mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
+       }
+       else
+               idx = assembly->dynamic_assembly->us.index ++;
+
+       mono_g_hash_table_insert (assembly->dynamic_assembly->tokens, 
+                                                         GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
+
        return MONO_TOKEN_STRING | idx;
 }
 
@@ -2114,55 +2677,71 @@ mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
        MonoClass *klass;
        guint32 token;
 
-       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;
                /*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;
                /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
-               return token;
        }
-       if (strcmp (klass->name, "FieldBuilder") == 0) {
+       else if (strcmp (klass->name, "FieldBuilder") == 0) {
                MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
-               return mb->table_idx | MONO_TOKEN_FIELD_DEF;
+               token = mb->table_idx | MONO_TOKEN_FIELD_DEF;
        }
-       if (strcmp (klass->name, "TypeBuilder") == 0) {
+       else if (strcmp (klass->name, "TypeBuilder") == 0) {
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
-               return tb->table_idx | MONO_TOKEN_TYPE_DEF;
+               token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
        }
-       if (strcmp (klass->name, "MonoType") == 0) {
+       else if (strcmp (klass->name, "MonoType") == 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, "MonoCMethod") == 0 ||
                        strcmp (klass->name, "MonoMethod") == 0) {
                MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
-               token = mono_image_get_methodref_token (assembly, m->method);
+               if (m->method->klass->image == assembly->assembly.image) {
+                       static guint32 method_table_idx = 0xffffff;
+                       /*
+                        * 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->assembly.image) {
+                       static guint32 field_table_idx = 0xffffff;
+                       field_table_idx --;
+                       token = MONO_TOKEN_FIELD_DEF | field_table_idx;
+               } else
+                       token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
                /*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;
        }
-       g_print ("requested token for %s\n", klass->name);
-       return 0;
+       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);
+
+       mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
+                                                         obj);
+
+       return token;
 }
 
 typedef struct {
@@ -2178,8 +2757,48 @@ typedef struct {
        guint32 flags;
 } MonoILT;
 
+static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
+
+static MonoImage*
+create_dynamic_mono_image (char *assembly_name, char *module_name)
+{
+       MonoImage *image;
+
+       image = g_new0 (MonoImage, 1);
+       
+       /* keep in sync with image.c */
+       image->name = assembly_name;
+       image->assembly_name = image->name; /* they may be different */
+       image->module_name = module_name;
+       image->references = g_new0 (MonoAssembly*, 1);
+       image->references [0] = NULL;
+
+       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->delegate_begin_invoke_cache = 
+               g_hash_table_new ((GHashFunc)mono_signature_hash, 
+                                 (GCompareFunc)mono_metadata_signature_equal);
+       image->delegate_end_invoke_cache = 
+               g_hash_table_new ((GHashFunc)mono_signature_hash, 
+                                 (GCompareFunc)mono_metadata_signature_equal);
+       image->delegate_invoke_cache = 
+               g_hash_table_new ((GHashFunc)mono_signature_hash, 
+                                 (GCompareFunc)mono_metadata_signature_equal);
+
+       image->runtime_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->managed_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->native_wrapper_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->remoting_invoke_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+       image->synchronized_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+       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
@@ -2193,22 +2812,30 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        MonoImage *image;
        int i;
        
+       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);
 #endif
 
+       assembly->assembly.dynamic = assembly;
+       assemblyb->assembly.assembly = (MonoAssembly*)assembly;
        assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+       assembly->method_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
+       assembly->field_to_table_idx = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
        assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
+       assembly->tokens = mono_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);
+       assembly->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
 
        string_heap_init (&assembly->sheap);
        mono_image_add_stream_data (&assembly->us, "", 1);
-       mono_image_add_stream_data (&assembly->blob, "", 1);
+       add_to_blob_cached (assembly, (char*) "", 1, NULL, 0);
        /* 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 */
@@ -2226,19 +2853,16 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
                assembly->tables [i].columns = table_sizes [i];
        }
 
-       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 */
-
-       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);
+       assembly->run = assemblyb->access != 2;
+       assembly->save = assemblyb->access != 1;
 
+       image = create_dynamic_mono_image (mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
+       assembly->assembly.aname.name = image->name;
+       image->assembly = (MonoAssembly*)assembly;
        assembly->assembly.image = image;
-       
+
+       register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
+       mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
 }
 
 static int
@@ -2251,8 +2875,10 @@ 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++;
 
@@ -2278,13 +2904,14 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
        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;
        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,
@@ -2304,6 +2931,16 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
                return;
        
        mono_image_build_metadata (assemblyb);
+
+       if (assemblyb->resources) {
+               int len = mono_array_length (assemblyb->resources);
+               for (i = 0; i < len; ++i)
+                       assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
+       }
+
+       
+       build_compressed_metadata (assembly);
+
        nsections = calc_section_size (assembly);
 
        pefile = &assembly->pefile;
@@ -2359,10 +2996,13 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
        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 */
 
@@ -2397,7 +3037,27 @@ 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 = assemblyb->pekind;
+
+               //
+               // 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 (kind == 2)
+                       kind = 3;
+               else if (kind == 3)
+                       kind = 2;
+               
+               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);
@@ -2432,8 +3092,12 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
        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 - 2);
+       *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);
@@ -2444,8 +3108,19 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
                cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->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 +3141,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->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->assembly.image->raw_metadata);
                        break;
                case MONO_SECTION_RELOC:
                        rva = (guint32*)(pefile->data + assembly->sections [i].offset);
@@ -2506,25 +3194,92 @@ mono_image_create_pefile (MonoReflectionAssemblyBuilder *assemblyb) {
 
 /*
  * 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, MonoImage *module)
+{
+       /* this is done only once */
+       mono_domain_lock (domain);
+       CACHE_OBJECT (module, res, NULL);
+}
+
+void
+mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
+{
+       MonoImage *image = moduleb->module.image;
+       MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
+       if (!image) {
+               if (!ab->modules) {
+                       /* a MonoImage was already created in mono_image_basic_init () */
+                       image = ab->dynamic_assembly->assembly.image;
+               } else {
+                       image = create_dynamic_mono_image (mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.name));
+               }
+               moduleb->module.image = image;
+               register_module (mono_object_domain (moduleb), moduleb, image);
+       }
+}
+
 /*
  * mono_assembly_get_object:
  * @domain: an app domain
@@ -2538,16 +3293,41 @@ 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;
+       
+       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, image->name);
+       res->scopename = mono_string_new (domain, image->module_name);
+
+       CACHE_OBJECT (image, res, NULL);
        return res;
 }
 
+
 static gboolean
 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
 {
@@ -2573,12 +3353,24 @@ 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:
                return t1->data.klass == t2->data.klass;
        case MONO_TYPE_PTR:
+               return mymono_metadata_type_equal (t1->data.type, t2->data.type);
        case MONO_TYPE_SZARRAY:
+retry_sz:
+               if (t1->data.type->type != t2->data.type->type)
+                       return FALSE;
+               if (t1->data.type->type == MONO_TYPE_CLASS || t1->data.type->type == MONO_TYPE_VALUETYPE)
+                       return t1->data.type->data.klass == t2->data.type->data.klass;
+               if (t1->data.type->type == MONO_TYPE_SZARRAY) {
+                       t1 = t1->data.type;
+                       t2 = t2->data.type;
+                       goto retry_sz;
+               }
                return mymono_metadata_type_equal (t1->data.type, t2->data.type);
        case MONO_TYPE_ARRAY:
                if (t1->data.array->rank != t2->data.array->rank)
@@ -2604,10 +3396,10 @@ mymono_metadata_type_hash (MonoType *t1)
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
                /* 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;
 }
@@ -2625,20 +3417,27 @@ 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 (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 +3445,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 +3460,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 +3473,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 +3493,12 @@ 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);
+       CACHE_OBJECT (field, res, klass);
        return res;
 }
 
@@ -2713,12 +3517,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 +3541,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;
 }
 
@@ -2766,17 +3570,18 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
        if (!method->signature->param_count)
                return NULL;
 
-       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));
+       CHECK_OBJECT (MonoReflectionParameter**, &(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);
+       
        oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
 #if HAVE_BOEHM_GC
-       res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
+       res = GC_MALLOC (sizeof (MonoReflectionParameter*) * method->signature->param_count);
 #else
        res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
 #endif
@@ -2790,10 +3595,97 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
                res [i]->AttrsImpl = method->signature->params [i]->attrs;
        }
        g_free (names);
-       CACHE_OBJECT (&(method->signature), res);
+       CACHE_OBJECT (&(method->signature), res, NULL);
        return res;
 }
 
+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 = "";
+       
+       while (*p && (isalnum (*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' && strncmp (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;
+               } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
+                       p += 8;
+                       if (strncmp (p, "neutral", 7) == 0) {
+                               assembly->culture = "";
+                               p += 7;
+                       } else {
+                               assembly->culture = p;
+                               while (*p && *p != ',') {
+                                       p++;
+                               }
+                       }
+               } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
+                       p += 15;
+                       s = p;
+                       while (*s && isxdigit (*s)) {
+                               *s = tolower (*s);
+                               s++;
+                       }
+                       assembly->hash_len = s - p;
+                       if (!(s-p) || ((s-p) & 1))
+                               return 1;
+                       assembly->hash_value = s = p;
+                       while (*s && isxdigit (*s)) {
+                               int val;
+                               val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
+                               s++;
+                               *p = val << 4;
+                               *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
+                               p++;
+                       }
+                       p = s;
+               } 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 +3706,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 +3719,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 +3752,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 +3802,13 @@ 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:
                        break;
                }
-               if (info->assembly)
+               if (info->assembly.name)
                        break;
        }
        *w = 0; /* terminate class name */
@@ -2985,17 +3876,8 @@ mono_type_get_name (MonoType *type)
        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;
@@ -3045,86 +3927,308 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
                }
                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
+ *
+ * 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)
+{
+       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;
-               }
-               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;
+       type = mono_reflection_get_type_internal (image, info, ignorecase);
+       if (type)
+               return type;
+       if (!mono_domain_has_type_resolve (mono_domain_get ()))
+               return NULL;
+       
+       // 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 && (!image || (assembly->assembly->image == image)))
+               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;
+       
+       /*g_print ("requested type %s\n", str);*/
+       if (!mono_reflection_parse_type (name, &info)) {
+               g_list_free (info.modifiers);
+               g_list_free (info.nested);
+               return NULL;
+       }
+
+       if (info.assembly.name) {
+               image = mono_image_loaded (info.assembly.name);
+               /* do we need to load if it's not already loaded? */
+               if (!image) {
+                       g_list_free (info.modifiers);
+                       g_list_free (info.nested);
+                       return NULL;
                }
+       } else if (image == NULL) {
+               image = mono_defaults.corlib;
+       }
+
+       type = mono_reflection_get_type (image, &info, FALSE);
+       if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
+               image = mono_defaults.corlib;
+               type = mono_reflection_get_type (image, &info, FALSE);
+       }
+       
+       g_list_free (info.modifiers);
+       g_list_free (info.nested);
+       return type;
+}
+
+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;
+               return mono_type_get_object (mono_domain_get (), t);
+       }
+       case MONO_TYPE_OBJECT: {
+               char subt = *p++;
+               MonoObject *obj;
+               MonoClass *subc;
+               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;
+               alen = read32 (p);
+               p += 4;
+               if (alen == 0xffffffff) {
+                       *end = p;
+                       return NULL;
                }
+               arr = mono_array_new (mono_domain_get(), mono_class_from_mono_type (t->data.type), alen);
+               switch (t->data.type->type)
+               {
+                       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_STRING:
+                               for (i = 0; i < alen; i++) {
+                                       MonoObject *item = load_cattr_value (image, t->data.type, 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 +4236,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 +4299,273 @@ 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;
+
+       if (len < 2 || read16 (p) != 0x0001) /* Prolog */
+               return NULL;
+
+       mono_class_init (method->klass);
+       /*g_print ("got attr %s\n", method->klass->name);*/
+       
+       params = g_new (void*, method->signature->param_count);
+
+       /* 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;
+                       if ((unsigned char) *named == 0x80) /* no idea what this is, but it looks optional */
+                               named++;
+                       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 */
+               }
+               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];
+       /* the table is not sorted */
+       for (i = 0; i < ca->rows; ++i) {
+               if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
+                       continue;
+               list = g_list_prepend (list, GUINT_TO_POINTER (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] >> 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;
+               }
+               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 <<= CUSTOM_ATTR_BITS;
+       idx |= 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 <<= CUSTOM_ATTR_BITS;
+       idx |= 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 <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_ASSEMBLY;
+       return mono_custom_attrs_from_index (assembly->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 <<= CUSTOM_ATTR_BITS;
+       idx |= 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 <<= CUSTOM_ATTR_BITS;
+       idx |= 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 <<= CUSTOM_ATTR_BITS;
+       idx |= 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;
+       
+       /* FIXME: handle dynamic custom attrs for parameters */
+       /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
+               return cinfo;*/
+       image = method->klass->image;
+       method_index = find_method_index (method);
+       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 = 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 <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_PARAMDEF;
+       return mono_custom_attrs_from_index (image, idx);
+}
+
 /*
  * mono_reflection_get_custom_attrs:
  * @obj: a reflection object handle
@@ -3224,158 +4576,91 @@ 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;
        
+       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 ("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->klass, 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->klass, 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->klass, 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);
+       } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
+               MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
+               cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->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);
+       } 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;
+       return sig;
+}
+
 static void
 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
 {
@@ -3416,13 +4701,13 @@ type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
        MonoAssembly *ta;
 
        name = mono_type_get_name (type);
-       klass = mono_class_from_mono_type (type);
+       klass = my_mono_class_from_mono_type (type);
        ta = klass->image->assembly;
        if (ta == ass || klass->image == mono_defaults.corlib)
                return name;
 
        /* missing public key */
-       result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s", 
+       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");
@@ -3479,8 +4764,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,8 +4789,15 @@ handle_enum:
        case MONO_TYPE_CLASS: {
                char *str;
                guint32 slen;
-               if (!mono_object_isinst (arg, mono_defaults.monotype_class))
-                       g_error ("only types allowed");
+               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);
 handle_type:
                str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
                slen = strlen (str);
@@ -3517,6 +4815,27 @@ handle_type:
                g_free (str);
                break;
        }
+       case MONO_TYPE_SZARRAY: {
+               int len, i;
+               MonoClass *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 = mono_class_from_mono_type (type)->element_class;
+               for (i = 0; i < len; ++i) {
+                       encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
+               }
+               break;
+       }
        /* it may be a boxed value or a Type */
        case MONO_TYPE_OBJECT: {
                MonoClass *klass = mono_object_class (arg);
@@ -3528,6 +4847,10 @@ 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;
@@ -3572,25 +4895,29 @@ 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 (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);
+               arg = mono_array_get (ctorArgs, MonoObject*, i);
                encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
        }
        i = 0;
@@ -3610,6 +4937,29 @@ 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 */
+                       if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
+                               char *str = type_get_qualified_name (ptype, 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 (ptype->type, p, &p);
+                       }
                        len = strlen (pname);
                        mono_metadata_encode_value (len, p, &p);
                        memcpy (p, pname, len);
@@ -3629,6 +4979,29 @@ 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);
+                       }
                        len = strlen (fname);
                        mono_metadata_encode_value (len, p, &p);
                        memcpy (p, fname, len);
@@ -3662,13 +5035,20 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 {
        MonoClass *klass, *parent;
 
+       MONO_ARCH_SAVE_REGS;
+
        klass = g_new0 (MonoClass, 1);
 
        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;
        
        klass->inited = 1; /* we lie to the runtime */
@@ -3680,16 +5060,38 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        klass->element_class = klass;
        klass->reflection_info = tb; /* need to pin. */
 
+       /* 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->assemblyb->dynamic_assembly->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;
+       }
        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);*/
 }
 
@@ -3704,7 +5106,9 @@ 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;
@@ -3715,8 +5119,359 @@ 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);
+               klass->instance_size = klass->element_class->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 MonoMethod*
+reflection_methodbuilder_to_mono_method (MonoClass *klass,
+                                                                                ReflectionMethodBuilder *rmb,
+                                                                                MonoMethodSignature *sig)
+{
+       MonoMethod *m;
+       MonoMethodNormal *pm;
+
+       if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+           (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+               m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 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;
+       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->addr = mono_lookup_internal_call (m);
+               m->signature->pinvoke = 1;
+       } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+               /* TODO */
+               m->signature->pinvoke = 1;
+               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 (klass->image->assembly->dynamic,
+                                                                                                        rmb->ilgen,
+                                                                                                        num_clauses);
+               }
+
+               pm->header = header;
+       }
+
+       return m;
+}      
+
+static MonoMethod*
+ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
+{
+       ReflectionMethodBuilder rmb;
+       const char *name;
+       MonoMethodSignature *sig;
+
+       name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
+
+       sig = ctor_builder_to_signature (mb);
+
+       rmb.ilgen = mb->ilgen;
+       rmb.parameters = mb->parameters;
+       rmb.pinfo = mb->pinfo;
+       rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
+       rmb.iattrs = mb->iattrs;
+       rmb.call_conv = mb->call_conv;
+       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.code = NULL;
+
+       mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+       mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+       if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->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);
+
+       rmb.ilgen = mb->ilgen;
+       rmb.parameters = mb->parameters;
+       rmb.pinfo = mb->pinfo;
+       rmb.attrs = mb->attrs;
+       rmb.iattrs = mb->iattrs;
+       rmb.call_conv = mb->call_conv;
+       rmb.type = mb->type;
+       rmb.name = mb->name;
+       rmb.table_idx = &mb->table_idx;
+       rmb.init_locals = mb->init_locals;
+       rmb.code = mb->code;
+
+       mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+       mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+       if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
+               /* ilgen is no longer needed */
+               mb->ilgen = NULL;
+       }
+       return mb->mhandle;
+}
+
+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->methods? mono_array_length (tb->methods): 0;
+       klass->method.count = num;
+       klass->methods = g_new (MonoMethod*, num);
+       num = tb->ctors? mono_array_length (tb->ctors): 0;
+       for (i = 0; i < num; ++i)
+               klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
+       num = tb->methods? mono_array_length (tb->methods): 0;
+       j = i;
+       for (i = 0; i < num; ++i)
+               klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
+
+       klass->wastypebuilder = TRUE;
+       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 < mono_array_length (tb->methods); ++i) {
+                       MonoReflectionMethodBuilder *mb = 
+                               mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+                       if (mb->override_method)
+                               onum ++;
+               }
+       }
+
+       overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
+
+       if (tb->methods) {
+               onum = 0;
+               for (i = 0; i < mono_array_length (tb->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);
+}
+
+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->fields? mono_array_length (tb->fields): 0;
+       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) {
+                       field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+                       MonoDynamicAssembly *assembly = klass->image->assembly->dynamic;
+                       field->def_value = g_new0 (MonoConstant, 1);
+                       idx = encode_constant (assembly, fb->def_value, &field->def_value->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->def_value->value = g_malloc (len);
+                       memcpy (field->def_value->value, p, len);
+               }
+       }
+       mono_class_layout_fields (klass);
+}
+
+MonoReflectionType*
+mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
+{
+       MonoClass *klass;
+       MonoReflectionType* res;
+
+       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.
+        * nested_classes
+        * properties
+        * events
+        */
+       klass->flags = tb->attrs;
+       klass->element_class = klass;
+
+       if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->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);
+
+       /* 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);
+
+       /* FIXME: properties */
+
+       res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+       /* with enums res == tb: need to fix that. */
+       if (!klass->enumtype)
+               g_assert (res != (MonoReflectionType*)tb);
+       return res;
 }
 
 MonoArray *
@@ -3728,6 +5483,8 @@ mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
        MonoArray *result;
        char *buf, *p;
 
+       MONO_ARCH_SAVE_REGS;
+
        p = buf = g_malloc (10 + na * 10);
 
        mono_metadata_encode_value (0x07, p, &p);
@@ -3755,6 +5512,8 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
        MonoArray *result;
        char *buf, *p;
 
+       MONO_ARCH_SAVE_REGS;
+
        p = buf = g_malloc (10 + na * 10);
 
        mono_metadata_encode_value (0x06, p, &p);
@@ -3772,3 +5531,133 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
        return result;
 }
 
+gpointer
+mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
+{
+       MonoDynamicAssembly *assembly = image->assembly->dynamic;
+       MonoObject *obj;
+       gpointer result;
+
+       obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
+       g_assert (obj);
+
+       if (strcmp (obj->vtable->klass->name, "String") == 0) {
+               result = 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;
+}
+
+
+
+