Made message fit in 80 cols without wrapping, fixed typo too.
[mono.git] / mono / metadata / reflection.c
index 0afdb746ffd8548c59fcbbacf922bad9bca35b3e..b10f09ca78ff8e70924e9bbfddf27f99901f8a52 100644 (file)
@@ -213,7 +213,6 @@ encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endb
                mono_metadata_encode_value (type->type, p, &p);
                break;
        case MONO_TYPE_PTR:
-               g_print ("encode pointer\n");
        case MONO_TYPE_SZARRAY:
                mono_metadata_encode_value (type->type, p, &p);
                encode_type (assembly, type->data.type, p, &p);
@@ -490,7 +489,7 @@ fat_header:
                                        mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
                                }
                        } else {
-                               g_error ("No clauses");
+                               g_error ("No clauses for ex info block %d", i);
                        }
                }
        }
@@ -826,6 +825,9 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *
        guint32 *values;
        char *name;
 
+       /* maybe this fixup should be done in the C# code */
+       if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
+               fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
        table = &assembly->tables [MONO_TABLE_FIELD];
        fb->table_idx = table->next_idx ++;
        values = table->values + fb->table_idx * MONO_FIELD_SIZE;
@@ -1023,7 +1025,7 @@ resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
        guint32 *values;
        guint32 cols [MONO_ASSEMBLY_SIZE];
 
-       if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, image))))
+       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);
@@ -1048,10 +1050,51 @@ resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
 
        token <<= RESOLTION_SCOPE_BITS;
        token |= RESOLTION_SCOPE_ASSEMBLYREF;
-       g_hash_table_insert (assembly->typeref, image, GUINT_TO_POINTER (token));
+       g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
        return token;
 }
 
+static guint32
+create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
+{
+       MonoDynamicTable *table;
+       guint32 *values;
+       guint32 token;
+       char sig [128];
+       char *p = sig;
+       char blob_size [6];
+       char *b = blob_size;
+
+       switch (type->type) {
+       case MONO_TYPE_FNPTR:
+       case MONO_TYPE_PTR:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:
+               encode_type (assembly, type, p, &p);
+               break;
+       default:
+               return 0;
+       }
+       
+       g_assert (p-sig < 128);
+       mono_metadata_encode_value (p-sig, b, &b);
+       token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
+       mono_image_add_stream_data (&assembly->blob, sig, p-sig);
+
+       table = &assembly->tables [MONO_TABLE_TYPESPEC];
+       alloc_table (table, table->rows + 1);
+       values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
+       values [MONO_TYPESPEC_SIGNATURE] = token;
+
+       token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
+       g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
+       table->next_idx ++;
+       return token;
+}
+
+/*
+ * Despite the name, we handle also TypeSpec (with the above helper).
+ */
 static guint32
 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
 {
@@ -1061,6 +1104,9 @@ mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
        MonoClass *klass;
 
        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);
@@ -1131,12 +1177,12 @@ mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *metho
 {
        guint32 token;
        
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, method));
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
        if (token)
                return token;
        token = mono_image_get_memberref_token (assembly, method->klass, 
                method->name,  method_encode_signature (assembly, method->signature));
-       g_hash_table_insert (assembly->typeref, method, GUINT_TO_POINTER(token));
+       g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
        return token;
 }
 
@@ -1145,12 +1191,12 @@ mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *fi
 {
        guint32 token;
        
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, field));
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
        if (token)
                return token;
        token = mono_image_get_memberref_token (assembly, klass, 
                field->name,  fieldref_encode_signature (assembly, field));
-       g_hash_table_insert (assembly->typeref, field, GUINT_TO_POINTER(token));
+       g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
        return token;
 }
 
@@ -1315,7 +1361,12 @@ mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *m
        name = mono_string_to_utf8 (mb->module.name);
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
        g_free (name);
-       /* need to set mvid? */
+       i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
+       i /= 16;
+       ++i;
+       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;
 
        mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
        /*
@@ -1615,6 +1666,7 @@ mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
        values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
        values [MONO_ASSEMBLY_REV_NUMBER] = 0;
        values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
+       values [MONO_ASSEMBLY_FLAGS] = 0;
 
        mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
 
@@ -1773,7 +1825,8 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
 #endif
 
        assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
-       assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
+       assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
+       assembly->typeref = g_hash_table_new (mono_metadata_type_hash, mono_metadata_type_equal);
 
        string_heap_init (&assembly->sheap);
        mono_image_add_stream_data (&assembly->us, "", 1);
@@ -1799,6 +1852,19 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
        
 }
 
+typedef struct {
+       guint32 import_lookup_table;
+       guint32 timestamp;
+       guint32 forwarder;
+       guint32 name_rva;
+       guint32 import_address_table_rva;
+} MonoIDT;
+
+typedef struct {
+       guint32 name_rva;
+       guint32 flags;
+} MonoILT;
+
 /*
  * mono_image_get_heade:
  * @assemblyb: an assembly builder object
@@ -1816,11 +1882,15 @@ mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, i
 {
        MonoMSDOSHeader *msdos;
        MonoDotNetHeader *header;
-       MonoSectionTable *section;
+       MonoSectionTable *section, *reloc;
        MonoCLIHeader *cli_header;
        guint32 header_size =  TEXT_OFFSET + CLI_H_SIZE;
        MonoDynamicAssembly *assembly;
+       MonoIDT import_directory;
+       MonoILT import_lookup;
 
+       static const guchar entrycode [16] = {0xff, 0x25, 0};
+       guint32 entry_offset, import_table_offset, import_hint_offset;
        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,
@@ -1840,6 +1910,41 @@ mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, i
 
        mono_image_build_metadata (assemblyb);
 
+       memset (&import_directory, 0, sizeof (MonoIDT));
+       assembly->code.index += 3;
+       assembly->code.index &= ~3;
+       import_table_offset = TEXT_OFFSET + CLI_H_SIZE + assembly->code.index;
+       /* calc rva... */
+       import_hint_offset = import_table_offset + 40 + 8;
+       import_hint_offset += 15;
+       import_hint_offset &= ~15;
+
+       import_directory.import_lookup_table = import_table_offset + 40;
+       import_directory.name_rva = import_hint_offset + 14;
+       import_directory.import_address_table_rva = 0x200; /* FIXME */
+
+       mono_image_add_stream_data (&assembly->code, (char*)&import_directory, sizeof (MonoIDT));
+       /* add an empty item to mark the end */
+       memset (&import_directory, 0, sizeof (MonoIDT));
+       mono_image_add_stream_data (&assembly->code, (char*)&import_directory, sizeof (MonoIDT));
+       
+       memset (&import_lookup, 0, sizeof (MonoILT));
+       import_lookup.name_rva = import_hint_offset;
+       mono_image_add_stream_data (&assembly->code, (char*)&import_lookup, sizeof (MonoILT));
+       assembly->code.index += 15;
+       assembly->code.index &= ~15;
+       mono_image_add_stream_data (&assembly->code, "", 1);
+       mono_image_add_stream_data (&assembly->code, "", 1);
+       mono_image_add_stream_data (&assembly->code, "_CorExeMain", 12);
+       mono_image_add_stream_data (&assembly->code, "mscoree.dll", 12);
+       mono_image_add_stream_data (&assembly->code, "", 1); /* lame */
+       mono_image_add_stream_data (&assembly->code, "", 1);
+       mono_image_add_stream_data (&assembly->code, "", 1);
+       mono_image_add_stream_data (&assembly->code, "", 1);
+
+       entry_offset = mono_image_add_stream_data (&assembly->code, entrycode, sizeof (entrycode));
+       /*g_print ("ep offset: 0x%08x\n", entry_offset);*/
+       
        memset (buffer, 0, header_size);
        memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
 
@@ -1855,7 +1960,7 @@ mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, i
        header->pesig [2] = header->pesig [3] = 0;
 
        header->coff.coff_machine = 0x14c;
-       header->coff.coff_sections = 1; /* only .text supported now */
+       header->coff.coff_sections = 2; /* only .text and .reloc supported now */
        header->coff.coff_time = time (NULL);
        header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
        /* it's an exe */
@@ -1865,7 +1970,7 @@ mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, i
        header->pe.pe_magic = 0x10B;
        header->pe.pe_major = 6;
        header->pe.pe_minor = 0;
-       /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
+       /* set later: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
 
        header->nt.pe_image_base = 0x400000;
        header->nt.pe_section_align = 8192;
@@ -1896,13 +2001,26 @@ mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, i
 
        /* Write section tables */
        strcpy (section->st_name, ".text");
-       section->st_virtual_address = START_TEXT_RVA;
-       section->st_virtual_size = assembly->meta_size +  assembly->code.index;
+       section->st_virtual_address = assembly->text_rva;
+       section->st_virtual_size = assembly->meta_size + assembly->code.index;
        section->st_raw_data_size = section->st_virtual_size + (FILE_ALIGN - 1);
        section->st_raw_data_size &= ~(FILE_ALIGN - 1);
        section->st_raw_data_ptr = TEXT_OFFSET;
        section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
 
+       reloc = section + 1;
+       strcpy (reloc->st_name, ".reloc");
+       reloc->st_virtual_address = section->st_virtual_address + section->st_raw_data_size;
+       reloc->st_virtual_size = 12;
+       reloc->st_raw_data_size = reloc->st_virtual_size + (FILE_ALIGN - 1);
+       reloc->st_raw_data_size &= ~(FILE_ALIGN - 1);
+       reloc->st_raw_data_ptr = section->st_raw_data_ptr + section->st_raw_data_size;
+       reloc->st_flags = SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
+       
+
+       header->pe.pe_code_size = section->st_raw_data_size;
+       header->pe.pe_rva_entry_point = TEXT_OFFSET + CLI_H_SIZE + entry_offset;
+
        /* 
         * align: build_compressed_metadata () assumes metadata is aligned 
         * see below:
@@ -2093,6 +2211,7 @@ 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);
        return ret;
 }
@@ -2685,7 +2804,7 @@ mono_reflection_get_custom_attrs (MonoObject *obj)
                idx = find_method_index (rmethod->method);
                idx <<= CUSTOM_ATTR_BITS;
                idx |= CUSTOM_ATTR_METHODDEF;
-               image = method->klass->image;
+               image = rmethod->method->klass->image;
        } else if (strcmp ("ParameterInfo", klass->name) == 0) {
                MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
@@ -2770,6 +2889,24 @@ mono_reflection_get_custom_attrs (MonoObject *obj)
        return result;
 }
 
+static MonoMethodSignature*
+ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
+       MonoMethodSignature *sig;
+       int count, i;
+
+       count = ctor->parameters? mono_array_length (ctor->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);
+               sig->params [i] = pt->type;
+       }
+       return sig;
+}
+
 /*
  * mono_reflection_get_custom_attrs_blob:
  * @ctor: custom attribute constructor
@@ -2792,21 +2929,15 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo
        guint32 buflen, i, type;
 
        if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
-               g_warning ("ConstructorBuilder Custom attribute not yet supported");
-               /* 
-                * maybe we should have a param array to method signature function and
-                * continue with the normal codepath.
-                */
-               result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
-               mono_array_set (result, char, 0, 1);
-               return result;
+               sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
+       } else {
+               sig = ((MonoReflectionMethod*)ctor)->method->signature;
        }
        buflen = 256;
        p = buffer = g_malloc (buflen);
        /* write the prolog */
        *p++ = 1;
        *p++ = 0;
-       sig = ((MonoReflectionMethod*)ctor)->method->signature;
        /* FIXME: ENOENDIAN */
        for (i = 0; i < sig->param_count; ++i) {
                if ((p-buffer) + 10 >= buflen) {
@@ -2889,6 +3020,8 @@ handle_enum:
        p = mono_array_addr (result, char, 0);
        memcpy (p, buffer, buflen);
        g_free (buffer);
+       if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
+               g_free (sig);
        return result;
 }